Exemple #1
0
        private static DataValueType DecideValueType(BinaryExpressionOperator op, DataValueType left, DataValueType right)
        {
            if (op.IsArithmetic())
            {
                if (left == DataValueType.Integer && right == DataValueType.Integer)
                {
                    return(DataValueType.Integer);
                }
                else if (left == DataValueType.Boolean && right == DataValueType.Boolean)
                {
                    return(DataValueType.Boolean);
                }
                else if (left == DataValueType.Float || right == DataValueType.Float)
                {
                    return(DataValueType.Float);
                }
                else if (left == DataValueType.String || right == DataValueType.String)
                {
                    return(DataValueType.String);
                }
            }
            else if (op.IsLogical() || op.IsRelational())
            {
                return(DataValueType.Boolean);
            }

            return(DataValueType.Unknown);
        }
Exemple #2
0
            public RedILNode VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, State data)
            {
                var operand = CastUtilities.CastRedILNode <ExpressionNode>(unaryOperatorExpression.Expression.AcceptVisitor(this, data.NewState(unaryOperatorExpression, null)));

                if (OperatorUtilities.IsIncrement(unaryOperatorExpression.Operator))
                {
                    if (data.ParentNode.NodeType != NodeType.Statement)
                    {
                        throw new RedILException($"Incremental operators can only be used within statements");
                    }

                    BinaryExpressionOperator binaryOp = default;
                    switch (unaryOperatorExpression.Operator)
                    {
                    case UnaryOperatorType.Increment:
                    case UnaryOperatorType.PostIncrement:
                        binaryOp = BinaryExpressionOperator.Add;
                        break;

                    case UnaryOperatorType.Decrement:
                    case UnaryOperatorType.PostDecrement:
                        binaryOp = BinaryExpressionOperator.Subtract;
                        break;
                    }

                    var constantOne = new ConstantValueNode(DataValueType.Integer, 1);
                    return(new AssignNode(operand, VisitBinaryOperatorExpression(operand, constantOne, binaryOp, data.NewState(unaryOperatorExpression, null))));
                }

                var op = OperatorUtilities.UnaryOperator(unaryOperatorExpression.Operator);

                return(new UnaryExpressionNode(op, operand));
            }
Exemple #3
0
        public static ExpressionNode Create(BinaryExpressionOperator op, ExpressionNode left, ExpressionNode right)
        {
            var type = DecideValueType(op, left.DataType, right.DataType);
            var node = new BinaryExpressionNode(type, op, left, right);

            return(node.Simplify());
        }
Exemple #4
0
 public static bool IsArithmatic(BinaryExpressionOperator op)
 {
     return(op == BinaryExpressionOperator.Add ||
            op == BinaryExpressionOperator.Subtract ||
            op == BinaryExpressionOperator.Multiply ||
            op == BinaryExpressionOperator.Divide ||
            op == BinaryExpressionOperator.Modulus);
 }
 /// <summary>
 /// Creates a new operator expression.
 /// </summary>
 /// <param name="operatorType">Type of the operator.</param>
 /// <param name="left">The left expression.</param>
 /// <param name="right">The right expression.</param>
 public BinaryOperatorExpression(
     BinaryExpressionOperator operatorType,
     IConditionExpression left,
     IConditionExpression right)
 {
     _operatorType = operatorType;
     _left = left;
     _right = right;
 }
 /// <summary>
 /// Creates a new operator expression.
 /// </summary>
 /// <param name="operatorType">Type of the operator.</param>
 /// <param name="left">The left expression.</param>
 /// <param name="right">The right expression.</param>
 public BinaryOperatorExpression(
     BinaryExpressionOperator operatorType,
     IConditionExpression left,
     IConditionExpression right)
 {
     _operatorType = operatorType;
     _left         = left;
     _right        = right;
 }
Exemple #7
0
 public UniformOperatorNode(
     DataValueType dataType,
     BinaryExpressionOperator op,
     IList <ExpressionNode> children)
     : base(RedILNodeType.UniformExpression, dataType)
 {
     Operator = op;
     Children = children;
 }
Exemple #8
0
 public static bool IsBoolean(BinaryExpressionOperator op)
 {
     return(op == BinaryExpressionOperator.And ||
            op == BinaryExpressionOperator.Or ||
            op == BinaryExpressionOperator.Equal ||
            op == BinaryExpressionOperator.NotEqual ||
            op == BinaryExpressionOperator.Less ||
            op == BinaryExpressionOperator.Greater ||
            op == BinaryExpressionOperator.LessEqual ||
            op == BinaryExpressionOperator.GreaterEqual);
 }
Exemple #9
0
 public BinaryExpressionNode(
     DataValueType dataType,
     BinaryExpressionOperator op,
     ExpressionNode left,
     ExpressionNode right)
     : base(RedILNodeType.BinaryExpression, dataType)
 {
     Operator = op;
     Left     = left;
     Right    = right;
 }
Exemple #10
0
        private ExpressionNode SimplifyArithmatic(BinaryExpressionOperator op, ExpressionNode left,
                                                  ExpressionNode right)
        {
            if (left.Type == RedILNodeType.Constant && right.Type == RedILNodeType.Constant)
            {
                var leftC     = (ConstantValueNode)left;
                var rightC    = (ConstantValueNode)right;
                var isInteger = left.DataType == DataValueType.Integer && right.DataType == DataValueType.Integer;
                var dataType  = isInteger ? DataValueType.Integer : DataValueType.Float;
                var leftVal   = isInteger ? Convert.ToInt64(leftC.Value) : Convert.ToDouble(leftC.Value);
                var rightVal  = isInteger ? Convert.ToInt64(rightC.Value) : Convert.ToDouble(rightC.Value);
                switch (Operator)
                {
                case BinaryExpressionOperator.Add:
                    return(new ConstantValueNode(dataType, leftVal + rightVal));

                case BinaryExpressionOperator.Subtract:
                    return(new ConstantValueNode(dataType, leftVal - rightVal));

                case BinaryExpressionOperator.Multiply:
                    return(new ConstantValueNode(dataType, leftVal * rightVal));

                case BinaryExpressionOperator.Divide:
                    return(new ConstantValueNode(dataType, leftVal / rightVal));

                case BinaryExpressionOperator.Modulus:
                    return(new ConstantValueNode(dataType, leftVal % rightVal));

                case BinaryExpressionOperator.Less:
                    return(new ConstantValueNode(DataValueType.Boolean, leftVal < rightVal));

                case BinaryExpressionOperator.Greater:
                    return(new ConstantValueNode(DataValueType.Boolean, leftVal > rightVal));

                case BinaryExpressionOperator.LessEqual:
                    return(new ConstantValueNode(DataValueType.Boolean, leftVal <= rightVal));

                case BinaryExpressionOperator.GreaterEqual:
                    return(new ConstantValueNode(DataValueType.Boolean, leftVal >= rightVal));
                }
            }

            return(this);
        }
Exemple #11
0
        private ExpressionNode SimplifyBoolean(BinaryExpressionOperator op, ExpressionNode left, ExpressionNode right)
        {
            if (left.Type == RedILNodeType.Constant || right.Type == RedILNodeType.Constant)
            {
                var constant = left.Type == RedILNodeType.Constant
                    ? (ConstantValueNode)left
                    : (ConstantValueNode)right;
                var other = left.Type == RedILNodeType.Constant ? right : left;
                switch (op)
                {
                case BinaryExpressionOperator.And:
                    return(constant.Value.Equals(true) ? other : False);

                case BinaryExpressionOperator.Or:
                    return(constant.Value.Equals(true) ? True : other);
                }
            }

            return(this);
        }
Exemple #12
0
        internal static SmallType GetResultType(SmallType pLeft, BinaryExpressionOperator pOp, SmallType pRight)
        {
            switch (pOp)
            {
            case BinaryExpressionOperator.Addition:
            case BinaryExpressionOperator.Subtraction:
            case BinaryExpressionOperator.Multiplication:
            case BinaryExpressionOperator.Division:
            case BinaryExpressionOperator.Mod:
                if (pLeft.IsAssignableFrom(pRight))
                {
                    return(pLeft);
                }
                if (TypeHelper.IsFloat(pLeft) && TypeHelper.IsNumber(pRight))
                {
                    return(pLeft);
                }
                if (TypeHelper.IsFloat(pRight) && TypeHelper.IsNumber(pLeft))
                {
                    return(pRight);
                }
                return(SmallTypeCache.Undefined);

            case BinaryExpressionOperator.Equals:
            case BinaryExpressionOperator.GreaterThan:
            case BinaryExpressionOperator.GreaterThanOrEqual:
            case BinaryExpressionOperator.LessThan:
            case BinaryExpressionOperator.LessThanOrEqual:
            case BinaryExpressionOperator.NotEquals:
                if (pLeft.IsAssignableFrom(pRight))
                {
                    return(pLeft);
                }
                return(SmallTypeCache.Undefined);

            default:
                throw new NotSupportedException("Unknown binary expression operator " + pOp.ToString());
            }
        }
 /// <summary>
 /// Creates a new operator expression.
 /// </summary>
 /// <param name="operatorType">Binary expression operator type.</param>
 public OperatorExpressionPlaceholder(BinaryExpressionOperator operatorType)
 {
     _operatorType = operatorType;
 }
Exemple #14
0
        /// <summary>
        /// Takes in a list of expressions and operator expression placeholders and
        /// builds an expression tree node.
        /// </summary>
        /// <param name="originalNodes">Original nodes.</param>
        /// <param name="originalExpression">Original expression.</param>
        /// <returns>A condition expression.</returns>
        private static IConditionExpression AssembleExpressionTree(
            ReadOnlyCollection <IConditionExpression> originalNodes, string originalExpression)
        {
            IConditionExpression conditionExpression = null;

            List <IConditionExpression> nodes = new List <IConditionExpression>(originalNodes);

            //
            // Build a queue that represents the binary operator precedence
            //
            Queue <BinaryExpressionOperator> operatorPrecedence = new Queue <BinaryExpressionOperator>();

            operatorPrecedence.Enqueue(BinaryExpressionOperator.Equal);
            operatorPrecedence.Enqueue(BinaryExpressionOperator.NotEqual);
            operatorPrecedence.Enqueue(BinaryExpressionOperator.Contains);
            operatorPrecedence.Enqueue(BinaryExpressionOperator.Matches);
            operatorPrecedence.Enqueue(BinaryExpressionOperator.And);
            operatorPrecedence.Enqueue(BinaryExpressionOperator.Or);

            //
            // Loop through the nodes and merge them by operator precedence
            //
            BinaryExpressionOperator currentOperator = operatorPrecedence.Dequeue();

            while (nodes.Count > 1)
            {
                for (int nodeIndex = 1; nodeIndex < nodes.Count - 1; nodeIndex++)
                {
                    OperatorExpressionPlaceholder operatorExpressionPlaceHolder =
                        nodes[nodeIndex] as OperatorExpressionPlaceholder;

                    if (operatorExpressionPlaceHolder != null &&
                        operatorExpressionPlaceHolder.Operator == currentOperator)
                    {
                        IConditionExpression left  = nodes[nodeIndex - 1];
                        IConditionExpression right = nodes[nodeIndex + 1];

                        if ((operatorExpressionPlaceHolder.Operator == BinaryExpressionOperator.Equal ||
                             operatorExpressionPlaceHolder.Operator == BinaryExpressionOperator.Contains) &&
                            !(left is LeafExpression && right is LeafExpression))
                        {
                            OnInvalidExpression(originalExpression);
                        }

                        BinaryOperatorExpression operatorExpression = new BinaryOperatorExpression(
                            operatorExpressionPlaceHolder.Operator, left, right);

                        nodes[nodeIndex] = operatorExpression;
                        nodes.Remove(left);
                        nodes.Remove(right);

                        //
                        // Restart processing of this level
                        //
                        nodeIndex = 0;
                    }
                }

                if (operatorPrecedence.Count > 0)
                {
                    currentOperator = operatorPrecedence.Dequeue();
                }
                else
                {
                    break;
                }
            }

            //
            // At the end of everything, we should have a single binary or unary
            // condition expression.  Anything else is invalid and a format exception
            // will be thrown.
            //
            if (nodes.Count == 1)
            {
                conditionExpression = nodes[0] as BinaryOperatorExpression;
                if (conditionExpression == null)
                {
                    conditionExpression = nodes[0] as UnaryOperatorExpression;
                }
            }

            if (conditionExpression == null)
            {
                OnInvalidExpression(originalExpression);
            }

            return(conditionExpression);
        }
Exemple #15
0
            private ExpressionNode VisitBinaryOperatorExpression(ExpressionNode left, ExpressionNode right, BinaryExpressionOperator op, State data)
            {
                if (OperatorUtilities.IsBoolean(op))
                {
                    return(new BinaryExpressionNode(DataValueType.Boolean, op, left, right));
                }
                else if (OperatorUtilities.IsArithmatic(op))
                {
                    if (left.DataType == DataValueType.String ||
                        right.DataType == DataValueType.String)
                    {
                        return(new BinaryExpressionNode(DataValueType.String, BinaryExpressionOperator.StringConcat, left, right));
                    }
                    else if (left.DataType == DataValueType.Float ||
                             right.DataType == DataValueType.Float)
                    {
                        return(new BinaryExpressionNode(DataValueType.Float, op, left, right));
                    }
                    else if (left.DataType == DataValueType.Integer &&
                             right.DataType == DataValueType.Integer)
                    {
                        return(new BinaryExpressionNode(DataValueType.Integer, op, left, right));
                    }
                }
                else if (op == BinaryExpressionOperator.NullCoalescing)
                {
                    return(new BinaryExpressionNode(left.DataType, op, left, right));
                }

                throw new RedILException($"Unsupported operator '{op}' with data types '{left.DataType}' and '{right.DataType}'");
            }
Exemple #16
0
 public static BinaryExpressionSyntax BinaryExpression(SyntaxNode pLeft, BinaryExpressionOperator pOperator, SyntaxNode pRight)
 {
     return(new BinaryExpressionSyntax(pLeft, pOperator, pRight));
 }
Exemple #17
0
 internal BinaryExpressionSyntax(SyntaxNode pLeft, BinaryExpressionOperator pOperator, SyntaxNode pRight)
 {
     Left     = pLeft;
     Operator = pOperator;
     Right    = pRight;
 }
 public static bool IsLogical(this BinaryExpressionOperator op)
 {
     return(op == BinaryExpressionOperator.And || op == BinaryExpressionOperator.Or);
 }
            private void WriteBinaryOperator(CompilationState state, BinaryExpressionOperator op)
            {
                switch (op)
                {
                case BinaryExpressionOperator.StringConcat:
                    state.Write("..");
                    break;

                case BinaryExpressionOperator.Add:
                    state.Write("+");
                    break;

                case BinaryExpressionOperator.Subtract:
                    state.Write("-");
                    break;

                case BinaryExpressionOperator.Multiply:
                    state.Write("*");
                    break;

                case BinaryExpressionOperator.Divide:
                    state.Write("/'");
                    break;

                case BinaryExpressionOperator.Modulus:
                    state.Write("%");
                    break;

                case BinaryExpressionOperator.Equal:
                    state.Write("==");
                    break;

                case BinaryExpressionOperator.Less:
                    state.Write("<");
                    break;

                case BinaryExpressionOperator.Greater:
                    state.Write(">");
                    break;

                case BinaryExpressionOperator.NotEqual:
                    state.Write("~=");
                    break;

                case BinaryExpressionOperator.LessEqual:
                    state.Write("<=");
                    break;

                case BinaryExpressionOperator.GreaterEqual:
                    state.Write(">=");
                    break;

                case BinaryExpressionOperator.Or:
                case BinaryExpressionOperator.NullCoalescing:
                    state.Write(" or ");
                    break;

                case BinaryExpressionOperator.And:
                    state.Write(" and ");
                    break;
                }
            }
        public override LLVMValueRef Emit(EmittingContext pContext)
        {
            pContext.EmitDebugLocation(this);

            LLVMValueRef value;

            switch (Operator)
            {
            case UnaryExpressionOperator.Not:
                value = Value.Emit(pContext);
                Utils.LlvmHelper.LoadIfPointer(ref value, pContext);
                return(LLVM.BuildNot(pContext.Builder, value, ""));

            case UnaryExpressionOperator.Negative:
                value = Value.Emit(pContext);
                Utils.LlvmHelper.LoadIfPointer(ref value, pContext);
                return(LLVM.BuildNeg(pContext.Builder, value, ""));

            case UnaryExpressionOperator.Length:
                var arr = Value.Emit(pContext);
                return(LLVM.BuildLoad(pContext.Builder, pContext.GetArrayLength(arr), ""));

            case UnaryExpressionOperator.PreIncrement:
            case UnaryExpressionOperator.PreDecrement:
            case UnaryExpressionOperator.PostIncrement:
            case UnaryExpressionOperator.PostDecrement:
                var variable = (IdentifierSyntax)Value;
                variable.DoNotLoad = true;
                LLVMValueRef v = variable.Emit(pContext);

                BinaryExpressionOperator op = BinaryExpressionOperator.Equals;
                switch (Operator)
                {
                case UnaryExpressionOperator.PostDecrement:
                case UnaryExpressionOperator.PreDecrement:
                    op = BinaryExpressionOperator.Subtraction;
                    break;

                case UnaryExpressionOperator.PostIncrement:
                case UnaryExpressionOperator.PreIncrement:
                    op = BinaryExpressionOperator.Addition;
                    break;
                }

                value = BinaryExpressionSyntax.EmitOperator(v, op, pContext.GetInt(1), pContext);

                //Post unary we want to return the original variable value
                if (Operator == UnaryExpressionOperator.PostIncrement || Operator == UnaryExpressionOperator.PostDecrement)
                {
                    //Save the old value to a temp variable that we will return
                    var          temp      = pContext.AllocateVariable("<temp_unary>", Value);
                    LLVMValueRef tempValue = Utils.LlvmHelper.IsPointer(v) ? LLVM.BuildLoad(pContext.Builder, v, "") : v;
                    LLVM.BuildStore(pContext.Builder, tempValue, temp);

                    //Increment the variable
                    Utils.LlvmHelper.LoadIfPointer(ref value, pContext);
                    if (Value.SyntaxType == SyntaxType.Identifier || Value.SyntaxType == SyntaxType.MemberAccess)
                    {
                        LLVM.BuildStore(pContext.Builder, value, v);
                    }

                    return(temp);
                }

                //If it isn't a variable we cane save we need to return the addition
                if (Value.SyntaxType == SyntaxType.Identifier || Value.SyntaxType == SyntaxType.MemberAccess)
                {
                    LLVM.BuildStore(pContext.Builder, value, v);
                }
                return(value);

            default:
                throw new NotSupportedException();
            }
        }
Exemple #21
0
 /// <summary>
 /// Creates a new operator expression.
 /// </summary>
 /// <param name="operatorType">Binary expression operator type.</param>
 public OperatorExpressionPlaceholder(BinaryExpressionOperator operatorType)
 {
     _operatorType = operatorType;
 }
Exemple #22
0
        internal static LLVMValueRef EmitOperator(LLVMValueRef pLeft,
                                                  BinaryExpressionOperator pOp,
                                                  LLVMValueRef pRight,
                                                  EmittingContext pContext)
        {
            //We since arrays are pointers, we need to load the value at the pointer
            LlvmHelper.LoadIfPointer(ref pLeft, pContext);
            LlvmHelper.LoadIfPointer(ref pRight, pContext);

            bool useFloat = false;

            if (LlvmHelper.IsFloat(pLeft))
            {
                if (!LlvmHelper.IsFloat(pRight))
                {
                    pRight = LLVM.BuildSIToFP(pContext.Builder, pRight, pLeft.TypeOf(), "");
                }
                useFloat = true;
            }
            if (LlvmHelper.IsFloat(pRight))
            {
                if (!LlvmHelper.IsFloat(pLeft))
                {
                    pLeft = LLVM.BuildSIToFP(pContext.Builder, pLeft, pRight.TypeOf(), "");
                }
                useFloat = true;
            }

            switch (pOp)
            {
            case BinaryExpressionOperator.Addition:
                if (useFloat)
                {
                    return(LLVM.BuildFAdd(pContext.Builder, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildAdd(pContext.Builder, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.Multiplication:
                if (useFloat)
                {
                    return(LLVM.BuildFMul(pContext.Builder, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildMul(pContext.Builder, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.Subtraction:
                if (useFloat)
                {
                    return(LLVM.BuildFSub(pContext.Builder, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildSub(pContext.Builder, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.Division:
                if (useFloat)
                {
                    return(LLVM.BuildFDiv(pContext.Builder, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildSDiv(pContext.Builder, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.Mod:
                if (useFloat)
                {
                    return(LLVM.BuildFRem(pContext.Builder, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildSRem(pContext.Builder, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.Equals:
                if (useFloat)
                {
                    return(LLVM.BuildFCmp(pContext.Builder, LLVMRealPredicate.LLVMRealOEQ, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntEQ, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.NotEquals:
                if (useFloat)
                {
                    return(LLVM.BuildFCmp(pContext.Builder, LLVMRealPredicate.LLVMRealONE, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntNE, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.GreaterThan:
                if (useFloat)
                {
                    return(LLVM.BuildFCmp(pContext.Builder, LLVMRealPredicate.LLVMRealOGT, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntSGT, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.GreaterThanOrEqual:
                if (useFloat)
                {
                    return(LLVM.BuildFCmp(pContext.Builder, LLVMRealPredicate.LLVMRealOGE, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntSGE, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.LessThan:
                if (useFloat)
                {
                    return(LLVM.BuildFCmp(pContext.Builder, LLVMRealPredicate.LLVMRealOLT, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntSLT, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.LessThanOrEqual:
                if (useFloat)
                {
                    return(LLVM.BuildFCmp(pContext.Builder, LLVMRealPredicate.LLVMRealOLE, pLeft, pRight, ""));
                }
                else
                {
                    return(LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntSLE, pLeft, pRight, ""));
                }

            case BinaryExpressionOperator.And:
            case BinaryExpressionOperator.BitwiseAnd:
                return(LLVM.BuildAnd(pContext.Builder, pLeft, pRight, ""));

            case BinaryExpressionOperator.Or:
            case BinaryExpressionOperator.BitwiseOr:
                return(LLVM.BuildOr(pContext.Builder, pLeft, pRight, ""));

            case BinaryExpressionOperator.LeftBitShift:
                return(LLVM.BuildLShr(pContext.Builder, pLeft, pRight, ""));

            case BinaryExpressionOperator.RightBitShift:
                return(LLVM.BuildAShr(pContext.Builder, pLeft, pRight, ""));

            default:
                throw new NotImplementedException();
            }
        }
 public static bool IsRelational(this BinaryExpressionOperator op)
 {
     return(op == BinaryExpressionOperator.Equal || op == BinaryExpressionOperator.NotEqual ||
            op == BinaryExpressionOperator.Less || op == BinaryExpressionOperator.LessEqual ||
            op == BinaryExpressionOperator.Greater || op == BinaryExpressionOperator.GreaterEqual);
 }