/// <summary>
        /// Generate the code that we will use to access this array. Loop symantics in this framework are basically "foreach" rather than "for" - so
        /// we return an object that can be used to reference each array element.
        /// </summary>
        /// <param name="env"></param>
        /// <param name="context"></param>
        /// <param name="indexName"></param>
        /// <param name="popVariableContext"></param>
        /// <returns></returns>
        public Tuple<Expression, IDeclaredParameter> AddLoop(IGeneratedQueryCode env, ICodeContext context, CompositionContainer container)
        {
            ///
            /// First, we will need to know the length of this array
            /// 

            var lenExpression = Expression.ArrayLength(_arrayExpression);
            var lenTranslation = ExpressionToCPP.GetExpression(lenExpression, env, context, container);

            ///
            /// Next, generate the expression that forms the basis of the index lookup. We don't
            /// translate this - that only gets to happen when one is actually looking at a final result.
            /// 

            var loopVariable = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            var indexExpression = Expression.MakeBinary(ExpressionType.ArrayIndex, _arrayExpression, loopVariable);

            ///
            /// Now the for loop statement!
            /// 

            env.Add(new StatementForLoop(loopVariable, lenTranslation));

            ///
            /// Return the index expression - the thing that can be used to replace all expressions and
            /// reference the item we are looping over.
            /// 

            return Tuple.Create<Expression, IDeclaredParameter>(indexExpression, loopVariable);
        }
Exemple #2
0
        /// <summary>
        /// Actually try and process this! The count consisits of a count integer and something to increment it
        /// at its current spot.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="codeEnv"></param>
        /// <returns></returns>
        public Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            if (gc == null)
                throw new ArgumentNullException("CodeEnv must not be null!");

            var c = resultOperator as CountResultOperator;
            if (c == null)
                throw new ArgumentNullException("resultOperator can only be a CountResultOperator and must not be null");

            //
            // The accumulator where we will store the result.
            //

            var accumulator = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            accumulator.SetInitialValue("0");

            //
            // Use the Aggregate infrasturcutre to do the adding. This
            // has the advantage that it will correctly combine with
            // similar statements during query optimization.
            //

            var add = Expression.Add(accumulator, Expression.Constant((int)1));
            var addResolved = ExpressionToCPP.GetExpression(add, gc, cc, container);

            gc.Add(new StatementAggregate(accumulator, addResolved));
            return accumulator;
        }
        public static Expression Resolve(this Expression source, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            if (cc == null)
            {
                cc = new CodeContext();
            }

            // It does happen that we are asked to translate a null expression. This could be a static method call, for example.

            if (source == null)
                return null;

            try
            {
                Debug.WriteLine("Expression Resolver: Resolving {0}{1}", source.ToString(), "");
                Debug.Indent();
                var r = ResolveToExpression.Translate(source, gc, cc, container);
                Debug.WriteLine("Expression Resolver: Result: {0}{1}", r == null ? "<null>" : r.ToString(), "");
                return r;
            }
            finally
            {
                Debug.Unindent();
            }
        }
        /// <summary>
        /// Implement the skipping. We have a main limitation: we currently know only how to implement integer skipping.
        /// We implement with "if" statements to support composability, even if it means running longer in the end...
        /// We actually return nothing when goes - we aren't really a final result the way "Count" is.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <returns></returns>
        public void ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode codeEnv, ICodeContext codeContext, CompositionContainer container)
        {
            ///
            /// Quick checks to make sure
            /// 

            if (codeEnv == null)
                throw new ArgumentNullException("codeEnv cannot be null");

            var take = resultOperator as TakeResultOperator;
            var skip = resultOperator as SkipResultOperator;

            if (take == null && skip == null)
            {
                throw new ArgumentNullException("resultOperator must not be null and must represent either a take or a skip operation!");
            }

            if (take != null && take.Count.Type != typeof(int))
                throw new ArgumentException("Take operator count must be an integer!");
            if (skip != null && skip.Count.Type != typeof(int))
                throw new ArgumentException("Skip operator count must be an integer!");

            // If this is a "global" take, then we need to declare the variable a bit specially.
            // Global: we have a limit on the number of objects that goes across events. We test this by seeing if this
            // is a sub-query that is registered (or not).
            var isGlobalTake = codeContext.IsInTopLevelQueryModel(queryModel);

            // Now, we create a count variable and that is how we will tell if we are still skipping or
            // taking. It must be declared in the current block, before our current code! :-)

            var counter = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int), otherDependencies: codeContext.LoopIndexVariable.Return<IDeclaredParameter>());
            if (isGlobalTake)
            {
                counter.DeclareAsStatic = true;
                codeEnv.Add(counter);
            } else
            {
                codeEnv.AddOutsideLoop(counter);
            }

            var comparison = StatementIfOnCount.ComparisonOperator.LessThanEqual;
            IValue limit = null;
            if (skip != null)
            {
                comparison = StatementIfOnCount.ComparisonOperator.GreaterThan;
                limit = ExpressionToCPP.GetExpression(skip.Count, codeEnv, codeContext, container);
            }
            else
            {
                limit = ExpressionToCPP.GetExpression(take.Count, codeEnv, codeContext, container);
            }

            codeEnv.Add(new StatementIfOnCount(counter, limit, comparison));

            ///
            /// We are particularly fortunate here. We don't have to update the Loop variable - whatever it is, is
            /// still the right one! Normally we'd have to futz with the LoopVariable in code context because we
            /// were iterating over something new. :-) Easy!
            /// 
        }
        /// <summary>
        /// Run the method call against the expressions we know.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <returns></returns>
        public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            if (expr == (MethodCallExpression)null)
                throw new ArgumentNullException("expr");

            var h = FindHandler(expr.Method.DeclaringType);
            return h.CodeMethodCall(expr, gc, container);
        }
        /// <summary>
        /// Create a new visitor and add our code to the current spot we are in the "code".
        /// </summary>
        /// <param name="code"></param>
        public QueryVisitor(IGeneratedQueryCode code, ICodeContext context, CompositionContainer container)
        {
            _codeEnv = code;
            _codeContext = context;
            MEFContainer = container;

            if (_codeContext == null)
                _codeContext = new CodeContext();
        }
 public IValue CodeMethodCall(
     TypeHandlerReplacementCall target,
     MethodCallExpression expr,
     IGeneratedQueryCode gc
 )
 {
     var result01 = target.CodeMethodCall(expr, gc, MEFUtilities.MEFContainer);
     return result01;
 }
Exemple #8
0
 public IVariable TestProcessResultOperator([PexAssumeUnderTest]ROSum target,
     SumResultOperator sumro,
     QueryModel qm,
     IGeneratedQueryCode gc,
     ICodeContext cc)
 {
     var result = target.ProcessResultOperator(sumro, qm, gc, cc, MEFUtilities.MEFContainer);
     return result;
 }
        /// <summary>
        /// Called late to replace a constant expression of this type. By the time we get here these should not exist!
        /// The expression holder can't hold anything interesting (like parameters) - by the time we are here
        /// it is too late to do the parsing.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="codeEnv"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public IValue ProcessConstantReference(ConstantExpression expr, IGeneratedQueryCode codeEnv, CompositionContainer container)
        {
            var holder = expr.Value as IExpressionHolder;
            if (holder == null)
                throw new InvalidOperationException("Can't get at the interface to get at the expression.");

            var e = holder.HeldExpression;
            return ExpressionToCPP.InternalGetExpression(e, codeEnv, null, container);
        }
#pragma warning restore 649

        /// <summary>
        /// Process the constant reference
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="codeEnv"></param>
        /// <returns></returns>
        public IValue ProcessConstantReference(ConstantExpression expr, IGeneratedQueryCode codeEnv, CompositionContainer container)
        {
            // <pex>
            if (expr == (ConstantExpression)null)
                throw new ArgumentNullException("expr");
            // </pex>

            var h = FindHandler(expr.Type);
            return h.ProcessConstantReference(expr, codeEnv, container);
        }
            /// <summary>
            /// Translate an expression.
            /// </summary>
            /// <param name="expr"></param>
            /// <param name="cc"></param>
            /// <returns></returns>
            public static Expression Translate(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
            {
                var tr = new ResolveToExpression() { CodeContext = cc, GeneratedCode = gc, MEFContainer = container };
                if (container != null)
                {
                    container.SatisfyImportsOnce(tr);
                }

                return tr.Visit(expr);
            }
        /// <summary>
        /// Find all statements that can be lifted out of their current block, and bubble them up
        /// as much as possible.
        /// </summary>
        /// <param name="result"></param>
        /// <remarks>
        /// We only lift things outside of loops, we don't lift them outside of if statements.
        /// If statements are an efficiency thing on their own - they should prevent expensive tests
        /// from happening if they don't need to.
        /// </remarks>
        internal static void Optimize(IGeneratedQueryCode result)
        {
            var statements = result.CodeBody as IStatementCompound;
            VisitOptimizableStatements(statements);

            foreach (var f in result.Functions.Where(f => f.StatementBlock != null))
            {
                VisitOptimizableStatements(f.StatementBlock);
            }
        }
 internal IValue ProcessConstantReference(
     [PexAssumeUnderTest]TypeHandlerHelpers target,
     ConstantExpression expr,
     IGeneratedQueryCode codeEnv
 )
 {
     IValue result = target.ProcessConstantReference(expr, codeEnv, null);
     return result;
     // TODO: add assertions to method TypeHandlerHelpersTest.ProcessConstantReference(TypeHandlerHelpers, ConstantExpression, IGeneratedCode)
 }
 public IValue ProcessConstantReference(
     TypeHandlerCache target,
     ConstantExpression expr,
     IGeneratedQueryCode codeEnv
 )
 {
     IValue result = target.ProcessConstantReference(expr, codeEnv, null);
     return result;
     // TODO: add assertions to method TypeHandlerCacheTest.ProcessConstantReference(TypeHandlerCache, ConstantExpression, IGeneratedCode)
 }
        /// <summary>
        /// Deal with the various method calls to convert.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            if (expr.Method.Name == "ToDouble")
                return ProcessToDouble(expr, gc, container);

            ///
            /// We don't know how to deal with this particular convert!
            /// 

            throw new NotImplementedException("Can't translate the call Convert." + expr.Method.Name);
        }
 internal Expression ProcessMethodCall(
     [PexAssumeUnderTest]TypeHandlerHelpers target,
     MethodCallExpression expr,
     IGeneratedQueryCode gc,
     ICodeContext context
 )
 {
     Expression result01 = target.ProcessMethodCall(expr, gc, context, null);
     return result01;
     // TODO: add assertions to method TypeHandlerHelpersTest.ProcessMethodCall(TypeHandlerHelpers, MethodCallExpression, IValue&, IGeneratedCode, ICodeContext)
 }
Exemple #17
0
        internal IValue ProcessConstantReference(
            [PexAssumeUnderTest] TypeHandlerHelpers target,
            ConstantExpression expr,
            IGeneratedQueryCode codeEnv
            )
        {
            IValue result = target.ProcessConstantReference(expr, codeEnv, null);

            return(result);
            // TODO: add assertions to method TypeHandlerHelpersTest.ProcessConstantReference(TypeHandlerHelpers, ConstantExpression, IGeneratedCode)
        }
 /// <summary>Test stub for ProcessMethodCall(MethodCallExpression, IValue&amp;, IGeneratedCode, ICodeContext)</summary>
 ///[PexMethod]
 public Expression ProcessMethodCall(
     TypeHandlerReplacementCall target,
     MethodCallExpression expr,
     IGeneratedQueryCode gc,
     ICodeContext context
 )
 {
     Expression result01 = target.ProcessMethodCall(expr, gc, context, MEFUtilities.MEFContainer);
     return result01;
     // TODO: add assertions to method TypeHandlerReplacementCallTest.ProcessMethodCall(TypeHandlerReplacementCall, MethodCallExpression, IValue&, IGeneratedCode, ICodeContext)
 }
Exemple #19
0
        public IValue ProcessConstantReference(
            TypeHandlerCache target,
            ConstantExpression expr,
            IGeneratedQueryCode codeEnv
            )
        {
            IValue result = target.ProcessConstantReference(expr, codeEnv, null);

            return(result);
            // TODO: add assertions to method TypeHandlerCacheTest.ProcessConstantReference(TypeHandlerCache, ConstantExpression, IGeneratedCode)
        }
        /// <summary>
        /// Called during the high-level expression parsing. We will parse the expression and method to other expressions...
        /// So we drive everything through (get rid of sub-queries, etc.). First part of two pass parsing. Second part is below
        /// that will actually generate the C++ code.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public Expression ProcessMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, ICodeContext context, CompositionContainer container)
        {
            //
            // Pick apart the various things in the method call we need.
            //

            var robj   = expr.Object.Resolve(gc, context, container);
            var method = expr.Method;
            var rargs  = expr.Arguments.Select(e => e.Resolve(gc, context, container));

            return(Expression.Call(robj, method, rargs));
        }
Exemple #21
0
        /// <summary>
        /// Try to do a fast count. Basically, what we are dealing with here is the fact that we have
        /// a simple array, we need only take its length, and return that.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public Tuple<bool, Expression> ProcessIdentityQuery(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode _codeEnv, ICodeContext _codeContext, CompositionContainer container)
        {
            //
            // We just need to return a length expression. We are low enough level we need to do some basic resolution.
            //

            if (!queryModel.MainFromClause.FromExpression.Type.IsArray)
                return Tuple.Create(false, null as Expression);

            var lengthExpr = Expression.ArrayLength(queryModel.MainFromClause.FromExpression).Resolve(_codeEnv, _codeContext, container);
            return Tuple.Create(true, lengthExpr as Expression);
        }
Exemple #22
0
        internal Expression ProcessMethodCall(
            [PexAssumeUnderTest] TypeHandlerHelpers target,
            MethodCallExpression expr,
            IGeneratedQueryCode gc,
            ICodeContext context
            )
        {
            Expression result01 = target.ProcessMethodCall(expr, gc, context, null);

            return(result01);
            // TODO: add assertions to method TypeHandlerHelpersTest.ProcessMethodCall(TypeHandlerHelpers, MethodCallExpression, IValue&, IGeneratedCode, ICodeContext)
        }
        /// <summary>Test stub for ProcessMethodCall(MethodCallExpression, IValue&amp;, IGeneratedCode, ICodeContext)</summary>
        ///[PexMethod]
        public Expression ProcessMethodCall(
            TypeHandlerReplacementCall target,
            MethodCallExpression expr,
            IGeneratedQueryCode gc,
            ICodeContext context
            )
        {
            Expression result01 = target.ProcessMethodCall(expr, gc, context, MEFUtilities.MEFContainer);

            return(result01);
            // TODO: add assertions to method TypeHandlerReplacementCallTest.ProcessMethodCall(TypeHandlerReplacementCall, MethodCallExpression, IValue&, IGeneratedCode, ICodeContext)
        }
Exemple #24
0
        /// <summary>
        /// Deal with the various method calls to convert.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            if (expr.Method.Name == "ToDouble")
            {
                return(ProcessToDouble(expr, gc, container));
            }

            ///
            /// We don't know how to deal with this particular convert!
            ///

            throw new NotImplementedException("Can't translate the call Convert." + expr.Method.Name);
        }
 /// Pex seems to hang when it tries to explore this one.
 ///[PexMethod]
 public Expression ProcessResultOperator(
     ROAggregate target,
     AggregateFromSeedResultOperator resultOperator,
     QueryModel queryModel,
     IGeneratedQueryCode _codeEnv
 )
 {
     CodeContext c = new CodeContext();
     Expression result
        = target.ProcessResultOperator(resultOperator, queryModel, _codeEnv, c, MEFUtilities.MEFContainer);
     return result;
     // TODO: add assertions to method ROAggregateTest.ProcessResultOperator(ROAggregate, ResultOperatorBase, QueryModel, IGeneratedCode)
 }
        /// <summary>
        /// Process a new against an expression - that hopefully we know!
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        internal Expression ProcessNew(NewExpression expression, out IValue result, IGeneratedQueryCode gc, CompositionContainer container)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            var h = FindHandler(expression.Type);

            return(h.ProcessNew(expression, out result, gc, container));

            throw new NotImplementedException();
        }
#pragma warning restore 649

        /// <summary>
        /// Process the constant reference
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="codeEnv"></param>
        /// <returns></returns>
        public IValue ProcessConstantReference(ConstantExpression expr, IGeneratedQueryCode codeEnv, CompositionContainer container)
        {
            // <pex>
            if (expr == (ConstantExpression)null)
            {
                throw new ArgumentNullException("expr");
            }
            // </pex>

            var h = FindHandler(expr.Type);

            return(h.ProcessConstantReference(expr, codeEnv, container));
        }
        /// <summary>
        /// Try to do a member reference. Return null if we can't do it.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        internal IValue TryMemberReference(MemberExpression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            var h = FindHandler(expr.Expression.Type, false);

            if (h == null)
            {
                return(null);
            }

            return(h.ProcessMemberReference(expr, gc, cc, container));

            throw new NotImplementedException();
        }
        /// <summary>
        /// Called late to replace a constant expression of this type. By the time we get here these should not exist!
        /// The expression holder can't hold anything interesting (like parameters) - by the time we are here
        /// it is too late to do the parsing.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="codeEnv"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public IValue ProcessConstantReference(ConstantExpression expr, IGeneratedQueryCode codeEnv, CompositionContainer container)
        {
            var holder = expr.Value as IExpressionHolder;

            if (holder == null)
            {
                throw new InvalidOperationException("Can't get at the interface to get at the expression.");
            }

            var e = holder.HeldExpression;

            return(ExpressionToCPP.InternalGetExpression(e, codeEnv, null, container));
        }
 internal Expression ProcessResultOperator(
     [PexAssumeUnderTest]ROMinMax target,
     ResultOperatorBase resultOperator,
     QueryModel queryModel,
     IGeneratedQueryCode gc,
     ICodeContext cc,
     CompositionContainer container
 )
 {
     Expression result
        = target.ProcessResultOperator(resultOperator, queryModel, gc, cc, container);
     return result;
     // TODO: add assertions to method ROMinMaxTest.ProcessResultOperator(ROMinMax, ResultOperatorBase, QueryModel, IGeneratedQueryCode, ICodeContext, CompositionContainer)
 }
        /// <summary>
        /// Given array info, code a loop over it.
        /// </summary>
        /// <param name="query">The query this loop is associated with</param>
        /// <param name="arrayRef">The reference to the array</param>
        /// <remarks>Will add the query to the code context to forward to the variable that is being dealt with here.</remarks>
        public static IVariableScopeHolder CodeLoopOverArrayInfo(this IArrayInfo arrayRef, IQuerySource query, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            var indexVar = arrayRef.AddLoop(gc, cc, container);
            if (indexVar == null)
                return null;

            ///
            /// Next, make sure the index variable can be used for later references!
            /// 

            var result = cc.Add(query, indexVar.Item1);
            cc.SetLoopVariable(indexVar.Item1, indexVar.Item2);
            return result;
        }
Exemple #32
0
        /// Pex seems to hang when it tries to explore this one.
        ///[PexMethod]
        public Expression ProcessResultOperator(
            ROAggregate target,
            ResultOperatorBase resultOperator,
            QueryModel queryModel,
            IGeneratedQueryCode _codeEnv
            )
        {
            CodeContext c = new CodeContext();
            Expression  result
                = target.ProcessResultOperator(resultOperator, queryModel, _codeEnv, c, MEFUtilities.MEFContainer);

            return(result);
            // TODO: add assertions to method ROAggregateTest.ProcessResultOperator(ROAggregate, ResultOperatorBase, QueryModel, IGeneratedCode)
        }
Exemple #33
0
        internal Expression ProcessNew(
            [PexAssumeUnderTest] TypeHandlerCache target,
            NewExpression expression,
            out IValue _result,
            IGeneratedQueryCode _codeEnv,
            CompositionContainer MEFContainer
            )
        {
            Expression result = target.ProcessNew
                                    (expression, out _result, _codeEnv, MEFContainer);

            return(result);
            // TODO: add assertions to method TypeHandlerCacheTest.ProcessNew(TypeHandlerCache, NewExpression, IValue&, IGeneratedQueryCode, ICodeContext, CompositionContainer)
        }
            /// <summary>
            /// Translate an expression.
            /// </summary>
            /// <param name="expr"></param>
            /// <param name="cc"></param>
            /// <returns></returns>
            public static Expression Translate(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
            {
                var tr = new ResolveToExpression()
                {
                    CodeContext = cc, GeneratedCode = gc, MEFContainer = container
                };

                if (container != null)
                {
                    container.SatisfyImportsOnce(tr);
                }

                return(tr.Visit(expr));
            }
        /// <summary>
        /// Do a type check, and then create the range info... which is dirt simple, of course!
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        /// <param name="ReGetIArrayInfo"></param>
        /// <returns></returns>
        public IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container, Func <Expression, IArrayInfo> ReGetIArrayInfo)
        {
            if (expr.NodeType == ExpressionType.Constant)
            {
                return(ProcessPossibleConstEnumerableRange(expr, gc, cc, container, ReGetIArrayInfo));
            }

            if (expr.NodeType == EnumerableRangeExpression.ExpressionType)
            {
                return(ProcessEnumerableRangeExpression(expr, gc, cc, container, ReGetIArrayInfo));
            }

            return(null);
        }
Exemple #36
0
        internal Expression ProcessResultOperator(
            [PexAssumeUnderTest] ROMinMax target,
            ResultOperatorBase resultOperator,
            QueryModel queryModel,
            IGeneratedQueryCode gc,
            ICodeContext cc,
            CompositionContainer container
            )
        {
            Expression result
                = target.ProcessResultOperator(resultOperator, queryModel, gc, cc, container);

            return(result);
            // TODO: add assertions to method ROMinMaxTest.ProcessResultOperator(ROMinMax, ResultOperatorBase, QueryModel, IGeneratedQueryCode, ICodeContext, CompositionContainer)
        }
        /// <summary>
        /// Given an array expression return an array info that can be used
        /// for the various needed things. Throws if it can't figure out how to do
        /// a loop. It might return null, in which case the array index context has
        /// just been "setup".
        /// </summary>
        /// <param name="expr"></param>
        /// <returns>null, if no further setup is required to run the loop, and an IArrayInfo if further work is required.</returns>
        private IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            expr = NormalizeExpression(expr);

            //
            // See if we can find something that will handle the array.
            //

            var arInfo = (from h in _handlers
                          let r = h.GetIArrayInfo(expr, gc, cc, container, e => GetIArrayInfo(e, gc, cc, container))
                                  where r != null
                                  select r).FirstOrDefault();

            return(arInfo);
        }
Exemple #38
0
        internal Expression ProcessResultOperator(
            [PexAssumeUnderTest] ROAnyAll target,
            ResultOperatorBase resultOperator,
            QueryModel queryModel,
            IGeneratedQueryCode _codeEnv,
            ICodeContext _codeContext,
            CompositionContainer container
            )
        {
            Expression result = target.ProcessResultOperator
                                    (resultOperator, queryModel, _codeEnv, _codeContext, container);

            return(result);
            // TODO: add assertions to method ROAnyAllTest.ProcessResultOperator(ROAnyAll, ResultOperatorBase, QueryModel, IGeneratedQueryCode, ICodeContext, CompositionContainer)
        }
        /// <summary>
        /// Given an array expression return an array info that can be used
        /// for the various needed things. Throws if it can't figure out how to do
        /// a loop. It might return null, in which case the array index context has
        /// just been "setup".
        /// </summary>
        /// <param name="expr"></param>
        /// <returns>null, if no further setup is required to run the loop, and an IArrayInfo if further work is required.</returns>
        private IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            expr = NormalizeExpression(expr);

            //
            // See if we can find something that will handle the array.
            //

            var arInfo = (from h in _handlers
                          let r = h.GetIArrayInfo(expr, gc, cc, container, e => GetIArrayInfo(e, gc, cc, container))
                          where r != null
                          select r).FirstOrDefault();

            return arInfo;
        }
        /// <summary>
        /// Translate the CPP code reference into the code
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            if (expr == null)
                throw new ArgumentNullException("expr");

            ///
            /// Get the coding attribute off the method
            /// 

            var code = expr.Method.TypeHasAttribute<CPPCodeAttribute>();
            if (code == null)
                throw new InvalidOperationException(string.Format("Asked to generate code for a CPP method '{0}' but no CPPCode attribute found on that method!", expr.Method.Name));

            return CPPCodeStatement.BuildCPPCodeStatement(expr, gc, container, code.IncludeFiles, code.Code);
        }
        /// <summary>
        /// Take the incoming stream of items, and send them along! :-)
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        public void ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            //
            // Some basic checks on the input.
            //

            if (cc == null)
                throw new ArgumentNullException("cc");
            if (gc == null)
                throw new ArgumentNullException("gc");
            if (cc.LoopVariable == null)
                throw new ArgumentNullException("No defined loop variable!");

            //
            // Get the indexer that is being used to access things. We will just push that onto a temp vector of int's. That will be
            // a list of the items that we want to come back and look at. That said, once done we need to pop-up one level in our
            // depth.
            //

            var arrayRecord = DeclarableParameter.CreateDeclarableParameterArrayExpression(typeof(int));
            gc.AddOutsideLoop(arrayRecord);

            var recordIndexStatement = new Statements.StatementRecordIndicies(ExpressionToCPP.GetExpression(cc.LoopIndexVariable.AsExpression(), gc, cc, container), arrayRecord);
            gc.Add(recordIndexStatement);

            gc.Pop();

            //
            // Now, we go down one loop and run over the pairs with a special loop.
            //

            var index1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            var index2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int));
            var indexIterator = new Statements.StatementPairLoop(arrayRecord, index1, index2);
            gc.Add(indexIterator);

            //
            // Finally, build the resulting loop variable. For now it is just a tuple, which is basically the formed expression we started with,
            // but with the other index properties. Other bits will have to do the translation for us. :-)
            //

            var item1 = cc.LoopVariable.ReplaceSubExpression(cc.LoopIndexVariable.AsExpression(), index1);
            var item2 = cc.LoopVariable.ReplaceSubExpression(cc.LoopIndexVariable.AsExpression(), index2);

            var tupleType = typeof(Tuple<,>).MakeGenericType(cc.LoopVariable.Type, cc.LoopVariable.Type);
            var newTuple = Expression.New(tupleType.GetConstructor(new Type[] { cc.LoopVariable.Type, cc.LoopVariable.Type }), item1, item2);
            cc.SetLoopVariable(newTuple, null);
        }
Exemple #42
0
        /// <summary>
        /// See if we can't resolve a group-by object into a looper of some sort.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        /// <param name="ReGetIArrayInfo"></param>
        /// <returns></returns>
        public IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container, Func <Expression, IArrayInfo> ReGetIArrayInfo)
        {
            if (!expr.Type.IsGenericType ||
                expr.Type.GetGenericTypeDefinition() != typeof(GroupByTypeTagEnum <int, int>).GetGenericTypeDefinition())
            {
                return(null);
            }
            var param = expr as ConstantExpression;

            if (param == null)
            {
                return(null);
            }

            var groupObj = param.Value as BaseGroupInfo;

            if (groupObj == null)
            {
                throw new InvalidOperationException("Group object has a null value - should never happen!");
            }

            //
            // Loop over the groups. groupIndex represents the actual group index.
            //

            var loopOverGroups = new Statements.StatementLoopOverGroups(groupObj.MapRecord);

            gc.Add(loopOverGroups);

            //
            // Finally, the loop index variable and we have to create the index object now, which is the grouping
            // (which can also be iterated over).
            //

            var t_return = typeof(GroupByType <int, int>).GetGenericTypeDefinition().MakeGenericType(param.Value.GetType().GetGenericArguments());
            var ctor     = t_return.GetConstructor(new Type[] { });
            var o        = ctor.Invoke(new object[] { }) as BaseGroupInfo;

            o.MapRecord                    = groupObj.MapRecord;
            o.TargetExpression             = groupObj.TargetExpression;
            o.TargetExpressionLoopVariable = groupObj.TargetExpressionLoopVariable;
            o.GroupIndexVariable           = loopOverGroups.IndexVariable;
            o.GroupLoopStatement           = loopOverGroups;

            var loopVar = Expression.Constant(o);

            return(new SimpleLoopVarSetting(loopVar, loopOverGroups.IndexVariable));
        }
        public IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container, Func <Expression, IArrayInfo> ReGetIArrayInfo)
        {
            if (expr is SubQueryExpression)
            {
                return(null);
            }

            var translated = AttemptTranslationToArray(expr, cc);

            if (translated != null)
            {
                return(ReGetIArrayInfo(translated));
            }

            return(null);
        }
        /// <summary>
        /// If one of the helper functions needs to be parsed, we end up here.
        /// Note: this is a bit tricky, and, worse, this is not tested (too complex :-)).
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public System.Linq.Expressions.Expression ProcessMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, ICodeContext context, CompositionContainer container)
        {
            if (expr == null)
                throw new ArgumentNullException("expr");

            if (expr.Method.Name == "ApplyReturnFirst")
            {
                ///
                /// Load out the parameter names we are looking at so we cna do the translation.
                /// 

                var parameters = expr.Method.GetParameters();
                var action = RaiseLambda(expr.Arguments[2]);

                var methodGenericArguments = expr.Method.GetGenericArguments();
                var actionType = typeof(Action<,>).MakeGenericType(new Type[] { methodGenericArguments[0], methodGenericArguments[1] });
                var expressionGeneric = typeof(Expression<>).MakeGenericType(new Type[] { actionType });
                var parameterSpec = expressionGeneric.GetProperty("Parameters");
                var lambdaParameters = (parameterSpec.GetValue(action, null) as IEnumerable<ParameterExpression>).ToArray();

                ///
                /// Next, do the lambda expression. Order of p1 and p2 is b/c we should make sure that it happens
                /// before any parameters are replaced! Note we parse the body of the lambda here! Parameters are defined and should
                /// correctly deal with any substitution in process.
                /// 

                var p2 = context.Add(lambdaParameters[1].Name, expr.Arguments[1]);
                var p1 = context.Add(lambdaParameters[0].Name, expr.Arguments[0]);

                var statementBody = ExpressionToCPP.GetExpression(action.Body.Resolve(gc, context, container), gc, context, container);

                p1.Pop();
                p2.Pop();

                gc.Add(new Statements.StatementSimpleStatement(statementBody.RawValue, resultVars: new string[0] { }, dependentVars: statementBody.Dependants.Select(i => i.RawValue).ToArray()));

                ///
                /// Finally, what we will return if this is the last thing we are doing!
                /// 

                return expr.Arguments[0];
            }
            else
            {
                throw new NotImplementedException("Helpers." + expr.Method.Name + " is not handled!");
            }
        }
        /// <summary>
        /// Do the work of translating this to code by fetching the data from the interface.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            if (expr == null)
                throw new ArgumentNullException("expr");

            // Get a reference to the object so we can code the call to get back the C++ code.
            var onTheFly = (expr?.Object as ConstantExpression)?.Value as IOnTheFlyCPPObject;
            if (onTheFly == null)
            {
                throw new InvalidOperationException("Unable to find the IOnTheFlyCPPObject!");
            }

            var includeFiles = onTheFly.IncludeFiles();
            var loc = onTheFly.LinesOfCode(expr.Method.Name).ToArray();

            return CPPCodeStatement.BuildCPPCodeStatement(expr, gc, container, includeFiles, loc);
        }
Exemple #46
0
        /// <summary>
        /// Internal expression resolver.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="ce"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        /// <remarks>
        /// Cache and do cache lookup of expressions to try to short-circuit the expression resolution.
        /// </remarks>
        public static IValue InternalGetExpression(Expression expr, IGeneratedQueryCode ce, ICodeContext cc, CompositionContainer container)
        {
            // If we are looking at a null expression, then we resolve to a null value
            if (expr == null)
            {
                return(null);
            }

            // If this is a known sub-expression, then we should return
            // the cached value.
            if (ce != null)
            {
                var v = ce.LookupSubexpression(expr);
                if (v != null)
                {
                    return(v);
                }
            }

            // We are going to do the visit. Create the resolver we are going to use
            // and configure it.
            if (cc == null)
            {
                cc = new CodeContext();
            }

            var visitor = new ExpressionToCPP(ce, cc);

            visitor.MEFContainer = container;

            if (container != null)
            {
                container.SatisfyImportsOnce(visitor);
            }

            // Do the visit
            visitor.Visit(expr);

            // Cache the result.
            if (ce != null)
            {
                ce.RememberSubexpression(expr, visitor.Result);
            }

            return(visitor.Result);
        }
Exemple #47
0
        /// <summary>
        /// We want to print the results out to a file.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        /// <remarks>
        /// We can handle several types of streams here:
        /// 1) a stream of double's - this is just one column.
        /// 2) A stream of Tuples
        /// 3) A stream of custom objects
        /// </remarks>
        public override Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            // Argument checking
            var asTTree = resultOperator as AsTTreeResultOperator;
            if (asTTree == null)
                throw new ArgumentException("resultOperaton");

            // Declare the includes.
            gc.AddIncludeFile("<map>");
            gc.AddIncludeFile("TSystem.h");
            gc.AddIncludeFile("TFile.h");
            gc.AddIncludeFile("TTree.h");

            // If we were left to our own devices generating an output file, then make one up based on the tree name.
            var outputFile = asTTree.OutputFile != null
                ? asTTree.OutputFile
                : new FileInfo($"{asTTree.TreeName}.root");

            // Declare the TTree and the file we will be using!
            // Initialization is not important as we will over-write this directly.
            var stream = DeclarableParameter.CreateDeclarableParameterExpression(typeof(OutputTTreeFileType));
            stream.InitialValue = new OutputTTreeFileType(outputFile);

            // Generate a real filename. We are going to key the file by the cache key. Unfortunately, at this
            // point in the generation the cache key isn't known. So we have to have a 'promise' that can be used
            // for later when the code is actually generated.
            var outputFilePromise = GenerateUniqueFile(outputFile, cc);

            // Open the file and declare the tree
            gc.AddInitalizationStatement(new StatementSimpleStatement(() => $"{stream.RawValue}.first = new TFile(\"{outputFilePromise().FullName.AddCPPEscapeCharacters()}\",\"RECREATE\")", dependentVars: new string[0], resultVars: new string[] { stream.RawValue }));
            gc.AddInitalizationStatement(new StatementSimpleStatement($"{stream.RawValue}.second = new TTree(\"{asTTree.TreeName}\", \"{asTTree.TreeTitle}\")", dependentVars: new string[0],  resultVars: new string[] { stream.RawValue }));

            // Get the list of item values we are going to need here.
            List<Expression> itemValues = ExtractItemValueExpressions(queryModel);

            // We are just going to print out the line with the item in it.
            var itemAsValues = itemValues.Select(iv => ExpressionToCPP.GetExpression(iv, gc, cc, container)).ToArray();
            var pstatement = new StatementFillTree(stream, itemAsValues.Zip(asTTree.HeaderColumns, (i, h) => Tuple.Create(i, h)).ToArray());

            gc.Add(pstatement);

            // The return is a file path in the C# world. But here in C++, what should be returned?
            // We will use a string.
            return stream;
        }
Exemple #48
0
        /// <summary>
        /// Convert something to a double. We don't actually do anything as long as this is an expression that we
        /// can naturally convert (int, float, etc.).
        ///
        /// We are expecting an expressio nthat is ToDouble(Convert()), so if we can't see the convert, then we bail.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        private static IValue ProcessToDouble(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            var srcExpr = expr.Arguments[0];

            if (srcExpr.NodeType != ExpressionType.Convert)
            {
                throw new NotImplementedException("Expecting a Convert expression inside the call to Convert.ToDouble");
            }
            var cvtExpr = srcExpr as UnaryExpression;

            var result = ExpressionToCPP.InternalGetExpression(cvtExpr.Operand, gc, null, container);

            if (!result.Type.IsNumberType())
            {
                throw new NotImplementedException("Do not know how to convert '" + srcExpr.Type.Name + "' to a double!");
            }

            return(result);
        }
        /// <summary>
        /// Parse an array expression, and turn it into a loop. Use indexName as the loop variable. Bomb if we can't do it. If you hand in null we will make up our own.
        /// </summary>
        /// <param name="query">The query that this loop is associated with.</param>
        /// <param name="expr">The expression that evaluates to an array.</param>
        /// <param name="gc"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        public static IVariableScopeHolder ParseArrayExpression(IQuerySource query, Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            if (_parser == null)
            {
                _parser = new ArrayExpressionParser();
                container.SatisfyImportsOnce(_parser);
            }

            var result = _parser.GetIArrayInfo(expr, gc, cc, container);

            if (result == null)
                throw new InvalidOperationException($"Can't figure out how to loop over this array: '{expr.ToString()}' (expression: '{expr.NodeType}', type: '{expr.Type.FullyQualifiedName()}')");

            //
            // Turn it into code - any code that we need.
            //

            return result.CodeLoopOverArrayInfo(query, gc, cc, container);
        }
Exemple #50
0
        /// <summary>
        /// Evaluate an expression. If the result is just DeclareableParameter, return that, otherwise make an assignment.
        /// </summary>
        /// <param name="ce"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        /// <param name="exprToHandIn"></param>
        /// <returns></returns>
        private static DeclarableParameter AssignExpreaaionToEvaluationIfNeededBool(IGeneratedQueryCode ce, ICodeContext cc, CompositionContainer container, Expression exprToHandIn, IScopeInfo whereToDeclare = null)
        {
            IValue exprEvaluation = GetExpression(exprToHandIn, ce, cc, container);

            if (exprEvaluation is DeclarableParameter p)
            {
                // We can only return this if the variable is declared at the place we want it to be!
                var currentScope = ce.CurrentScope;
                try
                {
                    if (whereToDeclare != null)
                    {
                        ce.CurrentScope = whereToDeclare;
                    }
                    if (ce.CodeBody.AllDeclaredVariables.Where(dp => dp == p).Any())
                    {
                        return(p);
                    }
                } finally
                {
                    ce.CurrentScope = currentScope;
                }
            }

            // Create and assign an expression.
            var result = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool));

            result.InitialValue = new ValSimple("false", typeof(bool));

            if (whereToDeclare == null)
            {
                ce.Add(result);
            }
            else
            {
                var currentScope = ce.CurrentScope;
                ce.CurrentScope = whereToDeclare;
                ce.Add(result);
                ce.CurrentScope = currentScope;
            }
            ce.Add(new Statements.StatementAssign(result, exprEvaluation));
            return(result);
        }
        /// <summary>
        /// For a root variable we create a special variable which holds onto the initial value, and
        /// also will get loaded at the correct time.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="codeEnv"></param>
        /// <returns></returns>
        public IValue ProcessConstantReference(ConstantExpression expr, IGeneratedQueryCode codeEnv, CompositionContainer container)
        {
            ///
            /// The value is a reference that will do the loading.
            ///

            var rootObject = expr.Value as ROOTNET.Interface.NTNamed;

            if (rootObject == null)
            {
                throw new ArgumentException("the object to be stored must derive from NTNamed! It is of type '" + expr.Value.GetType().Name + "' which does not appear to derive from TNamed.");
            }

            //
            // Queue this object for transfer, get a "unique" name back. This will also double check
            // to see if the object is already up there read to be queued.
            //

            var varNameForTransport = codeEnv.QueueForTransfer(rootObject);

            //
            // Now, we need to generate an IValue for the object that can be used in our expression parsing.
            // When in the middle of a tight loop, since finding the object is a "slow" linear lookup, we will cache it in a static
            // variable. This isn't so pretty when there is a one-time initialization, but it shouldn't add too much.
            //

            var staticCache = new ROOTObjectStaticHolder(rootObject.GetType(), rootObject);

            staticCache.DeclareAsStatic = true;
            staticCache.InitialValue    = new ValSimple("nullptr", staticCache.Type);
            codeEnv.Add(staticCache);

            codeEnv.Add(new Statements.StatementFilter(new ValSimple($"{staticCache.RawValue} == nullptr", typeof(bool), new IDeclaredParameter[] { staticCache })));
            var CPPType = rootObject.GetType().AsCPPType();
            var val     = new ROOTObjectCopiedValue(varNameForTransport, rootObject.GetType(), CPPType, rootObject.Name, rootObject.Title);

            codeEnv.Add(new Statements.StatementAssign(staticCache, val));
            codeEnv.Pop();

            // And the rest of the code should use the static cache.
            return(staticCache);
        }
Exemple #52
0
        /// <summary>
        /// We want to print the results out to a file.
        /// </summary>
        /// <param name="resultOperator"></param>
        /// <param name="queryModel"></param>
        /// <param name="_codeEnv"></param>
        /// <param name="_codeContext"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        /// <remarks>
        /// We can handle several types of streams here:
        /// 1) a stream of double's - this is just one column.
        /// 2) A stream of Tuples
        /// 3) A stream of custom objects
        /// </remarks>
        public override Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
        {
            // Argument checking
            var asCSV = resultOperator as AsCSVResultOperator;
            if (asCSV == null)
                throw new ArgumentException("resultOperaton");

            // Declare the includes.
            gc.AddIncludeFile("<fstream>");
            gc.AddIncludeFile("<iostream>");

            // The output filename. How we do this is a little funny because we need the hash from the completely
            // done query, which isn't ready just yet.
            var outputFile = GenerateUniqueFile(asCSV.OutputFile, cc);
            var stream = DeclarableParameter.CreateDeclarableParameterExpression(typeof(OutputCSVTextFileType));
            stream.InitialValue = new OutputCSVTextFileType(outputFile);

            var headerline = new StringBuilder();
            bool first = true;
            foreach (var h in asCSV.HeaderColumns)
            {
                if (!first)
                {
                    headerline.Append(", ");
                }
                headerline.Append(h);
                first = false;
            }
            gc.AddInitalizationStatement(new Statements.StatementSimpleStatement($"{stream.RawValue} << \"{headerline.ToString()}\" << std::endl;", dependentVars: new string[0], resultVars: new string[] { stream.RawValue }));

            // Get the list of item values we are going to need here.
            List<Expression> itemValues = ExtractItemValueExpressions(queryModel);

            // We are just going to print out the line with the item in it.
            var itemAsValues = itemValues.Select(iv => ExpressionToCPP.GetExpression(iv, gc, cc, container));
            var pstatement = new StatementCSVDump(stream, itemAsValues.ToArray());
            gc.Add(pstatement);

            // The return is a file path in the C# world. But here in C++, what should be returned?
            // We will use a string.
            return stream;
        }
        /// <summary>
        /// Do the work of translating this to code by fetching the data from the interface.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            if (expr == null)
            {
                throw new ArgumentNullException("expr");
            }

            // Get a reference to the object so we can code the call to get back the C++ code.
            var onTheFly = (expr?.Object as ConstantExpression)?.Value as IOnTheFlyCPPObject;

            if (onTheFly == null)
            {
                throw new InvalidOperationException("Unable to find the IOnTheFlyCPPObject!");
            }

            var includeFiles = onTheFly.IncludeFiles();
            var loc          = onTheFly.LinesOfCode(expr.Method.Name).ToArray();

            return(CPPCodeStatement.BuildCPPCodeStatement(expr, gc, container, includeFiles, loc));
        }
Exemple #54
0
        /// <summary>
        /// Translate the CPP code reference into the code
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="result"></param>
        /// <param name="gc"></param>
        /// <param name="context"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container)
        {
            if (expr == null)
            {
                throw new ArgumentNullException("expr");
            }

            ///
            /// Get the coding attribute off the method
            ///

            var code = expr.Method.TypeHasAttribute <CPPCodeAttribute>();

            if (code == null)
            {
                throw new InvalidOperationException(string.Format("Asked to generate code for a CPP method '{0}' but no CPPCode attribute found on that method!", expr.Method.Name));
            }

            return(CPPCodeStatement.BuildCPPCodeStatement(expr, gc, container, code.IncludeFiles, code.Code));
        }
Exemple #55
0
        /// <summary>
        /// We are looking at a&&b or a||b. We wnat to make sure we evaluate b iff we need it, depending on the result of a.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="ce"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        /// <remarks>
        /// To prevent us from updating variables (which makes optmization harder), we will implement the code as follows for a&&b:
        /// bool_1 = false; bool_2 = false; bool_3 = false;
        /// bool_1 = a
        /// if (bool_1) bool_2 = b
        /// bool_3 = bool_1 && bool_2
        ///</remarks>
        private static IValue GetExpressionForBoolAndOr(Expression expr, IGeneratedQueryCode ce, ICodeContext cc, CompositionContainer container)
        {
            // Svae to make sure we can get back.
            var outterScope = ce.CurrentScope;

            // Create a variable to hold the result of this test
            var resultBool3 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool));

            resultBool3.InitialValue = new ValSimple("false", typeof(bool));
            ce.Add(resultBool3);

            // Create and evaluate bool_1
            var binaryExpression            = expr as BinaryExpression;
            DeclarableParameter resultBool1 = AssignExpreaaionToEvaluationIfNeededBool(ce, cc, container, binaryExpression.Left);

            // Now, see if we need to evalute the right hand operand.
            if (expr.NodeType == ExpressionType.AndAlso)
            {
                ce.Add(new Statements.StatementFilter(resultBool1));
            }
            else
            {
                var notYet = new ValSimple($"!{resultBool1.RawValue}", typeof(bool), new IDeclaredParameter[] { resultBool1 });
                ce.Add(new Statements.StatementFilter(notYet));
            }

            // Create and evaluate bool 1.
            var resultBool2 = AssignExpreaaionToEvaluationIfNeededBool(ce, cc, container, binaryExpression.Right, outterScope);

            ce.CurrentScope = outterScope;

            // Finally, evaluate bool3.
            var termEvaluation = expr.NodeType == ExpressionType.AndAlso
                ? $"{resultBool1.RawValue}&&{resultBool2.RawValue}"
                : $"{resultBool1.RawValue}||{resultBool2.RawValue}";

            ce.Add(new Statements.StatementAssign(resultBool3, new ValSimple(termEvaluation, typeof(bool), new[] { resultBool1, resultBool2 })));

            // Return the value we've now filled.
            return(resultBool3);
        }
Exemple #56
0
        /// <summary>
        /// Helper routine to return the expression as a string.
        /// </summary>
        /// <param name="expr"></param>
        /// <returns></returns>
        public static IValue GetExpression(Expression expr, IGeneratedQueryCode ce, ICodeContext cc, CompositionContainer container)
        {
            try
            {
                // Get setup and deal with simple cases.
                Debug.WriteLine("ExpressionToCPP: Parsing {0}{1}", expr.ToString(), "");
                Debug.Indent();
                if (expr == null)
                {
                    return(null);
                }

                if (cc == null)
                {
                    cc = new CodeContext();
                }

                // Special case we can deal with seperately - when there is a bool and an AndAlso or OrElse.
                // We want to make sure we guard the second expression so it isn't executed if it isn't needed.
                if (expr.Type == typeof(bool) &&
                    (expr.NodeType == ExpressionType.AndAlso || expr.NodeType == ExpressionType.OrElse))
                {
                    return(GetExpressionForBoolAndOr(expr, ce, cc, container));
                }

                // Cache the list of variables that need to be eliminated when CPP is done.
                var cachedScopedVariables = cc.ResetCachedVariableList();

                var r = InternalGetExpression(expr.Resolve(ce, cc, container), ce, cc, container).PerformAllSubstitutions(cc);
                Debug.WriteLine("ExpressionToCPP: Returning value {0}{1}", r.ToString(), "");

                cc.PopCachedVariableList();

                cc.LoadCachedVariableList(cachedScopedVariables);
                return(r);
            }
            finally
            {
                Debug.Unindent();
            }
        }
        public IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container, Func <Expression, IArrayInfo> ReGetIArrayInfo)
        {
            if (!(expr is SubQueryExpression))
            {
                return(null);
            }

            var resolved = expr.Resolve(gc, cc, container);

            if (resolved == null)
            {
                return(new DummyArrayInfo());
            }

            if (resolved is SubQueryExpression)
            {
                throw new InvalidOperationException(string.Format("Unable to translate '{0}' to something we can loop over!", expr.ToString()));
            }

            return(ReGetIArrayInfo(resolved));
        }
        public IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container, Func <Expression, IArrayInfo> ReGetIArrayInfo)
        {
            if (!(expr is QuerySourceReferenceExpression))
            {
                return(null);
            }

            var preplacements = ParameterReplacementExpressionVisitor.ReplaceParameters(expr, cc);
            var r             = TranslatingExpressionVisitor.Translate(preplacements, cc.CacheCookies, e => e);

            //
            // If we don't know what we are doing here, bail!
            //

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

            return(ReGetIArrayInfo(r));
        }
        /// <summary>
        /// Look to see if this is a member access, and if so, then attempt to decode it.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        /// <param name="ReGetIArrayInfo"></param>
        /// <returns></returns>
        public IArrayInfo GetIArrayInfo(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container, Func <Expression, IArrayInfo> ReGetIArrayInfo)
        {
            // Make sure this is an expression we expect to be dealing with!
            if (expr.NodeType != ExpressionType.MemberAccess)
            {
                return(null);
            }

            // get the root expression, and decode it.
            var ma       = expr as MemberExpression;
            var resolved = ma.Expression.Resolve(gc, cc, container);

            if (resolved == ma.Expression)
            {
                return(null);
            }

            // Create a new member access and attempt to resolve that mess.
            var maNew = Expression.MakeMemberAccess(resolved, ma.Member);

            return(ReGetIArrayInfo(maNew));
        }
 /// <summary>
 /// No member lookup is possible (though it might be eventually!).
 /// </summary>
 /// <param name="expr"></param>
 /// <param name="gc"></param>
 /// <param name="cc"></param>
 /// <param name="container"></param>
 /// <returns></returns>
 public IValue ProcessMemberReference(MemberExpression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container)
 {
     throw new NotImplementedException();
 }