Disabling Validate's static type checking

Ugh. I think this is that bug in Validate rearing its ugly head again... If you download and push the form thru XLSForm Offline - and disable the validate check - it will convert to XML fine.

As I has to with this, I'll see if I can come up with a workaround to fake out Validate, and will re-post a new form if/when I do...

@ln, @ggalmazor would you be willing to discuss disabling - or at least reducing to just a warning - Validates static type checking analysis on the next TSC call. I think trying to perform type checking by statically evaluating XPath expressions without actually instantiating any variables is fundamentally flawed, and prone to error. And I dont see any way of fixing it - you can't reliably determine the type of XPath sub-expressions without fully evaluating them at runtime.

I moved this from its original Support thread where the issue came up (again).

Basically, Validate performs a static evaluation of Xpath expressions in a form upon trying to convert a form to XML. The problem is, because its static, any variables in the expression (or subexpressions) are not instantiated and therefore all treated a NULL (!), which depending on how these are used in the calculation can result in a type-mismatch in other various parts of the XPath calculation, even though at runtime everything is perfectly fine.

I think performing a preliminary static type check analysis can be somewhat useful in picking up silly mistakes, but I don't think this should result in fatal errors as it does today - basically preventing converting valid forms.

This probably could do with a TSC discussion, since its a non-trivial change in Validate's behavior.

I can reproduce the related issue.

It's no secret that I love typed languages. I think they help make fewer mistakes and that types are a great source of information and context when trying to understand something.

I'd expect that <bind> types should always have precedence over any calculate expression's value. That's why I don't like ambiguous type declarations like select (should be string, because a value from a select field will always be a string).

Having said that, I'd expect that, if I declare a <bind> like this one:

<bind nodeset="/weekyear/first_day_of_year" 
  type="date" 
  calculate="concat(format-date(/weekyear/date, '%Y'), '-01-01')"/>

Then, /weekyear/first_day_of_year should contain a date value (not string, or anything else). If that were true, then Validate would not complain about the next <bind>'s calculate expression:

<bind nodeset="/weekyear/first_day_of_year_decimal" 
  type="int" 
  calculate="decimal-date-time(/weekyear/first_day_of_year)"/>

All the types match in the previous examples, but Validate will still be confused about the second <bind> because it's looking to the calculate's value instead of the <bind>'s type.

Instead of relaxing the static type checks, we could do a couple of things:

  • Explore the idea of following the types declared in <bind>s

  • Lacking of that, maybe create a new function that will take a formatted string and return a date value, so that we can use it like this:

    <bind nodeset="/weekyear/first_day_of_year" 
      type="date" 
      calculate="to_date(concat(format-date(/weekyear/date, '%Y'), '-01-01'))"/>
    
1 Like

I think the issue is more fundamental: IMO Validate is attempting to perform the equivalent of compile-time static type checking of (XPath) expression operands, whereas in reality XPath is (merely) an interpreted language [for lack of a better description] whose operand types are dynamically type cast - at runtime - to accommodate whatever current operator is being evaluated. This is typically accomplished by implicitly wrapping operators/arguments in the XPath primitives string(), number(), boolean(). The rules for these casts/conversions are quite explicit in the XPath spec, as are the consequences when (at runtime) the XPath processor finds it cant convert the underlying value; eg NaN.

I dont think this dynamic type-casting is necessarily flawed in any way, its just the way XPath works, and we should probably embrace it.

So I dont think we should introduce, and make users now include, entirely new XPath functions (eg to_date()) which are redundant in terms of contributing anything to the calculation result, just to satisfy Validate's desire for everything to be statically typed [sic]. That feels like trying to force a square peg into a round hole... :slight_smile: [and if we were to go down that path, arguably Validate should never permit NaNs to crop up either! :stuck_out_tongue: ]

I'd expect that types should always have precedence over any calculate expression's value.
...
Explore the idea of following the types declared in bind's

But that's simply not how XPath works. And I dont think we want to attempt to rewrite XPath to accommodate.

In order for Validate to be 100% accurate in its determination of validity, it must evaluate all XPath expressions within the same scope and following the same process as prescribed (proscribed?) for evaluating Xpath expressions, which involves type-casting operator arguments at runtime according to their current value. And I fundamentally see no way Validate can do so treating all variables as NULL during its static analysis.

Again, I think Validate's intentions are truly noble, and indeed very useful in providing form writers a quick preliminary check that their calculations aren't obviously syntactically broken. But it cant through static analysis determine what will/not in fact work at runtime (ie logic errors). So it should really be treated as a warning, and not a fatal, blocking error as it is presently.

That's why I don't like ambiguous type declarations like select (should be string, because a value from a select field will always be a string).

[At the risk of digressing completely from the topic at hand...] I totally agree. And disagree!. IMO the binding type of a select shouldn't be "select1", or even "string" for that matter; it should in fact be whatever type of value you are selecting, which could be a string ("Banana"), a number ("1") or even a date ("2019-11-20"). And the situation is even worse when it comes to select-multi, which should really be an array - of a basic type - neither of which we have anything in XForms presently to leverage. But I'll save that soapbox for another thread/time... :slight_smile: