Пример #1
0
        /// <summary>
        /// Deal with the aggregate operator coming in here.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <returns></returns>
        public Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode _codeEnv, ICodeContext context, CompositionContainer container)
        {
            ///
            /// Basic code checks
            ///

            AggregateFromSeedResultOperator a = resultOperator as AggregateFromSeedResultOperator;

            if (a == null)
            {
                throw new ArgumentNullException("result Operator must not be null and must be of type AggregateFromSeedResultOperator!");
            }

            if (a.Func.Parameters.Count != 1)
            {
                throw new InvalidOperationException("Aggregate only allows for a function with one parameters!");
            }

            if (a.OptionalResultSelector != null)
            {
                throw new NotImplementedException("Can't do a selector function yet");
            }

            // We need to declare a variable to hold the seed and its updates - the accumulator
            // We then need to write the code that does the update to the seed.
            // Finally, if there is a final function, we need to call that after the loop is done!
            var accumulator = DeclarableParameter.CreateDeclarableParameterExpression(a.Seed.Type);

            var newGC = new GeneratedCode(blockShouldBeBraced: false);
            var newCC = new CodeContext();

            accumulator.InitialValue = ExpressionToCPP.GetExpression(a.Seed, newGC, newCC, container);
            if (newGC.CodeBody.Statements.Count() > 0)
            {
                accumulator.InitialValueCode = newGC;
            }
            _codeEnv.QueueForTransferFromGC(newGC);

            ///
            /// Now, parse the lambda expression, doing a substitution with this guy! Note that the only argument is our
            /// accumulator - the other arguments have all been replaced with subqueryexpressions and the like!
            ///

            var p1           = context.Add(a.Func.Parameters[0].Name, accumulator);
            var funcResolved = ExpressionToCPP.GetExpression(a.Func.Body, _codeEnv, context, container);

            p1.Pop();

            if (accumulator.RawValue != funcResolved.RawValue)
            {
                _codeEnv.Add(new Statements.StatementAggregate(accumulator, funcResolved));
            }

            return(accumulator);
        }