Exemplo n.º 1
0
        /// <inheritdoc/>
        public bool TryCompile(IReadOnlyList <MathExpression> arguments, ICompilationContext <object?> ctx, ITypeHintHandler hintHandler, [MaybeNullWhen(false)] out Expression expr)
        {
            if (arguments.Count != 3)
            {
                expr = null;
                return(false);
            }

            var condition = hintHandler.TransformWithHint(arguments.First(), typeof(bool), ctx);

            var        hint = hintHandler.CurrentHint(ctx);
            Expression?thenExpr = null, elseExpr = null;
            Type?      convertAllTo, lastThen, lastElse;

            do
            {
                lastThen = thenExpr?.Type;
                lastElse = elseExpr?.Type;
                thenExpr = hintHandler.TransformWithHint(arguments[1], hint, ctx);
                elseExpr = hintHandler.TransformWithHint(arguments[2], hint, ctx);

                var allTypes = new[] { thenExpr.Type, elseExpr.Type };
                convertAllTo = allTypes
                               .OrderByDescending(CompilerHelpers.EstimateTypeSize)
                               .Where(ty => allTypes.All(t => CompilerHelpers.HasConversionPathTo(t, ty)))
                               .FirstOrDefault(); // biggest one
            }while (thenExpr.Type != elseExpr.Type && thenExpr.Type != convertAllTo &&
                    lastThen != thenExpr.Type && lastElse != elseExpr.Type);

            if (convertAllTo == null)
            {
                throw new ArgumentException("True and False branches of condition do not have a common type to be converted to");
            }

            expr = Expression.Condition(CompilerHelpers.AsBoolean(condition),
                                        CompilerHelpers.ConvertToType(thenExpr, convertAllTo),
                                        CompilerHelpers.ConvertToType(elseExpr, convertAllTo));
            return(true);
        }