/// <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; } }