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."); }
/// <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); }