public void TestResultScopeCurrentScope() { var gc = new GeneratedCode(); var b1 = new StatementInlineBlock(); gc.Add(b1); gc.SetCurrentScopeAsResultScope(); var outterScope = gc.CurrentScope; var b2 = new StatementInlineBlock(); gc.Add(b2); gc.SetCurrentScopeAsResultScope(); gc.AddAtResultScope(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); Assert.AreEqual(0, b1.DeclaredVariables.Count(), "variables at outside loop after 0 add"); Assert.AreEqual(1, b2.DeclaredVariables.Count(), "variables at inner loop after 1 add"); gc.CurrentScope = outterScope; gc.AddAtResultScope(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); Assert.AreEqual(1, b1.DeclaredVariables.Count(), "variables at outside loop after 1 add"); Assert.AreEqual(1, b2.DeclaredVariables.Count(), "variables at inner loop after 2 add"); }
public void TestChangeScopeSpecificNextLevel() { GeneratedCode target = new GeneratedCode(); target.Add(new StatementInlineBlock()); IStatement s = new StatementInlineBlock(); var deepestStatementLevel = TestUtils.GetDeepestStatementLevel(target); var deepestDeclarLevel = TestUtils.GetDeepestBookingLevel(target); var currentS = target.CurrentScope; var curVars = deepestDeclarLevel.DeclaredVariables.Count(); var curStatements = deepestStatementLevel.Statements.Count(); var v1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); target.Add(v1); target.Add(s); target.CurrentScope = currentS; var v2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); target.Add(v2); s.Parent = null; target.Add(s); Assert.AreEqual(curStatements + 2, deepestStatementLevel.Statements.Count(), "Scope reset, should always be two extra statements here!"); Assert.AreEqual(curVars + 2, deepestDeclarLevel.DeclaredVariables.Count(), "Scope reset should have also reset where the variable was pointing"); }
public void TestCombineNestedForLoopOnOneSide() { var base1 = new StatementInlineBlock(); var limit = new LINQToTTreeLib.Variables.ValSimple("5", typeof(int)); var loopP1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var loop1 = new StatementForLoop(loopP1, limit); base1.Add(loop1); var base2 = new StatementInlineBlock(); var limit2 = new LINQToTTreeLib.Variables.ValSimple("5", typeof(int)); var loopP12 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var loop12 = new StatementForLoop(loopP12, limit); base2.Add(loop12); var loopP22 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var loop22 = new StatementForLoop(loopP22, limit); loop12.Add(loop22); var r = base1.TryCombineStatement(base2, new dummyOpt()); Assert.IsTrue(r, "combination should work"); Assert.AreEqual(base1, loop1.Parent, "loop 1 parent"); Assert.AreEqual(loop1, loop22.Parent, "Loop 2 parent"); }
/// <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); }
public void TestForFunctionNumber() { CPPTranslator target = new CPPTranslator(); var vInt = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); vInt.SetInitialValue("2"); GeneratedCode code = new GeneratedCode(); code.SetResult(vInt); var innerBlock = new StatementInlineBlock(); var vInt2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); vInt2.SetInitialValue("5"); innerBlock.Add(vInt2); code.Add(innerBlock); var r = TranslateGeneratedCode(target, code); Assert.IsTrue(r.ContainsKey("NumberOfQueryFunctions"), "Number of functions isn't here"); Assert.IsInstanceOfType(r["NumberOfQueryFunctions"], typeof(int), "# function type"); Assert.AreEqual(1, r["NumberOfQueryFunctions"], "# of functions"); Assert.IsTrue(r.ContainsKey("QueryFunctionBlocks"), "Missing query function blocks"); Assert.IsInstanceOfType(r["QueryFunctionBlocks"], typeof(IEnumerable <IEnumerable <string> >), "Type is incorrect"); var codeBlocks = r["QueryFunctionBlocks"] as IEnumerable <IEnumerable <string> >; Assert.AreEqual(1, codeBlocks.Count(), "Wrong number of code blocks"); }
public void TestObjectInitalizerInInnerBlock() { CPPTranslator target = new CPPTranslator(); var vInt = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); vInt.SetInitialValue("2"); GeneratedCode code = new GeneratedCode(); code.SetResult(vInt); var innerBlock = new StatementInlineBlock(); var vInt2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); vInt2.SetInitialValue("5"); innerBlock.Add(vInt2); innerBlock.Add(new StatementSimpleStatement("fork = dork")); code.Add(innerBlock); var r = TranslateGeneratedCode(target, code); var st = (r["QueryFunctionBlocks"] as IEnumerable <IEnumerable <string> >).First().ToArray(); Assert.AreEqual(6, st.Length, "incorrect number of statements"); Assert.AreEqual("int " + vInt2.RawValue + " = 5;", st[2].Trim(), "incorrect initialization"); }
public void TestResultScopeNull() { var gc = new GeneratedCode(); var b = new StatementInlineBlock(); gc.Add(b); gc.AddAtResultScope(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); }
public GeneratedCode(bool blockShouldBeBraced = true) { CodeBody = new StatementInlineBlock(blockShouldBeBraced: blockShouldBeBraced); CurrentScopePointer = CodeBody; CurrentDeclarationScopePointer = CodeBody; PreviousDeclarationScopePointer = null; Depth = 1; }
public IEnumerable <IStatementCompound> QueryCode() { for (int i = 0; i < 300; i++) { var innerBlock = new StatementInlineBlock(); var vInt2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); vInt2.SetInitialValue("5"); innerBlock.Add(vInt2); yield return(innerBlock); } }
public void CheckDepthAndPopWorkTogether() { var target = new GeneratedCode(); var s1 = new StatementInlineBlock(); target.Add(s1); var s2 = new StatementInlineBlock(); target.Add(s2); Assert.AreEqual(3, target.Depth); target.Pop(); Assert.AreEqual(2, target.Depth); }
public void DeclaredVariablesLocalOnly() { var outter = new StatementInlineBlock(); outter.Add(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); var s = new StatementForLoop(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)), new ValSimple("5", typeof(int))); s.Add(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); outter.Add(s); Assert.AreEqual(2, s.DeclaredVariables.Count()); Assert.AreEqual(3, s.AllDeclaredVariables.Count()); }
public void TestResultScopePop() { var gc = new GeneratedCode(); var b1 = new StatementInlineBlock(); gc.Add(b1); var b2 = new StatementInlineBlock(); gc.Add(b2); gc.SetCurrentScopeAsResultScope(); gc.AddAtResultScope(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); // This pop should remove the result scope, and it should be back to "null" now, which // should cause an exception. gc.Pop(); gc.AddAtResultScope(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); }
public void CheckPopAndCurrentScopeWorkTogether() { GeneratedCode target = new GeneratedCode(); IStatement s1 = new StatementInlineBlock(); target.Add(s1); var depth = target.Depth; var s2 = new StatementInlineBlock(); target.Add(s2); var firstTwoDown = target.CurrentScope; var s3 = new StatementInlineBlock(); target.Add(s3); target.CurrentScope = firstTwoDown; // This pop should put us at the s1 level. target.Pop(); Assert.AreEqual(depth, target.Depth); }
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 }); }
/// <summary>Test stub for ProcessResultOperator(ResultOperatorBase, QueryModel, IGeneratedCode)</summary> internal GeneratedCode ProcessResultOperator( ROTakeSkipOperators target, ResultOperatorBase resultOperator, QueryModel queryModel, GeneratedCode codeEnv ) { if (codeEnv.ResultValue != null) { throw new ArgumentException("this should not be null for this test"); } if (codeEnv.CodeBody.DeclaredVariables == null) { throw new ArgumentException("Need this declare variables to be defined"); } /// /// We always expect to be inside a loop - and depend on it for doing our declares, so add something... /// var inlineBlock = new StatementInlineBlock(); codeEnv.Add(inlineBlock); /// /// Get the environment setup and run it /// CodeContext c = new CodeContext(); c.SetLoopVariable(Expression.Variable(typeof(int), "d"), null); target.ProcessResultOperator(resultOperator, queryModel, codeEnv, c, MEFUtilities.MEFContainer); codeEnv.DumpCodeToConsole(); /// /// First, there should be a counter now declared and ready to go in the current variable block - which will /// be the outer one for this test. If this is the outter most, then this is going to be burried. /// var declBlock = inlineBlock.Parent.Parent as IBookingStatementBlock; Assert.IsNotNull(declBlock, "Expecting a declaration block above!"); Assert.AreEqual(1, inlineBlock.Statements.Count(), "Expected an if block/increment!"); Assert.IsInstanceOfType(inlineBlock.Statements.First(), typeof(StatementIfOnCount), "if statement not found!"); var s = inlineBlock.Statements.First() as StatementIfOnCount; bool isTopLevel = codeEnv.DumpCode().Where(l => l.Contains("static int")).Any(); if (!isTopLevel) { Assert.AreEqual(1, declBlock.DeclaredVariables.Count(), "Expected only 1 variable to be declared"); Assert.IsInstanceOfType(declBlock.DeclaredVariables.First(), typeof(DeclarableParameter), "Expected it to be a counter"); } else { Assert.AreEqual(1, (s.Parent as IBookingStatementBlock).DeclaredVariables.Count()); } string count = ""; if (resultOperator is SkipResultOperator) { count = (resultOperator as SkipResultOperator).Count.ToString(); } else if (resultOperator is TakeResultOperator) { count = (resultOperator as TakeResultOperator).Count.ToString(); } Assert.AreEqual(count, s.Limit.RawValue, "bad count made it through"); /// /// Finally, the current loop variable should be identical, and there should be no result set. /// Assert.IsNull(codeEnv.ResultValue, "result value"); Assert.IsInstanceOfType(c.LoopVariable, typeof(ParameterExpression), "loop variable type"); var lv = c.LoopVariable as ParameterExpression; Assert.AreEqual("d", lv.Name, "loop variable name"); // // Dump everything and return. To force it out, add a dummy statement // (because if statements, etc., are smart enough to not print anything if they // are empty). // codeEnv.Add(new StatementSimpleStatement("fork = left")); codeEnv.DumpCodeToConsole(); return(codeEnv); }
/// <summary> /// Cache the result of a query model into a function. /// </summary> /// <param name="queryModel"></param> /// <param name="qmSource"></param> private void VisitQueryModelCache(QueryModel queryModel, IQMFunctionSource qmSource) { // If we already have the answer for this cache, then we should just re-call the routine. if (qmSource.StatementBlock != null) { Debug.WriteLine("Using previously cached QM result"); GenerateQMFunctionCall(qmSource); return; } Debug.WriteLine("Cache: Gathering Data"); Debug.Indent(); // Since we don't have it cached, we need to re-run things, and carefully watch for // everything new that shows up. What shows up will be what we declare as the function // body. var currentScope = _codeEnv.CurrentScope; var topLevelStatement = new StatementInlineBlock(); _codeEnv.Add(topLevelStatement); _codeEnv.SetCurrentScopeAsResultScope(); // If this variable has been cached, then return it. Otherwise, mark the cache as filled. _codeEnv.Add(new StatementFilter(qmSource.CacheVariableGood)); _codeEnv.Add(new StatementReturn(qmSource.CacheVariable)); _codeEnv.Pop(); _codeEnv.Add(new StatementAssign(qmSource.CacheVariableGood, new ValSimple("true", typeof(bool), null))); // Now, run the code to process the query model! VisitQueryModelNoCache(queryModel); // The result is treated differently depending on it being a sequence or a single value. if (qmSource.IsSequence) { // Push the good values into our cache object. if (!(_codeContext.LoopIndexVariable is IDeclaredParameter)) { throw new InvalidOperationException("Can't deal with anythign that isn't a loop var"); } _codeEnv.Add(new StatementRecordIndicies(ExpressionToCPP.GetExpression(_codeContext.LoopVariable, _codeEnv, _codeContext, MEFContainer), qmSource.CacheVariable)); // Remember what the loop index variable is, as we are going to need it when we generate the return function! qmSource.SequenceVariable(_codeContext.LoopIndexVariable, _codeContext.LoopVariable); } else { // This is a specific result. Save just the result and return it. // Grab the result, cache it, and return it. var rtnExpr = ExpressionToCPP.GetExpression(_codeEnv.ResultValue, _codeEnv, _codeContext, MEFContainer); topLevelStatement.Add(new StatementAssign(qmSource.CacheVariable, rtnExpr)); // If the return is a declared parameter, then it must be actually defined somewhere (we normally don't). var declParam = _codeEnv.ResultValue as IDeclaredParameter; if (declParam != null) { topLevelStatement.Add(declParam, false); } } // Always return the proper value... topLevelStatement.Add(new StatementReturn(qmSource.CacheVariable)); // Now extract the block of code and put it in the function block. _codeEnv.CurrentScope = currentScope; qmSource.SetCodeBody(topLevelStatement); // Reset our state and remove the function code. And put in the function call in its place. _codeEnv.Remove(topLevelStatement); GenerateQMFunctionCall(qmSource); Debug.Unindent(); }