protected override CrawlSyntaxNode VisitMultiChildExpression(MultiChildExpressionNode multiChildExpression)
        {
            var expr = (MultiChildExpressionNode)base.VisitMultiChildExpression(multiChildExpression);

            if (!(expr.ExpressionType == ExpressionType.Add ||
                  expr.ExpressionType == ExpressionType.Multiply ||
                  expr.ExpressionType == ExpressionType.ShortCircuitAnd ||
                  expr.ExpressionType == ExpressionType.ShortCircuitOr))
            {
                return(expr);
            }

            List <ExpressionNode> literals = new List <ExpressionNode>();
            List <ExpressionNode> restOfIt = new List <ExpressionNode>();

            foreach (ExpressionNode expression in expr.Arguments)
            {
                var literal = expression as LiteralNode;

                if (literal != null)
                {
                    literals.Add(literal);
                }
                else
                {
                    restOfIt.Add(expression);
                }
            }

            List <ExpressionNode> newArguments = literals.Concat(restOfIt).ToList();

            return(CrawlSyntaxNode.MultiChildExpression(expr.Interval, expr.ExpressionType, expr.ResultType,
                                                        newArguments));
        }
        protected override CrawlSyntaxNode VisitMultiChildExpression(MultiChildExpressionNode multiChildExpression)
        {
            CrawlSyntaxNode          expr      = base.VisitMultiChildExpression(multiChildExpression);
            MultiChildExpressionNode multuExpr = expr as MultiChildExpressionNode;

            if (multuExpr == null)
            {
                return(expr);
            }

            if (multuExpr.Arguments.ChildCount == 1)
            {
                OptimizationsWereMade = true;
                return(multuExpr.Arguments.First());
            }

            List <ExpressionNode>     newArguments = new List <ExpressionNode>();
            ListNode <ExpressionNode> arguments    = multuExpr.Arguments;


            //Algorithm ahead. Strap in.
            //Go through the node's arguments, building list of new arguments,
            //where any pair of neighboring literals have been folded into one.
            int i = 0;

            while (i < arguments.Count())
            {
                //If this is the last in the sequence, there is nothing left to fold.
                if (i == arguments.Count() - 1)
                {
                    newArguments.Add(arguments[i]);
                    break;
                }

                //Only literal nodes can be folded.
                LiteralNode current = arguments[i] as LiteralNode;
                if (current != null)
                {
                    //If both the current node and the next node is a literal, then
                    //fold them, add them to the new list,
                    //and jump to the argument after them.
                    LiteralNode next = arguments[i + 1] as LiteralNode;
                    if (next != null)
                    {
                        newArguments.Add(FoldMultuPair(current, multuExpr.ExpressionType, next));
                        OptimizationsWereMade = true;
                        i += 2;
                    }
                    //If the next argument is not a literal, it cannot be folded.
                    //move on to the argument after that.
                    else
                    {
                        newArguments.Add(arguments[i]);
                        newArguments.Add(arguments[i + 1]);
                        i += 2;
                    }
                }
                //If the current node isn't a literal,
                //move on to consider the next
                else
                {
                    newArguments.Add(arguments[i]);
                    i += 1;
                }
            }

            return(CrawlSyntaxNode.MultiChildExpression(multuExpr.Interval, multuExpr.ExpressionType,
                                                        multuExpr.ResultType, newArguments));
        }