private bool IsShiftOperator(BinaryOperand operand)
 {
     if (operand == BinaryOperand.RightShift ||
         operand == BinaryOperand.RightShiftAssign ||
         operand == BinaryOperand.LeftShift ||
         operand == BinaryOperand.LeftShiftAssign)
     {
         return(true);
     }
     return(false);
 }
 private bool IsAssignOperator(BinaryOperand operand)
 {
     if (operand == BinaryOperand.Assign ||
         operand == BinaryOperand.AddAssign ||
         operand == BinaryOperand.SubAssign ||
         operand == BinaryOperand.MultiplyAssign ||
         operand == BinaryOperand.DivideAssign ||
         operand == BinaryOperand.ModuloAssign ||
         operand == BinaryOperand.BitwiseOrAssign ||
         operand == BinaryOperand.BitwiseAndAssign ||
         operand == BinaryOperand.XorAssign)
     {
         return(true);
     }
     return(false);
 }
Esempio n. 3
0
 public BinaryNode(BinaryOperand op, QueryNode left, QueryNode right)
 {
     Op    = op;
     Left  = left;
     Right = right;
 }
        private Expression GetExpression(Expression left, Expression right, BinaryOperand operand)
        {
            var strType        = typeof(string);
            var convertedLeft  = left;
            var convertedRight = right;

            if (left.Type != right.Type)
            {
                if (left.Type == strType || right.Type == strType)
                {
                    var toStringMethod = typeof(Convert).GetMethod("ToString", new Type[] { typeof(object) });

                    if (left.Type == strType)
                    {
                        convertedRight = Expression.Call(null, toStringMethod,
                                                         Expression.Convert(right, typeof(object)));
                    }
                    else
                    {
                        convertedLeft = Expression.Call(null, toStringMethod,
                                                        Expression.Convert(left, typeof(object)));
                    }
                }
                else
                {
                    if (IsShiftOperator(operand))
                    {
                        convertedRight = Expression.Convert(right, typeof(int));
                    }
                    else if (IsAssignOperator(operand))
                    {
                        convertedRight = Expression.Convert(right, left.Type);
                    }
                    else if (operand != BinaryOperand.Coalesce)
                    {
                        convertedLeft  = ConvertType(left, left.Type, right.Type);
                        convertedRight = ConvertType(right, right.Type, left.Type);
                    }
                }
            }
            else if (!IsAssignOperator(operand) && IsByteType(left.Type) && IsByteType(right.Type))
            {
                convertedLeft  = Expression.Convert(left, typeof(int));
                convertedRight = Expression.Convert(right, typeof(int));
            }

            switch (operand)
            {
            case BinaryOperand.Add:
                if (left.Type == strType || right.Type == strType)
                {
                    var concatMethod = strType.GetMethod("Concat", new[] { typeof(object[]) });

                    var array = Expression.NewArrayInit(typeof(object),
                                                        Expression.Convert(left, typeof(object)),
                                                        Expression.Convert(right, typeof(object)));
                    return(Expression.Call(null, concatMethod, array));
                }
                return(Expression.Add(convertedLeft, convertedRight));

            case BinaryOperand.Sub:
                return(Expression.Subtract(convertedLeft, convertedRight));

            case BinaryOperand.Multiply:
                return(Expression.Multiply(convertedLeft, convertedRight));

            case BinaryOperand.Divide:
                return(Expression.Divide(convertedLeft, convertedRight));

            case BinaryOperand.Modulo:
                return(Expression.Modulo(convertedLeft, convertedRight));

            case BinaryOperand.Equal:
                return(Expression.Equal(convertedLeft, convertedRight));

            case BinaryOperand.NotEqual:
                return(Expression.NotEqual(convertedLeft, convertedRight));

            case BinaryOperand.And:
                return(Expression.AndAlso(convertedLeft, convertedRight));

            case BinaryOperand.Or:
                return(Expression.OrElse(convertedLeft, convertedRight));

            case BinaryOperand.LessThan:
                return(Expression.LessThan(convertedLeft, convertedRight));

            case BinaryOperand.LessThanEqual:
                return(Expression.LessThanOrEqual(convertedLeft, convertedRight));

            case BinaryOperand.GreaterThan:
                return(Expression.GreaterThan(convertedLeft, convertedRight));

            case BinaryOperand.GreaterThanEqual:
                return(Expression.GreaterThanOrEqual(convertedLeft, convertedRight));

            case BinaryOperand.BitwiseAnd:
                if (left.Type.IsEnum)
                {
                    var left1        = Expression.Convert(left, Enum.GetUnderlyingType(left.Type));
                    var right1       = Expression.Convert(right, Enum.GetUnderlyingType(right.Type));
                    var orExpression = Expression.And(left1, right1);
                    return(Expression.Convert(orExpression, Enum.GetUnderlyingType(left.Type)));
                }
                return(Expression.And(convertedLeft, convertedRight));

            case BinaryOperand.BitwiseOr:
                if (left.Type.IsEnum)
                {
                    var left1        = Expression.Convert(left, Enum.GetUnderlyingType(left.Type));
                    var right1       = Expression.Convert(right, Enum.GetUnderlyingType(right.Type));
                    var orExpression = Expression.Or(left1, right1);
                    return(Expression.Convert(orExpression, Enum.GetUnderlyingType(left.Type)));
                }
                return(Expression.Or(convertedLeft, convertedRight));

            case BinaryOperand.Xor:
                if (left.Type.IsEnum)
                {
                    var left1        = Expression.Convert(left, Enum.GetUnderlyingType(left.Type));
                    var right1       = Expression.Convert(right, Enum.GetUnderlyingType(right.Type));
                    var orExpression = Expression.ExclusiveOr(left1, right1);
                    return(Expression.Convert(orExpression, Enum.GetUnderlyingType(left.Type)));
                }
                return(Expression.ExclusiveOr(convertedLeft, convertedRight));

            case BinaryOperand.LeftShift:
                return(Expression.LeftShift(convertedLeft, convertedRight));

            case BinaryOperand.RightShift:
                return(Expression.RightShift(convertedLeft, convertedRight));

            case BinaryOperand.Coalesce:
                return(Expression.Coalesce(convertedLeft, convertedRight));
            }

            switch (operand)
            {
            case BinaryOperand.Assign:
                return(Expression.Assign(left, convertedRight));

            case BinaryOperand.AddAssign:
                if (left.Type == strType || right.Type == strType)
                {
                    var concatMethod = strType.GetMethod("Concat", new[] { typeof(object[]) });

                    var array = Expression.NewArrayInit(typeof(object),
                                                        Expression.Convert(left, typeof(object)),
                                                        Expression.Convert(right, typeof(object)));
                    var addExpression = Expression.Call(null, concatMethod, array);
                    return(Expression.Assign(left, addExpression));
                }
                else if (IsByteType(left.Type))
                {
                    var addExpression = GetExpression(convertedLeft, convertedRight, BinaryOperand.Add);
                    return(Expression.Assign(left, Expression.Convert(addExpression, left.Type)));
                }
                if (left.Type.IsSubclassOf(typeof(MulticastDelegate)))
                {
                    //Delegate.Combine
                    var delegateCombine = typeof(Delegate).GetMethod("Combine", new Type[] { typeof(Delegate), typeof(Delegate) });
                    return(Expression.Assign(left,
                                             Expression.Convert(Expression.Call(null,
                                                                                delegateCombine, left, convertedRight),
                                                                left.Type)));
                }
                return(Expression.AddAssign(left, convertedRight));

            case BinaryOperand.SubAssign:
                if (IsByteType(left.Type))
                {
                    var addExpression = GetExpression(convertedLeft, convertedRight, BinaryOperand.Sub);
                    return(Expression.Assign(left, Expression.Convert(addExpression, left.Type)));
                }
                if (left.Type.IsSubclassOf(typeof(MulticastDelegate)))
                {
                    //Delegate.Remove
                    var delegateCombine = typeof(Delegate).GetMethod("Remove", new Type[] { typeof(Delegate), typeof(Delegate) });
                    return(Expression.Assign(left,
                                             Expression.Convert(Expression.Call(null,
                                                                                delegateCombine, left, convertedRight),
                                                                left.Type)));
                }
                return(Expression.SubtractAssign(left, convertedRight));

            case BinaryOperand.MultiplyAssign:
                if (IsByteType(left.Type))
                {
                    var addExpression = GetExpression(convertedLeft, convertedRight, BinaryOperand.Multiply);
                    return(Expression.Assign(left, Expression.Convert(addExpression, left.Type)));
                }
                return(Expression.MultiplyAssign(left, convertedRight));

            case BinaryOperand.DivideAssign:
                if (IsByteType(left.Type))
                {
                    var addExpression = GetExpression(convertedLeft, convertedRight, BinaryOperand.Divide);
                    return(Expression.Assign(left, Expression.Convert(addExpression, left.Type)));
                }
                return(Expression.DivideAssign(left, convertedRight));

            case BinaryOperand.ModuloAssign:
                if (IsByteType(left.Type))
                {
                    var addExpression = GetExpression(convertedLeft, convertedRight, BinaryOperand.Modulo);
                    return(Expression.Assign(left, Expression.Convert(addExpression, left.Type)));
                }
                return(Expression.ModuloAssign(left, convertedRight));

            case BinaryOperand.BitwiseAndAssign:
                if (left.Type.IsEnum)
                {
                    var left1        = Expression.Convert(left, Enum.GetUnderlyingType(left.Type));
                    var right1       = Expression.Convert(convertedRight, Enum.GetUnderlyingType(convertedRight.Type));
                    var orExpression = Expression.And(left1, right1);
                    return(Expression.Assign(left, Expression.Convert(orExpression, left.Type)));
                }
                if (IsByteType(left.Type))
                {
                    var addExpression = GetExpression(convertedLeft, convertedRight, BinaryOperand.BitwiseAndAssign);
                    return(Expression.Assign(left, Expression.Convert(addExpression, left.Type)));
                }
                return(Expression.AndAssign(left, convertedRight));

            case BinaryOperand.BitwiseOrAssign:
                if (left.Type.IsEnum)
                {
                    var left1        = Expression.Convert(left, Enum.GetUnderlyingType(left.Type));
                    var right1       = Expression.Convert(convertedRight, Enum.GetUnderlyingType(convertedRight.Type));
                    var orExpression = Expression.Or(left1, right1);
                    return(Expression.Assign(left, Expression.Convert(orExpression, left.Type)));
                }
                if (IsByteType(left.Type))
                {
                    var addExpression = GetExpression(convertedLeft, convertedRight, BinaryOperand.BitwiseOr);
                    return(Expression.Assign(left, Expression.Convert(addExpression, left.Type)));
                }
                return(Expression.OrAssign(left, convertedRight));

            case BinaryOperand.XorAssign:
                if (left.Type.IsEnum)
                {
                    var left1        = Expression.Convert(left, Enum.GetUnderlyingType(left.Type));
                    var right1       = Expression.Convert(convertedRight, Enum.GetUnderlyingType(convertedRight.Type));
                    var orExpression = Expression.ExclusiveOr(left1, right1);
                    return(Expression.Assign(convertedLeft, Expression.Convert(orExpression, left.Type)));
                }
                if (IsByteType(left.Type))
                {
                    var addExpression = GetExpression(convertedLeft, convertedRight, BinaryOperand.Xor);
                    return(Expression.Assign(left, Expression.Convert(addExpression, left.Type)));
                }
                return(Expression.ExclusiveOrAssign(left, convertedRight));

            case BinaryOperand.LeftShiftAssign:
                return(Expression.LeftShiftAssign(left, convertedRight));

            case BinaryOperand.RightShiftAssign:
                return(Expression.RightShiftAssign(left, convertedRight));

            default:
                throw new NotSupportedException($"{binaryStatement.Operand} is not supported yet");
            }
        }