예제 #1
0
        public void TypeOfSequence()
        {
            var qmb = new QueryModelBuilder();
            qmb.AddClause(new SelectClause(Expression.Constant(1.0)));
            int[] list = new int[10];
            qmb.AddClause(new MainFromClause("r1", typeof(int), Expression.Constant(list)));

            var h = new QMFuncHeader() { Arguments = new object[] { }, IsSequence = true, QM = qmb.Build(), QMText = "hi" };
            var src = new QMFuncSource(h);
            Assert.AreEqual(typeof(double[]), src.ResultType, "result type");

            Assert.AreEqual(typeof(double[]), src.CacheVariable.Type, "Type of cache");
            Assert.AreEqual(typeof(bool), src.CacheVariableGood.Type, "Type of the cache good flag");
        }
예제 #2
0
        /// <summary>
        /// Create the QM Func Source starting from a pre-parsed bunch of header info.
        /// </summary>
        /// <param name="f"></param>
        public QMFuncSource(QMFuncHeader f)
        {
            this._header   = f;
            Name           = "QMFunction".CreateUniqueVariableName();
            Arguments      = f.Arguments.Select(a => new QMFunctionArgument(a));
            StatementBlock = null;

            // If this is a sequence, then we need to get a non-normal type.
            if (_header.IsSequence)
            {
                _sequenceType = _header.QM.GetResultType().GetGenericArguments().First();
                _sequenceType = _sequenceType.MakeArrayType();
            }

            // Now we can create the cached variables, etc.
            CacheVariable     = DeclarableParameter.CreateDeclarableParameterExpression(ResultType);
            CacheVariableGood = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool));
        }
예제 #3
0
            /// <summary>
            /// The main entry point that we watch - we generate a method info stub when we need it
            /// from this.
            /// </summary>
            /// <param name="queryModel"></param>
            public override void VisitQueryModel(QueryModel queryModel)
            {
                // If the type is something that is friendly to be returned from a
                // method, then we should cache this guy.

                _qmContextStack.Push(new QMContext());

                // Now, run through the query model.

                base.VisitQueryModel(queryModel);

                // And if the QM result type is something we can reasonably cache, then we should do it.
                //  - Do not cache the outter most QM. This guy has the best place to start combining things.
                //  - Do not cache anything that is enumerable. We'll have to deal with that later.
                //  - Do not cache any anonymous types
                //  - Deal with later somethign that is an iterator (used in a later loop).

                var isEnumerable   = typeof(IEnumerable).IsAssignableFrom(queryModel.GetResultType());
                var selectSequence = !queryModel.ResultOperators.Any();

                if (_qmContextStack.Count > 1 &&
                    ((selectSequence && isGoodSelectSequenceType(queryModel.GetResultType())) || !isEnumerable) &&
                    !queryModel.GetResultType().IsClass
                    )
                {
                    var qmText = FormattingQueryVisitor.Format(queryModel);
                    if (!FoundFunctions.Where(ff => ff.QMText == qmText).Any())
                    {
                        var sref = _qmContextStack.Peek();
                        var f    = new QMFuncHeader()
                        {
                            QM         = queryModel,
                            QMText     = qmText,
                            Arguments  = sref._arguments.Cast <object>(),
                            IsSequence = selectSequence
                        };
                        FoundFunctions.Add(f);
                    }
                }

                // Go back to working on the previous qm.
                _qmContextStack.Pop();
            }
예제 #4
0
        /// <summary>
        /// Create the QM Func Source starting from a pre-parsed bunch of header info.
        /// </summary>
        /// <param name="f"></param>
        public QMFuncSource(QMFuncHeader f)
        {
            this._header = f;
            Name = "QMFunction".CreateUniqueVariableName();
            Arguments = f.Arguments.Select(a => new QMFunctionArgument(a));
            StatementBlock = null;

            // If this is a sequence, then we need to get a non-normal type.
            if (_header.IsSequence)
            {
                _sequenceType = _header.QM.GetResultType().GetGenericArguments().First();
                _sequenceType = _sequenceType.MakeArrayType();
            }

            // Now we can create the cached variables, etc.
            CacheVariable = DeclarableParameter.CreateDeclarableParameterExpression(ResultType);
            CacheVariableGood = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool));

        }
예제 #5
0
        /// <summary>
        /// Generate a function with no arguments that returns an int given that name. The
        /// actual statement is a very simple constant.
        /// </summary>
        /// <param name="fname"></param>
        /// <returns></returns>
        public static QMFuncSource GenerateFunction()
        {
            int[] ints = new int[10];
            var qmb = new QueryModelBuilder();
            qmb.AddClause(new MainFromClause("i", typeof(int), Expression.Constant(ints)));
            qmb.AddClause(new SelectClause(Expression.Constant(1)));
            qmb.AddResultOperator(new Remotion.Linq.Clauses.ResultOperators.CountResultOperator());

            var h = new QMFuncHeader() { Arguments = new object[] { }, QM = qmb.Build() };
            h.QMText = h.QM.ToString();
            var f = new QMFuncSource(h);

            var p = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            var st = new StatementAssign(p, new ValSimple("5", typeof(int)));
            var inlineblock = new StatementInlineBlock();
            inlineblock.Add(st);
            inlineblock.Add(new StatementReturn(p));
            f.SetCodeBody(inlineblock);

            return f;
        }
예제 #6
0
 /// <summary>
 /// Empty ctor.
 /// </summary>
 public QMFuncSource()
 {
     this._header = null;
 }
예제 #7
0
            /// <summary>
            /// The main entry point that we watch - we generate a method info stub when we need it
            /// from this.
            /// </summary>
            /// <param name="queryModel"></param>
            public override void VisitQueryModel(QueryModel queryModel)
            {
                // If the type is something that is friendly to be returned from a
                // method, then we should cache this guy.

                _qmContextStack.Push(new QMContext());

                // Now, run through the query model.

                base.VisitQueryModel(queryModel);

                // And if the QM result type is something we can reasonably cache, then we should do it.
                //  - Do not cache the outter most QM. This guy has the best place to start combining things.
                //  - Do not cache anything that is enumerable. We'll have to deal with that later.
                //  - Do not cache any anonymous types
                //  - Deal with later somethign that is an iterator (used in a later loop).

                var isEnumerable = typeof(IEnumerable).IsAssignableFrom(queryModel.GetResultType());
                var selectSequence = !queryModel.ResultOperators.Any();
                if (_qmContextStack.Count > 1
                    && ((selectSequence && isGoodSelectSequenceType(queryModel.GetResultType())) || !isEnumerable)
                    && !queryModel.GetResultType().IsClass
                    )
                {
                    var qmText = FormattingQueryVisitor.Format(queryModel);
                    if (!FoundFunctions.Where(ff => ff.QMText == qmText).Any())
                    {
                        var sref = _qmContextStack.Peek();
                        var f = new QMFuncHeader()
                        {
                            QM = queryModel,
                            QMText = qmText,
                            Arguments = sref._arguments.Cast<object>(),
                            IsSequence = selectSequence
                        };
                        FoundFunctions.Add(f);
                    }
                }

                // Go back to working on the previous qm.
                _qmContextStack.Pop();
            }
예제 #8
0
 /// <summary>
 /// Empty ctor.
 /// </summary>
 public QMFuncSource()
 {
     this._header = null;
 }
        private QMFuncSource[] GenerateFunction2()
        {
            var fsub = QMFuncUtils.GenerateFunction();

            int[] ints = new int[10];
            var h = new QMFuncHeader() { Arguments = new object[] { }, QM = new QueryModel(new MainFromClause("i", typeof(int), Expression.Constant(ints)), new SelectClause(Expression.Constant(10))) };
            h.QMText = h.QM.ToString();
            var f = new QMFuncSource(h);

            var p = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            var st = new StatementAssign(p, new ValSimple(fsub.Name + "()", typeof(int)));
            var inlineblock = new StatementInlineBlock();
            inlineblock.Add(st);
            inlineblock.Add(new StatementReturn(p));
            f.SetCodeBody(inlineblock);

            return new QMFuncSource[] { fsub, f };
        }