FirelyTeam / firely-cql-sdk

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

Return types for some functions are wrong in the ELM compiler #508

Open EvanMachusak opened 2 months ago

EvanMachusak commented 2 months ago
define public function Power(argument System.Decimal, exponent System.Decimal) returns System.Decimal:
  case 
    when argument is null or exponent is null then null as System.Decimal
    when Equal(exponent, 0) then 1
    else 
      from (from (Expand(Interval[1,exponent], 1 '1')) _ return argument) a
        aggregate Result starting 1: Result * a
  end

Java cql-to-elm identifies this function as returning System.Decimal .NET cql-to-elm identifies this function as returning System.Decimal

The outputted C# code identifies this as returning object:

        [CqlDeclaration("Power")]
        public virtual object Power(decimal? argument, decimal? exponent)
        {
            object a_()
            {
                bool b_()
                {
                    decimal? c_ = context.Operators.ConvertIntegerToDecimal(0);
                    bool? d_ = this.Equal(exponent, c_);

                    return (d_ ?? false);
                }
;
                if ((context.Operators.Or((bool?)(argument is null), (bool?)(exponent is null)) ?? false))
                {
                    return (null as decimal?);
                }
                else if (b_())
                {
                    return 1;
                }
                else
                {
                    decimal? e_ = context.Operators.ConvertIntegerToDecimal(1);
                    CqlInterval<decimal?> f_ = context.Operators.Interval(e_, exponent, true, true);
                    CqlQuantity g_ = context.Operators.Quantity(1m, "1");
                    IEnumerable<decimal?> h_ = this.Expand(f_, g_);
                    decimal? i_(decimal? _) => 
                        argument;
;
                    IEnumerable<decimal?> j_ = context.Operators.Select<decimal?, decimal?>(h_, i_);
                    decimal? k_(decimal? Result, decimal? a)
                    {
                        decimal? n_ = context.Operators.Multiply(Result, a);

                        return n_;
                    }
;
                    decimal? m_ = context.Operators.Aggregate<decimal?, decimal?>(j_, k_, e_);

                    return m_;
                }
            }
;

            return a_();
        }

Related, semicolons are appearing on the line after the closing } after a lambda.

EvanMachusak commented 2 months ago

.NET is picking up the return type as Choice<Integer,Decimal> because of this case:

Equal(exponent, 0) then 1

(should be Equal(exponent, 0) then 1.0)

Because of the returns statement in the function it resolves this to System.Decimal, but doesn't wrap the Case with an As. The Java ELM also does not generate an As.

Seems ExpressionBuilder should invoke a ChangeType when the function explicitly declares a return type.