Esempio n. 1
0
        /// <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));
        }
        /// <summary>
        /// We have an enumerable range expression. Process it! :-)
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="cc"></param>
        /// <param name="container"></param>
        /// <param name="ReGetIArrayInfo"></param>
        /// <returns></returns>
        private IArrayInfo ProcessEnumerableRangeExpression(Expression expr, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container, Func <Expression, IArrayInfo> ReGetIArrayInfo)
        {
            var er = expr as EnumerableRangeExpression;

            var minVal = ExpressionToCPP.GetExpression(er.LowBoundary, gc, cc, container);
            var maxVal = ExpressionToCPP.GetExpression(er.HighBoundary, gc, cc, container);

            return(new EnumerableRangeArrayInfo(minVal, maxVal));
        }
            /// <summary>
            /// We only support a sub-class of expressions for now - so we'd better make sure we are protected!
            /// </summary>
            /// <param name="expression"></param>
            /// <returns></returns>
            protected override Expression VisitConditional(ConditionalExpression expression)
            {
                // We can support complex sub-expressions so long as they don't leak out of the
                // comparison.
                if (expression.Type.IsClass &&
                    (
                        CheckForSubQueries.CheckExpression(expression.IfFalse) ||
                        CheckForSubQueries.CheckExpression(expression.IfTrue))
                    )
                {
                    throw new NotSupportedException(string.Format("Complex true/false clauses in a conditional expression are not supported: '{0}'", expression.ToString()));
                }

                // If this is a class as a result, then we can't do much extra processing here. So skip.
                if (expression.Type.IsClass)
                {
                    return(base.VisitConditional(expression));
                }

                // Run the code for the test, and then create the if/then/else that will support it.
                var testExpression           = base.Visit(expression.Test);
                var testExpressionEvaluation = ExpressionToCPP.GetExpression(testExpression, GeneratedCode, CodeContext, MEFContainer);
                var testBoolInCode           = testExpressionEvaluation is DeclarableParameter p ? p : DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool));

                if (testBoolInCode != testExpressionEvaluation)
                {
                    GeneratedCode.Add(testBoolInCode);
                    GeneratedCode.Add(new Statements.StatementAssign(testBoolInCode, testExpressionEvaluation));
                }

                // The result
                var conditionalResult = DeclarableParameter.CreateDeclarableParameterExpression(expression.Type);

                GeneratedCode.Add(conditionalResult);

                // Do the if true statement
                var topScope = GeneratedCode.CurrentScope;

                GeneratedCode.Add(new Statements.StatementFilter(testBoolInCode));
                var iftrueExpression = Visit(expression.IfTrue);

                GeneratedCode.Add(new Statements.StatementAssign(conditionalResult, ExpressionToCPP.GetExpression(iftrueExpression, GeneratedCode, CodeContext, MEFContainer)));
                GeneratedCode.CurrentScope = topScope;

                // Do the if false statement
                GeneratedCode.Add(new Statements.StatementFilter(ExpressionToCPP.GetExpression(Expression.Not(testBoolInCode), GeneratedCode, CodeContext, MEFContainer)));
                var ifFalseExpression = Visit(expression.IfFalse);

                GeneratedCode.Add(new Statements.StatementAssign(conditionalResult, ExpressionToCPP.GetExpression(ifFalseExpression, GeneratedCode, CodeContext, MEFContainer)));
                GeneratedCode.CurrentScope = topScope;

                // Consider this expression now transformed, so return the result, not
                // the conditional expression itself.
                return(conditionalResult);
            }
Esempio n. 4
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);
        }