FirelyTeam / firely-cql-sdk

BSD 3-Clause "New" or "Revised" License
30 stars 18 forks source link

Unclear whether promotion influences the in/as/cast as behaviour. #82

Open ewoutkramer opened 12 months ago

ewoutkramer commented 12 months ago

The CQL spec never explicitly states that the arguments to is/as/cast as are exempt from automatic promotion/demotion, although it probably makes sense (and would be consistent with the behaviour of, say, the C# as and is, which also will not do implicit conversions).

Trying to reverse engineer the Java engines behaviour I noticed this:

// This works
define "y": {true} is Boolean

// This does not
define "z": {true} as Boolean

which leads me to think that in the Java engine promotion does apply to the is operator, but not to the as, which seems inconsistent to me. ("So some x is of type Y but I cannot actually cast it to Y?").

EvanMachusak commented 12 months ago

This is related to these two optional command arguments:

disable-list-demotion |   | Disables demotion of list-valued expressions to singletons -- | -- | -- disable-list-promotion |   | Disables promotion of singletons to list-valued expressions

By default list demotion & promotion is enabled in the command line tool.

Fundamentally, these command line features act as implicit cast operators.

In C#, the is and as keywords do not invoke implicit conversion operators, for good reason.

It is imperative that CQL give you an ability to determine at runtime what an object actually is. For example, consider this code:

define function "What is this?"(any System.Any):
  case
    when any is System.Boolean then ...
    when any is List<System.Boolean> then...
  else ...

If implicit conversion operators are allowed to apply to operands of the is operator, this code becomes non-deterministic, because the case operator does not demand that the when statements be evaluated in the order they appear.

If anything, I'd expect the opposite behavior. is should never invoke an implicit conversion, but as could.