예제 #1
0
        public INode ComparisonBinaryOperation(Func <INode> functionA, List <Token> keywords, Func <INode> functionB = null)
        {
            if (functionB == null)
            {
                functionB = functionA;
            }
            var left = functionA();

            Next();

            var ff = keywords[0].TokenType == CurrentToken.TokenType;

            var ffd = keywords[0].Value.Equals(CurrentToken.Value);

            while (keywords.Any(x => x.TokenType == CurrentToken.TokenType && x.Value.Equals(CurrentToken.Value)))
            {
                var operationToken = CurrentToken;
                Next();
                var right = functionB();
                left = new BinaryOpNode {
                    Left = left, Right = right, Operation = operationToken
                };
                Next();
            }
            Previous();
            return(left);
        }
예제 #2
0
        public void Visit(BinaryOpNode node)
        {
            node.Left.Accept(this);
            node.Right.Accept(this);
            switch (node.Operator)
            {
            case "+":
                il.Emit(OpCodes.Add);
                break;

            case "-":
                il.Emit(OpCodes.Sub);
                break;

            case "*":
                il.Emit(OpCodes.Mul);
                break;

            case "/":
                il.Emit(OpCodes.Div);
                break;

            default:
                OnCodeGenError(new SemanticErrorEventArgs(String.Format("Unknown operator {0}", node.Operator)));
                break;
            }
        }
예제 #3
0
        public override dynamic Visit(BinaryOpNode node)
        {
            var left  = node.Left.Accept(this);
            var right = node.Right.Accept(this);

            var op = node.Op;

            var ops = (OperatorType[])PermittedOperations[left];

            var type = left;

            if (left != right || left == right && !ops.Contains(op))
            {
                Context.ErrorService.Add(
                    ErrorType.Unknown,
                    node.Token,
                    $"type error: can't perform {left} {op} {right}"
                    );
                type = PrimitiveType.Error;
            }
            else
            {
                type = RelationalOperators.Contains(op)
                    ? PrimitiveType.Boolean
                    : left;
            }
            // throw new Exception($"type error: can't perform {left} {op} {right}");

            node.Type = new SimpleTypeNode
            {
                PrimitiveType = type
            };
            return(type);
        }
예제 #4
0
        private bool ResolveNullCheck(BinaryOpNode node, out int index)
        {
            LoadConstNode constNode;
            LoadFieldNode fieldNode;

            if (node.Left is LoadFieldNode && node.Right is LoadConstNode)
            {
                constNode = (LoadConstNode)node.Right;
                fieldNode = (LoadFieldNode)node.Left;
            }
            else if (node.Right is LoadFieldNode && node.Left is LoadConstNode)
            {
                fieldNode = (LoadFieldNode)node.Right;
                constNode = (LoadConstNode)node.Left;
            }
            else
            {
                index = 0;
                return(false);
            }

            if (constNode.Value != null)
            {
                index = 0;
                return(false);
            }

            index = fieldNode.PropertyIndex;

            return(true);
        }
예제 #5
0
        public static bool TryGetExpectedTypeForBinaryOp(TexlBinding binding, TexlNode curNode, int cursorPos, out DType expectedType)
        {
            // If we are in a binary operation context, the expected type is relative to the binary operation.
            if (curNode != null && curNode.Parent != null && curNode.Parent.Kind == NodeKind.BinaryOp)
            {
                BinaryOpNode binaryOpNode = curNode.Parent.CastBinaryOp();
                DType        coercedType;
                TexlNode     expectedNode = null;
                if (cursorPos < binaryOpNode.Token.Span.Min)
                {
                    // Cursor is before the binary operator. Expected type is equal to the type of right side.
                    expectedNode = binaryOpNode.Right;
                }
                else if (cursorPos > binaryOpNode.Token.Span.Lim)
                {
                    // Cursor is after the binary operator. Expected type is equal to the type of left side.
                    expectedNode = binaryOpNode.Left;
                }

                if (expectedNode != null)
                {
                    expectedType = binding.TryGetCoercedType(expectedNode, out coercedType) ? coercedType : binding.GetType(expectedNode);
                    return(true);
                }
            }

            expectedType = DType.Error;
            return(false);
        }
예제 #6
0
        public InOpDelegationStrategy(BinaryOpNode node, TexlFunction function) : base(BinaryOp.In, function)
        {
            Contracts.AssertValue(node);
            Contracts.Assert(node.Op == BinaryOp.In);

            _binaryOpNode = node;
        }
예제 #7
0
        public override bool IsSupportedOpNode(TexlNode node, OperationCapabilityMetadata metadata, TexlBinding binding)
        {
            Contracts.AssertValue(node);
            Contracts.AssertValue(metadata);
            Contracts.AssertValue(binding);

            BinaryOpNode binaryOpNode = node?.AsBinaryOp();

            if (binaryOpNode == null)
            {
                return(false);
            }

            var isRHSDelegableTable = IsRHSDelegableTable(binding, binaryOpNode, metadata);

            DName         columnName = default;
            FirstNameInfo info       = null;

            bool isFullyQualifiedFieldAccess = CheckForFullyQualifiedFieldAccess(isRHSDelegableTable, binaryOpNode, binding, node, ref columnName, ref info);

            if (!isFullyQualifiedFieldAccess)
            {
                return(false);
            }

            bool isRowScopedOrLambda = IsRowScopedOrLambda(binding, node, info, columnName, metadata);

            if (!isRowScopedOrLambda)
            {
                return(false);
            }

            return(base.IsSupportedOpNode(node, metadata, binding));
        }
예제 #8
0
        private bool DoCoercionCheck(BinaryOpNode binaryOpNode, OperationCapabilityMetadata metadata, TexlBinding binding)
        {
            Contracts.AssertValue(binaryOpNode);
            Contracts.AssertValue(metadata);
            Contracts.AssertValue(binding);

            DType leftType  = binding.GetType(binaryOpNode.Left);
            DType rightType = binding.GetType(binaryOpNode.Right);

            switch (leftType.Kind)
            {
            case DKind.Date:
                if (rightType.Kind == DKind.DateTime)
                {
                    // If rhs is a column of type DateTime and lhs is row scoped then we will need to apply the coercion on rhs. So check if coercion function date is supported or not.
                    if (IsColumnNode(binaryOpNode.Right, binding) && binding.IsRowScope(binaryOpNode.Left))
                    {
                        return(IsDelegatableColumnNode(binaryOpNode.Right.AsFirstName(), binding, null, DelegationCapability.Date));
                    }

                    // If lhs is rowscoped but not a field reference and rhs is rowscoped then we need to check if it's supported at table level.
                    if (binding.IsRowScope(binaryOpNode.Left) && binding.IsRowScope(binaryOpNode.Right))
                    {
                        return(metadata.IsDelegationSupportedByTable(DelegationCapability.Date));
                    }

                    return(true);
                }

                break;

            case DKind.DateTime:
                if (rightType.Kind == DKind.Date)
                {
                    // If lhs is a column of type DateTime and RHS is also row scoped then check if coercion function date is supported or not.
                    if (IsColumnNode(binaryOpNode.Left, binding) && binding.IsRowScope(binaryOpNode.Right))
                    {
                        return(IsDelegatableColumnNode(binaryOpNode.Left.AsFirstName(), binding, null, DelegationCapability.Date));
                    }

                    // If lhs is rowscoped but not a field reference and rhs is rowscoped then we need to check if it's supported at table level.
                    if (binding.IsRowScope(binaryOpNode.Left) && binding.IsRowScope(binaryOpNode.Right))
                    {
                        return(metadata.IsDelegationSupportedByTable(DelegationCapability.Date));
                    }

                    return(true);
                }

                break;

            default:
                break;
            }

            return(true);
        }
예제 #9
0
 public ExpressionNode Optimize(ExpressionNode expression)
 {
     return(expression switch
     {
         UnaryOpNode unaryOp => Optimize(unaryOp),
         BinaryOpNode binOp => Optimize(binOp),
         FunctionNode func => Optimize(func),
         _ => expression
     });
예제 #10
0
        public override dynamic Visit(BinaryOpNode node)
        {
            node.Left  = Replace(node.Left);
            node.Right = Replace(node.Right);

            node.Left.Accept(this);
            node.Right.Accept(this);

            return(null);
        }
예제 #11
0
        private bool IsPredicate(ExpressionNode node)
        {
            while (node is UnaryOpNode)
            {
                node = ((UnaryOpNode)node).Right;
            }
            BinaryOpNode binaryOpNode = node as BinaryOpNode;

            return(binaryOpNode != null && (binaryOpNode.Left is NameNode || binaryOpNode.Right is NameNode));
        }
예제 #12
0
        protected override Expression VisitBinary(BinaryExpression node)
        {
            MtBinaryOp op;

            switch (node.NodeType)
            {
            case ExpressionType.Equal:
                op = MtBinaryOp.Eq;
                break;

            case ExpressionType.NotEqual:
                op = MtBinaryOp.Neq;
                break;

            case ExpressionType.GreaterThan:
                op = MtBinaryOp.Gt;
                break;

            case ExpressionType.GreaterThanOrEqual:
                op = MtBinaryOp.Gte;
                break;

            case ExpressionType.LessThan:
                op = MtBinaryOp.Lt;
                break;

            case ExpressionType.LessThanOrEqual:
                op = MtBinaryOp.Lte;
                break;

            case ExpressionType.AndAlso:
                op = MtBinaryOp.And;
                break;

            case ExpressionType.OrElse:
                op = MtBinaryOp.Or;
                break;

            default:
                throw new ArgumentOutOfRangeException("Unsupported operation: " + node.NodeType);
            }

            var ast = new BinaryOpNode(op);

            Visit(node.Left);
            Visit(node.Right);

            ast.Right = _stack.Pop();
            ast.Left  = _stack.Pop();

            _stack.Push(ast);

            return(node);
        }
예제 #13
0
 public override void VisitBinaryOpNode(BinaryOpNode binop)
 {
     if (binop == null)
     {
         return;
     }
     if (binop.LeftNode != null)
     {
         binop.LeftNode.Visit(this);
     }
     binop.RightNode.Visit(this);
 }
예제 #14
0
파일: Parser.cs 프로젝트: muscar/JasonSharp
        private INode ParseExpression()
        {
            var exp = ParseTerm();

            while (tokens.Current.Kind == TokenKind.Plus || tokens.Current.Kind == TokenKind.Minus)
            {
                var op = tokens.Current.Contents;
                tokens.MoveNext();
                exp = new BinaryOpNode(op, exp, ParseExpression());
            }
            return(exp);
        }
예제 #15
0
파일: Parser.cs 프로젝트: muscar/JasonSharp
        private INode ParseTerm()
        {
            var exp = ParseAtom();

            while (tokens.Current.Kind == TokenKind.Mul || tokens.Current.Kind == TokenKind.Div)
            {
                var op = tokens.Current.Contents;
                tokens.MoveNext();
                exp = new BinaryOpNode(op, exp, ParseTerm());
            }
            return(exp);
        }
예제 #16
0
        private FilterLogicalOperator GetCompositeFilterDescriptorLogicalOperator(
            ExpressionNode binaryNode)
        {
            ExpressionNode expressionNode = binaryNode;

            for (UnaryOpNode unaryOpNode = expressionNode as UnaryOpNode; unaryOpNode != null && unaryOpNode.Op == Operator.Noop; unaryOpNode = expressionNode as UnaryOpNode)
            {
                expressionNode = unaryOpNode.Right;
            }
            BinaryOpNode binaryOpNode = expressionNode as BinaryOpNode;

            return(binaryOpNode != null && binaryOpNode.Op == Operator.Or ? FilterLogicalOperator.Or : FilterLogicalOperator.And);
        }
예제 #17
0
        public override void VisitBinaryOpNode(BinaryOpNode binop)
        {
            Text += "(";

            if (binop.LeftNode != null)
            {
                binop.LeftNode.Visit(this);
            }

            Text += " " + ConvertOpType(binop.OpType) + " ";
            binop.RightNode.Visit(this);
            Text += ")";
        }
예제 #18
0
        private AstNode BuildKeyPropertyExpression(Manifest curManifest, MtTypeDefinition type)
        {
            var pk = curManifest.GetPrimaryKey();

            if (pk.Length == 0)
            {
                return(null);
            }

            AstNode root         = null;
            var     manifestType = curManifest.GetType();

            foreach (var pkProp in pk)
            {
                var member = manifestType.GetProperty(pkProp);

                if (member == null)
                {
                    throw new Exception(string.Format("Failed to find property '{0}' specified as part of primary key. Manifest {1}", pkProp, manifestType));
                }

                var value  = member.GetValue(curManifest);
                var mtProp = type.Properties.FirstOrDefault(x => x.Name == pkProp);

                if (mtProp == null)
                {
                    throw new Exception(string.Format("Failed to find MT property '{0}' specified as part of primary key. Manifest {1}", pkProp, manifestType));
                }

                var op = new BinaryOpNode(MtBinaryOp.Eq)
                {
                    Left  = new LoadFieldNode(mtProp.Index),
                    Right = new LoadConstNode(value)
                };

                if (root == null)
                {
                    root = op;
                }
                else
                {
                    root = new BinaryOpNode(MtBinaryOp.And)
                    {
                        Left  = root,
                        Right = op
                    };
                }
            }

            return(root);
        }
예제 #19
0
        private static INode Parse(Tokens tokens)
        {
            return(ParseBinary());

            INode ParseBinary()
            {
                var lhs = ParseLeaf();

                while (true)
                {
                    Func <long, long, long>?op = tokens.CurrentToken switch
                    {
                        PlusToken => (a, b) => a + b,
                        MultiplyToken => (a, b) => a * b,
                        _ => null
                    };

                    if (op is null)
                    {
                        return(lhs);
                    }

                    tokens.MoveNext();
                    lhs = new BinaryOpNode(lhs, ParseLeaf(), op);
                }
            }

            INode ParseLeaf()
            {
                if (tokens.CurrentToken is NumberToken number)
                {
                    tokens.MoveNext();
                    return(new NumberNode(number.Value));
                }

                if (tokens.CurrentToken is OpenParenthesisToken)
                {
                    tokens.MoveNext();
                    var node = ParseBinary();
                    if (tokens.CurrentToken is not CloseParenthesisToken)
                    {
                        throw new InvalidOperationException("Missing close parenthesis");
                    }
                    tokens.MoveNext();
                    return(node);
                }

                throw new InvalidOperationException("Not a leaf");
            }
        }
예제 #20
0
        // For binary op node args, we need to use filter delegation strategy. Hence we override this method here.
        public override IOpDelegationStrategy GetOpDelegationStrategy(BinaryOp op, BinaryOpNode opNode)
        {
            Contracts.AssertValueOrNull(opNode);

            if (op == BinaryOp.In)
            {
                Contracts.AssertValue(opNode);
                Contracts.Assert(opNode.Op == op);

                return(new InOpDelegationStrategy(opNode, BuiltinFunctionsCore.Filter));
            }

            return(new DefaultBinaryOpDelegationStrategy(op, BuiltinFunctionsCore.Filter));
        }
예제 #21
0
        public bool CheckForFullyQualifiedFieldAccess(bool isRHSDelegableTable, BinaryOpNode binaryOpNode, TexlBinding binding, TexlNode node, ref DName columnName, ref FirstNameInfo info)
        {
            Contracts.AssertValue(binaryOpNode);
            Contracts.AssertValue(binding);
            Contracts.AssertValue(node);

            // Check for fully qualified field access
            var firstNameNode  = isRHSDelegableTable ? binaryOpNode.Left?.AsFirstName() : binaryOpNode.Right?.AsFirstName();
            var dottedNameNode = isRHSDelegableTable ? binaryOpNode.Left?.AsDottedName() : binaryOpNode.Right?.AsDottedName();

            if (dottedNameNode != null && dottedNameNode.Left is FirstNameNode possibleScopeAccess && (info = binding.GetInfo(possibleScopeAccess))?.Kind == BindKind.LambdaFullRecord)
            {
                columnName = dottedNameNode.Right.Name;
            }
예제 #22
0
        public bool IsRHSDelegableTable(TexlBinding binding, BinaryOpNode binaryOpNode, OperationCapabilityMetadata metadata)
        {
            Contracts.AssertValue(binding);
            Contracts.AssertValue(binaryOpNode);
            Contracts.AssertValue(metadata);

            var rightNodeType = binding.GetType(binaryOpNode.Right);

            var hasEnhancedDelegation = binding.Document.Properties.EnabledFeatures.IsEnhancedDelegationEnabled;
            var isColumn = rightNodeType?.IsColumn == true;
            var isDelegationSupportedByTable = metadata.IsDelegationSupportedByTable(DelegationCapability.CdsIn);
            var HasLeftFirstNameNodeOrIsFullRecordRowScopeAccess = binaryOpNode.Left?.AsFirstName() != null || binding.IsFullRecordRowScopeAccess(binaryOpNode.Left);

            return(hasEnhancedDelegation && isColumn && isDelegationSupportedByTable && HasLeftFirstNameNodeOrIsFullRecordRowScopeAccess);
        }
예제 #23
0
        public override LazyList <string> Visit(BinaryOpNode node, Context context)
        {
            Contracts.AssertValue(node);

            if (node.Token.Kind == TokKind.PercentSign)
            {
                return(Basic(node, context));
            }

            Precedence precedence;

            if (!binaryPrecedence.TryGetValue(node.Op, out precedence))
            {
                Contracts.Assert(false, "Couldn't find precedence for " + node.Op);
                precedence = Precedence.Error;
            }

            var builder   = LazyList <string> .Empty;
            var firstNode = true;

            foreach (var source in node.SourceList.Sources.Where(source => !(source is WhitespaceSource)))
            {
                var leftOrRight = source as NodeSource;
                if (leftOrRight != null)
                {
                    if (firstNode)
                    {
                        builder = builder
                                  .With(leftOrRight.Node.Accept(this, context))
                                  .With(" ");
                        firstNode = false;
                    }
                    else
                    {
                        builder = builder
                                  .With(" ")
                                  .With(leftOrRight.Node.Accept(this, context));
                    }
                }
                else
                {
                    builder = builder.With(source.Tokens.Select(GetScriptForToken));
                }
            }

            return(builder);
        }
            internal override bool TryAddSuggestionsForNodeKind(IntellisenseData.IntellisenseData intellisenseData)
            {
                Contracts.AssertValue(intellisenseData);

                TexlNode curNode = intellisenseData.CurNode;
                // Cursor is in the operation token.
                // Suggest binary operators.
                BinaryOpNode binaryOpNode = curNode.CastBinaryOp();
                var          tokenSpan    = binaryOpNode.Token.Span;

                string keyword           = binaryOpNode.Op == BinaryOp.Error ? tokenSpan.GetFragment(intellisenseData.Script) : TexlParser.GetTokString(binaryOpNode.Token.Kind);
                int    replacementLength = tokenSpan.Min == intellisenseData.CursorPos ? 0 : tokenSpan.Lim - tokenSpan.Min;

                intellisenseData.SetMatchArea(tokenSpan.Min, intellisenseData.CursorPos, replacementLength);
                intellisenseData.BoundTo = binaryOpNode.Op == BinaryOp.Error ? string.Empty : keyword;
                AddSuggestionsForBinaryOperatorKeyWords(intellisenseData);

                return(true);
            }
예제 #25
0
        public override bool PreVisit(BinaryOpNode node)
        {
            Contracts.AssertValue(node);

            // Cursor is in the left node.
            if (_cursorPosition <= node.Token.Span.Min)
            {
                node.Left.Accept(this);
                return(false);
            }

            // Cursor is inside the operation token.
            if (_cursorPosition <= node.Token.Span.Lim)
            {
                _result = node;
                return(false);
            }

            node.Right.Accept(this);
            return(false);
        }
예제 #26
0
        private bool IsPredicate(ExpressionNode node)
        {
            while (node is UnaryOpNode)
            {
                node = ((UnaryOpNode)node).Right;
            }

            BinaryOpNode binaryNode = node as BinaryOpNode;

            if (binaryNode == null)
            {
                return(false);
            }

            if (binaryNode.Left is NameNode || binaryNode.Right is NameNode)
            {
                return(true);
            }

            return(false);
        }
예제 #27
0
        }/// <summary>

        /// /
        /// </summary>
        /// <param name="functionA"></param>
        /// <param name="operations"></param>
        /// <param name="functionB"></param>
        /// <returns></returns>
        public INode ArithmeticBinaryOperation(Func <INode> functionA, List <TokenType> operations = null, Func <INode> functionB = null)
        {
            if (functionB == null)
            {
                functionB = functionA;
            }
            var left = functionA();

            Next();
            while (operations.Contains(CurrentToken.TokenType))
            {
                var operationToken = CurrentToken;
                Next();
                var right = functionB();
                left = new BinaryOpNode {
                    Left = left, Right = right, Operation = operationToken
                };
                Next();
            }
            Previous();
            return(left);
        }
예제 #28
0
        private FilterDescriptor CreateFilterDescriptor(BinaryOpNode binaryNode)
        {
            NameNode  node = binaryNode.Left as NameNode;
            ConstNode val  = binaryNode.Right as ConstNode;

            if (node == null)
            {
                node = binaryNode.Right as NameNode;
                val  = binaryNode.Left as ConstNode;
            }

            if (node == null)
            {
                throw new ArgumentException("Invalid BinaryOpNode parameter");
            }

            FilterDescriptor filterDescriptor = new FilterDescriptor();

            filterDescriptor.PropertyName = ((NameNode)node).Name;
            filterDescriptor.Value        = val.Value;
            filterDescriptor.Operator     = this.GetOperator(binaryNode.Op);
            return(filterDescriptor);
        }
예제 #29
0
        public override dynamic Visit(BinaryOpNode node)
        {
            var left  = node.Left.Accept(this);
            var right = node.Right.Accept(this);
            var op    = node.Token.Content;

            if (left == null || right == null)
            {
                return(null);
            }

            // TODO: this has no division by zero check and what have you

            return(op switch
            {
                "+" when !(left is bool) => (left + right),
                "-" when left is int || left is float => (left - right),
                "/" when(left is int || left is float) && right > 0 => (left / right),
                "/" when(left is int || left is float) && right == 0 => Context.ErrorService.Add(
                    ErrorType.Unknown,
                    node.Token,
                    $"division by zero"
                    ),
                "*" when left is int || left is float => (left * right),
                "%" when left is int => (left % right),
                "and" when left is bool => (left && right),
                "or" when left is bool => (left || right),
                "<" => (left < right),
                "<=" => (left <= right),
                ">" => (left > right),
                ">=" => (left >= right),
                "<>" => (left != right),
                "=" => (left == right),
                _ => null
                // error already reported before
                //throw new Exception($"invalid operation {op} on {left} {right}")
            });
예제 #30
0
        public override void VisitBinaryOpNode(BinaryOpNode binop)
        {
            if (binop == null)
            {
                return;
            }

            var line = new ThreeAddrLine();

            line.Accum = GenNewTemporaryVariable();

            if (binop.LeftNode != null)
            {
                binop.LeftNode.Visit(this);
                line.LeftOp = GetLastLine().Accum;
            }

            binop.RightNode.Visit(this);
            line.RightOp = GetLastLine().Accum;
            line.OpType  = ToStringHelper.ToString(binop.OpType);
            line.Label   = GenNewLabel();

            Data.Add(line);
        }