public void TestNestedFind()
        {
            var a = Expression.Add(
                DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)),
                DeclarableParameter.CreateDeclarableParameterExpression(typeof(double))
                );
            var t = FindDeclarableParameters.FindAll(a).Count();

            Assert.AreEqual(t, 2, "Two different decl in an add statement.");
        }
Example #2
0
        /// <summary>
        /// Turn a query model into code.
        /// </summary>
        /// <param name="queryModel"></param>
        private void VisitQueryModelNoCache(QueryModel queryModel)
        {
            // Cache the referenced query expressions and restore them at the end.

            var cachedReferencedQS = _codeContext.GetAndResetQuerySourceLookups();

            // Protect against all returns...

            try
            {
                //
                // If the query model is something that is trivial, then
                // perhaps there is a short-cut we can take?
                //

                if (queryModel.IsIdentityQuery() && queryModel.ResultOperators.Count == 1)
                {
                    var ro        = queryModel.ResultOperators[0];
                    var processor = _operators.FindScalarROProcessor(ro.GetType());
                    if (processor != null)
                    {
                        var result = processor.ProcessIdentityQuery(ro, queryModel, _codeEnv, _codeContext, MEFContainer);
                        if (result != null &&
                            result.Item1)
                        {
                            Debug.WriteLine("Identity Query being processed");
                            _codeEnv.SetResult(result.Item2);
                            return;
                        }
                    }
                }

                // Have we seen this query model before? If so, perhaps we can just short-circuit this?

                var cachedResult = _codeContext.GetReplacement(queryModel);
                if (cachedResult != null)
                {
                    var context = _codeEnv.FirstAllInScopeFromNow(FindDeclarableParameters.FindAll(cachedResult));
                    if (context != null)
                    {
                        _codeEnv.SetResult(cachedResult);
                        return;
                    }
                }

                // If we drop through here, then let the full machinery parse the thing
                base.VisitQueryModel(queryModel);
            }
            finally
            {
                _codeContext.RestoreQuerySourceLookups(cachedReferencedQS);
            }
        }
        public void TestSimpleFind()
        {
            var t = FindDeclarableParameters.FindAll(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))).Count();

            Assert.AreEqual(t, 1, "single decl statement.");
        }
        public void TestFindNothing()
        {
            var t = FindDeclarableParameters.FindAll(Expression.Constant(10)).Count();

            Assert.AreEqual(t, 0, "no decl param in a constant expression.");
        }
        /// <summary>
        /// Build a code statement from the include files, the expression for the method call, and the generated lines of code.
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="gc"></param>
        /// <param name="container"></param>
        /// <param name="includeFiles"></param>
        /// <param name="loc"></param>
        /// <returns></returns>
        public static IValue BuildCPPCodeStatement(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container, string[] includeFiles, string[] loc)
        {
            // Get include files in.
            if (includeFiles != null)
            {
                foreach (var inc in includeFiles)
                {
                    gc.AddIncludeFile(inc);
                }
            }

            // Next, go after the lines of code. We have to first sort out what parameter names we are looking at,
            // and then force a translation of those parameters into simple values we can pass to the C++ code we
            // are going to pull back.
            var paramsTranslated = from p in expr.Arguments.Zip(expr.Method.GetParameters(), (arg, param) => Tuple.Create(arg, param))
                                   select new
            {
                Name       = p.Item2.Name,
                Translated = ExpressionToCPP.InternalGetExpression(p.Item1, gc, null, container)
            };
            var paramLookup = paramsTranslated.ToDictionary(v => v.Name, v => v.Translated.ApplyParensIfNeeded());

            // Parse out the list of variables that are used. We will be passing these up the line as needed
            // so that we can tell how to optimize things.
            var dependents = new HashSet <string>(FindDeclarableParameters.FindAll(expr).Select(e => e.RawValue));

            // We also need a return variable. Since this can be multiple lines of code and we don't
            // know how the result will be used, we have to declare it up front... and pray they
            // use it correctly! :-)

            var cppResult = DeclarableParameter.CreateDeclarableParameterExpression(expr.Type);

            var cppStatement = new CPPCodeStatement(expr.Method, cppResult, loc, dependents);

            gc.Add(cppStatement);
            gc.Add(cppResult);

            paramLookup.Add(expr.Method.Name, cppResult.RawValue);

            var result = new ValSimple(cppResult.RawValue, expr.Type, DeclarableParameter.CreateDeclarableParameterExpression(cppResult.RawValue, expr.Type).AsArray());

            // Make sure a result exists in here! This at least will prevent some bad C++ code from getting generated!
            var  lookForResult = new Regex(string.Format(@"\b{0}\b", expr.Method.Name));
            bool didReference  = loc.Any(l => lookForResult.Match(l).Success);

            if (!didReference)
            {
                throw new ArgumentException(string.Format("The C++ code attached to the method '{0}' doesn't seem to set a result.", expr.Method.Name));
            }

            // Figure out if there are any Unique variables. If there are, then we need to do
            // a replacement on them.
            var findUnique        = new Regex(@"\b\w*Unique\b");
            var varUniqueRequests = (from l in loc
                                     let matches = findUnique.Matches(l)
                                                   from m in Enumerable.Range(0, matches.Count)
                                                   select matches[m].Value).Distinct();

            foreach (var varRepl in varUniqueRequests)
            {
                var uniqueName       = varRepl.Substring(0, varRepl.Length - "Unique".Length);
                var uniqueTranslated = uniqueName + _uniqueCounter.ToString();
                cppStatement.AddUniqueVariable(varRepl, uniqueTranslated);
                _uniqueCounter++;
            }

            // Add the parameters that need to be translated here.
            foreach (var paramName in paramLookup)
            {
                cppStatement.AddParamReplacement(paramName.Key, paramName.Value);
            }

            return(result);
        }