コード例 #1
0
        /// <summary>
        /// Reduces the expression node to a simpler expression.
        /// </summary>
        /// <returns>The reduced expression.</returns>
        public override Expression Reduce()
        {
            if (IsLifted)
            {
                if (Helpers.IsAlwaysNull(Operand))
                {
                    return(Expression.Default(Type));
                }

                if (Helpers.IsNeverNull(Operand))
                {
                    // CONSIDER: Peek into Operand and try to extract non-null value.

                    return
                        (Expression.Convert(
                             MakeFromEnd(Helpers.MakeNullableGetValueOrDefault(Operand)),
                             Type
                             ));
                }

                if (Operand is ParameterExpression i)
                {
                    return(MakeLiftedFromEnd(i));
                }
                else
                {
                    var temp = Expression.Parameter(Operand.Type, "__t");

                    return
                        (Expression.Block(
                             new[] { temp },
                             Expression.Assign(temp, Operand),
                             MakeLiftedFromEnd(temp)
                             ));
                }
            }
            else
            {
                return(MakeFromEnd(Operand));
            }

            Expression MakeLiftedFromEnd(ParameterExpression operand) =>
            Expression.Condition(
                Helpers.MakeNullableHasValue(operand),
                Expression.Convert(
                    MakeFromEnd(Helpers.MakeNullableGetValueOrDefault(operand)),
                    Type
                    ),
                Expression.Default(Type)
                );

            Expression MakeFromEnd(Expression operand)
            {
                var method = Method ?? FromEnd;

                switch (method)
                {
                case MethodInfo m:
                    switch (m.GetParametersCached().Length)
                    {
                    case 1:
                        return(Expression.Call(m, operand));

                    case 2:
                        return(Expression.Call(m, operand, Expression.Constant(true)));
                    }
                    break;

                case ConstructorInfo c:
                    switch (c.GetParametersCached().Length)
                    {
                    case 1:
                        return(Expression.New(c, operand));

                    case 2:
                        return(Expression.New(c, operand, Expression.Constant(true)));
                    }
                    break;
                }

                throw ContractUtils.Unreachable;
            }
        }