示例#1
0
        public void VisitUnaryExpression(AstUnaryExpression unaryExpression)
        {
            Assert.IsType <AstUnaryExpression>(this.expected);
            var expectedAst = (AstUnaryExpression)this.expected;

            Assert.Equal(expectedAst.Operator, unaryExpression.Operator);

            AssertVisit(expectedAst.Expression, unaryExpression.Expression);
        }
示例#2
0
        internal void ParseExpression_UnaryExpression_SupportForPlusOperator()
        {
            var expectedAst = new AstUnaryExpression
            {
                Operator   = CmdTokenKind.Plus,
                Expression = new AstNumberExpression
                {
                    Value = "6"
                }
            };

            AstAssert.Expression(expectedAst, "+6");
        }
示例#3
0
        public void Visit(AstUnaryExpression expr)
        {
            var opName =
                String.IsNullOrEmpty(expr.OperatorSymbol)
                    ? expr.OperatorName
                    : expr.OperatorSymbol;

            var node =
                StepsCluster
                .AddNode(NodeInfo.NodeName)
                .SetLabel(opName.Bold());

            FollowExpression(expr.Operand, node.ToNodeRef(DotCompass.West));
        }
示例#4
0
            public override AstNode VisitUnaryExpression(AstUnaryExpression node)
            {
                var root = AstExpression.Var("ROOT", isCurrent: true);

                if (TryOptimizeSizeOfElements(out var optimizedExpression))
                {
                    return(optimizedExpression);
                }

                if (TryOptimizeAccumulatorOfElements(out optimizedExpression))
                {
                    return(optimizedExpression);
                }

                if (TryOptimizeAccumulatorOfMappedElements(out optimizedExpression))
                {
                    return(optimizedExpression);
                }

                return(base.VisitUnaryExpression(node));

                bool TryOptimizeSizeOfElements(out AstExpression optimizedExpression)
                {
                    // { $size : "$_elements" } => { __agg0 : { $sum : 1 } } + "$__agg0"
                    if (node.Operator == AstUnaryOperator.Size)
                    {
                        if (node.Arg is AstGetFieldExpression argGetFieldExpression &&
                            argGetFieldExpression.FieldName is AstConstantExpression constantFieldNameExpression &&
                            constantFieldNameExpression.Value.IsString &&
                            constantFieldNameExpression.Value.AsString == "_elements")
                        {
                            var accumulatorExpression = AstExpression.AccumulatorExpression(AstAccumulatorOperator.Sum, 1);
                            var accumulatorFieldName  = _accumulators.AddAccumulatorExpression(accumulatorExpression);
                            optimizedExpression = AstExpression.GetField(root, accumulatorFieldName);
                            return(true);
                        }
                    }

                    optimizedExpression = null;
                    return(false);
                }

                bool TryOptimizeAccumulatorOfElements(out AstExpression optimizedExpression)
                {
                    // { $accumulator : { $getField : { input : "$$ROOT", field : "_elements" } } } => { __agg0 : { $accumulator : "$$ROOT" } } + "$__agg0"
                    if (node.Operator.IsAccumulator(out var accumulatorOperator) &&
                        node.Arg is AstGetFieldExpression getFieldExpression &&
                        getFieldExpression.FieldName is AstConstantExpression getFieldConstantFieldNameExpression &&
                        getFieldConstantFieldNameExpression.Value.IsString &&
                        getFieldConstantFieldNameExpression.Value == "_elements" &&
                        getFieldExpression.Input is AstVarExpression getFieldInputVarExpression &&
                        getFieldInputVarExpression.Name == "ROOT")
                    {
                        var accumulatorExpression = AstExpression.AccumulatorExpression(accumulatorOperator, root);
                        var accumulatorFieldName  = _accumulators.AddAccumulatorExpression(accumulatorExpression);
                        optimizedExpression = AstExpression.GetField(root, accumulatorFieldName);
                        return(true);
                    }

                    optimizedExpression = null;
                    return(false);
                }

                bool TryOptimizeAccumulatorOfMappedElements(out AstExpression optimizedExpression)
                {
                    // { $accumulator : { $map : { input : { $getField : { input : "$$ROOT", field : "_elements" } }, as : "x", in : f(x) } } } => { __agg0 : { $accumulator : f(x => root) } } + "$__agg0"
                    if (node.Operator.IsAccumulator(out var accumulatorOperator) &&
                        node.Arg is AstMapExpression mapExpression &&
                        mapExpression.Input is AstGetFieldExpression mapInputGetFieldExpression &&
                        mapInputGetFieldExpression.FieldName is AstConstantExpression mapInputconstantFieldExpression &&
                        mapInputconstantFieldExpression.Value.IsString &&
                        mapInputconstantFieldExpression.Value.AsString == "_elements" &&
                        mapInputGetFieldExpression.Input is AstVarExpression mapInputGetFieldVarExpression &&
                        mapInputGetFieldVarExpression.Name == "ROOT")
                    {
                        var rewrittenArg          = (AstExpression)AstNodeReplacer.Replace(mapExpression.In, (mapExpression.As, root));
                        var accumulatorExpression = AstExpression.AccumulatorExpression(accumulatorOperator, rewrittenArg);
                        var accumulatorFieldName  = _accumulators.AddAccumulatorExpression(accumulatorExpression);
                        optimizedExpression = AstExpression.GetField(root, accumulatorFieldName);
                        return(true);
                    }

                    optimizedExpression = null;
                    return(false);
                }
            }