public static Expression FoldInvocation(InvocationExpression inputExpression)
        {
            IEnumerable <Expression> args = ConstantFolding.FoldExpressionList(inputExpression.Arguments);
            Expression expr = ConstantFolding.Fold(inputExpression.Expression);
            Expression resultExpression;

            if (args != inputExpression.Arguments || expr != inputExpression.Expression)
            {
                resultExpression = Expression.Invoke(expr, args);
            }
            else
            {
                resultExpression = inputExpression;
            }

#if zero
            if (!IsConstant(expr))
            {
                return(retval);
            }
            // lambdas are constant
#endif
            foreach (Expression arg in args)
            {
                if (!IsConstant(arg))
                {
                    return(resultExpression);
                }
            }

            resultExpression = ExpressionSimplifier.EvaluateToExpression(resultExpression);
            return(resultExpression);
        }
        public static Expression FoldBinary(BinaryExpression inputExpression)
        {
            Expression       left       = ConstantFolding.Fold(inputExpression.Left);
            Expression       right      = ConstantFolding.Fold(inputExpression.Right);
            LambdaExpression conversion = ConstantFolding.FoldLambda(inputExpression.Conversion);
            Expression       resultExpression;

            if (left != inputExpression.Left || right != inputExpression.Right || conversion != inputExpression.Conversion)
            {
                if (inputExpression.NodeType == ExpressionType.Coalesce)
                {
                    resultExpression = Expression.Coalesce(left, right, conversion);
                }
                else
                {
                    resultExpression = Expression.MakeBinary(inputExpression.NodeType, left, right, inputExpression.IsLiftedToNull, inputExpression.Method);
                }
            }
            else
            {
                resultExpression = inputExpression;
            }

            if (IsConstant(left) && inputExpression.NodeType == ExpressionType.Coalesce)
            {
                object leftValue = ExpressionSimplifier.Evaluate(left);
                if (leftValue == null)
                {
                    resultExpression = right;
                }
                else
                {
                    resultExpression = Expression.Constant(leftValue);
                }
            }
            else if (IsConstant(left) && IsConstant(right))
            {
                resultExpression = ExpressionSimplifier.EvaluateToExpression(resultExpression);
            }

            return(resultExpression);
        }
        public static Expression FoldMemberAccess(MemberExpression inputExpression)
        {
            Expression expr = ConstantFolding.Fold(inputExpression.Expression);
            Expression resultExpression;

            if (expr != inputExpression.Expression)
            {
                resultExpression = Expression.MakeMemberAccess(expr, inputExpression.Member);
            }
            else
            {
                resultExpression = inputExpression;
            }

            if (IsConstant(expr))
            {
                resultExpression = ExpressionSimplifier.EvaluateToExpression(resultExpression);
            }

            return(resultExpression);
        }
        public static Expression FoldTypeIs(TypeBinaryExpression inputExpression)
        {
            Expression expr = ConstantFolding.Fold(inputExpression.Expression);
            Expression resultExpression;

            if (expr != inputExpression.Expression)
            {
                resultExpression = Expression.TypeIs(expr, inputExpression.TypeOperand);
            }
            else
            {
                resultExpression = inputExpression;
            }

            if (IsConstant(expr))
            {
                resultExpression = ExpressionSimplifier.EvaluateToExpression(resultExpression);
            }

            return(resultExpression);
        }
        public static Expression FoldUnary(UnaryExpression inputExpression)
        {
            Expression operand = ConstantFolding.Fold(inputExpression.Operand);
            Expression resultExpression;

            if (operand != inputExpression.Operand)
            {
                resultExpression = Expression.MakeUnary(inputExpression.NodeType, operand, inputExpression.Type, inputExpression.Method);
            }
            else
            {
                resultExpression = inputExpression;
            }

            if (IsConstant(operand))
            {
                resultExpression = ExpressionSimplifier.EvaluateToExpression(resultExpression);
            }

            return(resultExpression);
        }
        public static Expression FoldMethodCall(MethodCallExpression inputExpression)
        {
            Expression obj = ConstantFolding.Fold(inputExpression.Object);
            ReadOnlyCollection <Expression> args = ConstantFolding.FoldExpressionList(inputExpression.Arguments);
            Expression resultExpression;

            if (obj != inputExpression.Object || args != inputExpression.Arguments)
            {
                resultExpression = Expression.Call(obj, inputExpression.Method, args);
            }
            else
            {
                resultExpression = inputExpression;
            }

            if (!IsConstant(obj))
            {
                return(resultExpression);
            }

            foreach (Expression arg in args)
            {
                if (!IsConstant(arg))
                {
                    return(resultExpression);
                }
            }

            // skip simplifying .Take(Constant)
            if (inputExpression.Method.IsStatic &&
                inputExpression.Method.DeclaringType.IsAssignableFrom(typeof(Queryable)) &&
                inputExpression.Method.Name.Equals("Take"))
            {
                return(resultExpression);
            }

            resultExpression = ExpressionSimplifier.EvaluateToExpression(resultExpression);
            return(resultExpression);
        }