private Expression CreateCompareExpression(Expression left, Expression right)
        {
            Expression index = (Expression)Expression.Condition((Expression)LinqExpressionNormalizer.CreateRelationalOperator(ExpressionType.Equal, left, right), (Expression)Expression.Constant((object)0), (Expression)Expression.Condition((Expression)LinqExpressionNormalizer.CreateRelationalOperator(ExpressionType.GreaterThan, left, right), (Expression)Expression.Constant((object)1), (Expression)Expression.Constant((object)-1)));

            this._patterns[index] = (LinqExpressionNormalizer.Pattern) new LinqExpressionNormalizer.ComparePattern(left, right);
            return(index);
        }
        private static bool TryMatchCoalescePattern(Expression expression, out Expression normalized)
        {
            normalized = (Expression)null;
            bool flag = false;

            if (expression.NodeType == ExpressionType.Quote)
            {
                if (LinqExpressionNormalizer.TryMatchCoalescePattern(((UnaryExpression)expression).Operand, out normalized))
                {
                    flag       = true;
                    normalized = (Expression)Expression.Quote(normalized);
                }
            }
            else if (expression.NodeType == ExpressionType.Lambda)
            {
                LambdaExpression lambdaExpression = (LambdaExpression)expression;
                if (lambdaExpression.Body.NodeType == ExpressionType.Coalesce && lambdaExpression.Body.Type == typeof(bool))
                {
                    BinaryExpression body = (BinaryExpression)lambdaExpression.Body;
                    if (body.Right.NodeType == ExpressionType.Constant && false.Equals(((ConstantExpression)body.Right).Value))
                    {
                        normalized = (Expression)Expression.Lambda(lambdaExpression.Type, (Expression)Expression.Convert(body.Left, typeof(bool)), (IEnumerable <ParameterExpression>)lambdaExpression.Parameters);
                        flag       = true;
                    }
                }
            }
            return(flag);
        }
        private static BinaryExpression CreateRelationalOperator(
            ExpressionType op,
            Expression left,
            Expression right)
        {
            BinaryExpression result;

            LinqExpressionNormalizer.TryCreateRelationalOperator(op, left, right, out result);
            return(result);
        }
        private static MethodCallExpression NormalizePredicateArgument(
            MethodCallExpression callExpression)
        {
            int                  argumentOrdinal;
            Expression           normalized;
            MethodCallExpression methodCallExpression;

            if (LinqExpressionNormalizer.HasPredicateArgument(callExpression, out argumentOrdinal) && LinqExpressionNormalizer.TryMatchCoalescePattern(callExpression.Arguments[argumentOrdinal], out normalized))
            {
                methodCallExpression = Expression.Call(callExpression.Object, callExpression.Method, (IEnumerable <Expression>) new List <Expression>((IEnumerable <Expression>)callExpression.Arguments)
                {
                    [argumentOrdinal] = normalized
                });
            }
            else
            {
                methodCallExpression = callExpression;
            }
            return(methodCallExpression);
        }
 internal override Expression VisitBinary(BinaryExpression b)
 {
     b = (BinaryExpression)base.VisitBinary(b);
     if (b.NodeType == ExpressionType.Equal)
     {
         Expression left  = LinqExpressionNormalizer.UnwrapObjectConvert(b.Left);
         Expression right = LinqExpressionNormalizer.UnwrapObjectConvert(b.Right);
         if (left != b.Left || right != b.Right)
         {
             b = LinqExpressionNormalizer.CreateRelationalOperator(ExpressionType.Equal, left, right);
         }
     }
     LinqExpressionNormalizer.Pattern pattern;
     if (this._patterns.TryGetValue(b.Left, out pattern) && pattern.Kind == LinqExpressionNormalizer.PatternKind.Compare && LinqExpressionNormalizer.IsConstantZero(b.Right))
     {
         LinqExpressionNormalizer.ComparePattern comparePattern = (LinqExpressionNormalizer.ComparePattern)pattern;
         BinaryExpression result;
         if (LinqExpressionNormalizer.TryCreateRelationalOperator(b.NodeType, comparePattern.Left, comparePattern.Right, out result))
         {
             b = result;
         }
     }
     return((Expression)b);
 }
        internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            m = (MethodCallExpression)base.VisitMethodCall(m);
            if (m.Method.IsStatic)
            {
                if (m.Method.Name.StartsWith("op_", StringComparison.Ordinal))
                {
                    if (m.Arguments.Count == 2)
                    {
                        switch (m.Method.Name)
                        {
                        case "op_Equality":
                            return((Expression)Expression.Equal(m.Arguments[0], m.Arguments[1], false, m.Method));

                        case "op_Inequality":
                            return((Expression)Expression.NotEqual(m.Arguments[0], m.Arguments[1], false, m.Method));

                        case "op_GreaterThan":
                            return((Expression)Expression.GreaterThan(m.Arguments[0], m.Arguments[1], false, m.Method));

                        case "op_GreaterThanOrEqual":
                            return((Expression)Expression.GreaterThanOrEqual(m.Arguments[0], m.Arguments[1], false, m.Method));

                        case "op_LessThan":
                            return((Expression)Expression.LessThan(m.Arguments[0], m.Arguments[1], false, m.Method));

                        case "op_LessThanOrEqual":
                            return((Expression)Expression.LessThanOrEqual(m.Arguments[0], m.Arguments[1], false, m.Method));

                        case "op_Multiply":
                            return((Expression)Expression.Multiply(m.Arguments[0], m.Arguments[1], m.Method));

                        case "op_Subtraction":
                            return((Expression)Expression.Subtract(m.Arguments[0], m.Arguments[1], m.Method));

                        case "op_Addition":
                            return((Expression)Expression.Add(m.Arguments[0], m.Arguments[1], m.Method));

                        case "op_Division":
                            return((Expression)Expression.Divide(m.Arguments[0], m.Arguments[1], m.Method));

                        case "op_Modulus":
                            return((Expression)Expression.Modulo(m.Arguments[0], m.Arguments[1], m.Method));

                        case "op_BitwiseAnd":
                            return((Expression)Expression.And(m.Arguments[0], m.Arguments[1], m.Method));

                        case "op_BitwiseOr":
                            return((Expression)Expression.Or(m.Arguments[0], m.Arguments[1], m.Method));

                        case "op_ExclusiveOr":
                            return((Expression)Expression.ExclusiveOr(m.Arguments[0], m.Arguments[1], m.Method));
                        }
                    }
                    if (m.Arguments.Count == 1)
                    {
                        switch (m.Method.Name)
                        {
                        case "op_UnaryNegation":
                            return((Expression)Expression.Negate(m.Arguments[0], m.Method));

                        case "op_UnaryPlus":
                            return((Expression)Expression.UnaryPlus(m.Arguments[0], m.Method));

                        case "op_Explicit":
                        case "op_Implicit":
                            return((Expression)Expression.Convert(m.Arguments[0], m.Type, m.Method));

                        case "op_OnesComplement":
                        case "op_False":
                            return((Expression)Expression.Not(m.Arguments[0], m.Method));
                        }
                    }
                }
                if (m.Method.Name == "Equals" && m.Arguments.Count > 1)
                {
                    return((Expression)Expression.Equal(m.Arguments[0], m.Arguments[1], false, m.Method));
                }
                if (m.Method.Name == "CompareString" && m.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" || m.Method.Name == "Compare" && m.Arguments.Count > 1 && m.Method.ReturnType == typeof(int))
                {
                    return(this.CreateCompareExpression(m.Arguments[0], m.Arguments[1]));
                }
            }
            else
            {
                if (m.Method.Name == "Equals" && m.Arguments.Count > 0)
                {
                    Type parameterType = m.Method.GetParameters()[0].ParameterType;
                    if (parameterType != typeof(DbGeography) && parameterType != typeof(DbGeometry))
                    {
                        return((Expression)LinqExpressionNormalizer.CreateRelationalOperator(ExpressionType.Equal, m.Object, m.Arguments[0]));
                    }
                }
                if (m.Method.Name == "CompareTo" && m.Arguments.Count == 1 && m.Method.ReturnType == typeof(int))
                {
                    return(this.CreateCompareExpression(m.Object, m.Arguments[0]));
                }
                if (m.Method.Name == "Contains" && m.Arguments.Count == 1)
                {
                    Type       declaringType = m.Method.DeclaringType;
                    MethodInfo method;
                    if (declaringType.IsGenericType() && declaringType.GetGenericTypeDefinition() == typeof(List <>) && ReflectionUtil.TryLookupMethod(SequenceMethod.Contains, out method))
                    {
                        return((Expression)Expression.Call(method.MakeGenericMethod(declaringType.GetGenericArguments()), m.Object, m.Arguments[0]));
                    }
                }
            }
            return((Expression)LinqExpressionNormalizer.NormalizePredicateArgument(m));
        }