/// <summary> /// Do a loop over a list of declareable groups. /// </summary> /// <param name="mapOfGroups"></param> /// <param name="groupIndex"></param> public StatementLoopOverGroups(IValue mapOfGroups) { if (mapOfGroups == null) throw new ArgumentNullException("mapOfGroups"); this._mapOfGroups = mapOfGroups; var iteratorType = typeof(IEnumerable<int>).GetGenericTypeDefinition().MakeGenericType(new Type[] { mapOfGroups.Type }); this._groupIndex = DeclarableParameter.CreateDeclarableParameterExpression(iteratorType); }
public StatementLoopOverGroupItems(IValue arrayToLoopOver) { _groupArray = arrayToLoopOver; _counter = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); if (_groupArray == null) throw new ArgumentNullException("_groupArray"); if (_counter == null) throw new ArgumentNullException("counter"); }
/// <summary> /// Create with the accumulator and the function resolved that we will use to do the translation. /// </summary> /// <param name="accumulator"></param> /// <param name="funcResolved"></param> /// <param name="dependentVariables">List of variables that the val statement depends on</param> public StatementAggregate(DeclarableParameter result, IValue val) { if (result == null) throw new ArgumentNullException("Accumulator must not be zero"); if (val == null) throw new ArgumentNullException("funcResolved must not be null"); ResultVariable = result; Expression = val; // Which variables we have as input and output DependentVariables = new HashSet<string>(val.Dependants.Select(v => v.RawValue)); ResultVariables = new HashSet<string>() { result.RawValue }; }
public void AggregateCombineWithRename() { // a = a + b // c = c + b // These two should combine correctly, somehow. var a = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var ainc = new ValSimple(string.Format("{0}+b", a.ParameterName), typeof(int)); var s1 = new StatementAggregate(a, ainc); var c = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var cinc = new ValSimple(string.Format("{0}+b", c.ParameterName), typeof(int)); var s2 = new StatementAggregate(c, cinc); var opt = new MyCodeOptimizer(true); var result = s1.TryCombineStatement(s2, opt); Assert.IsTrue(result, "Expected combination would work"); Assert.AreEqual(a.ParameterName, opt.NewVariable.ParameterName, "new name not renamed to"); Assert.AreEqual(c.ParameterName, opt.OldName, "old name for rename not right"); }
public void AggregateRenameDependent() { var result = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var dep = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var depname = dep.RawValue; var target = new StatementAggregate(result, dep); target.CodeItUp().DumpToConsole(); target.RenameVariable(dep.RawValue, "foot"); target.CodeItUp().DumpToConsole(); var r = target.CodeItUp().ToArray(); Assert.AreEqual(-1, r[0].IndexOf(depname)); Assert.AreNotEqual(-1, r[0].IndexOf("foot")); Assert.AreEqual(result.RawValue, target.ResultVariable.RawValue); Assert.AreEqual(1, target.DependentVariables.Count()); Assert.AreEqual("foot", target.DependentVariables.First()); }
/// <summary> /// Create with the accumulator and the function resolved that we will use to do the translation. /// </summary> /// <param name="accumulator"></param> /// <param name="funcResolved"></param> /// <param name="dependentVariables">List of variables that the val statement depends on</param> public StatementAggregate(DeclarableParameter result, IValue val) { if (result == null) { throw new ArgumentNullException("Accumulator must not be zero"); } if (val == null) { throw new ArgumentNullException("funcResolved must not be null"); } ResultVariable = result; Expression = val; // Which variables we have as input and output DependentVariables = new HashSet <string>(val.Dependants.Select(v => v.RawValue)); ResultVariables = new HashSet <string>() { result.RawValue }; }
public void TestSimpleCombine() { var q1 = new GeneratedCode(); var q2 = new GeneratedCode(); var s1 = new Statements.StatementSimpleStatement("dude1"); var s2 = new Statements.StatementSimpleStatement("dude2"); q1.Add(s1); q2.Add(s2); var v1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var v2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); q1.SetResult(v1); q2.SetResult(v2); var target = new CombinedGeneratedCode(); target.AddGeneratedCode(q1); target.AddGeneratedCode(q2); Assert.AreEqual(1, target.QueryCode().Count(), "didn't combine blocks correctly"); var c = target.QueryCode().First(); Assert.AreEqual(2, c.Statements.Count(), "bad # of statements in combined query"); var st1 = c.Statements.First(); var st2 = c.Statements.Skip(1).First(); Assert.IsInstanceOfType(st1, typeof(Statements.StatementSimpleStatement), "st1"); Assert.IsInstanceOfType(st2, typeof(Statements.StatementSimpleStatement), "st2"); var sst1 = st1 as Statements.StatementSimpleStatement; var sst2 = st2 as Statements.StatementSimpleStatement; Assert.IsTrue("dude1" == sst1.Line || "dude1" == sst2.Line, "sst1"); Assert.IsTrue("dude2" == sst1.Line || "dude2" == sst2.Line, "sst2"); }
public void CPPNeedSomeReplacements() { // two identical expressions var target = new TypeHandlerCPPCode(); var gc = new GeneratedCode(); var context = new CodeContext(); var p_pt_1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)); var p_eta_1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)); var p_phi_1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)); var p_E_1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)); // Create first call var e1 = Expression.Call(typeof(TLZHelper).GetMethod("CreateTLZBE"), p_pt_1, p_eta_1, p_phi_1, p_E_1); var e1Value = target.CodeMethodCall(e1, gc, MEFUtilities.MEFContainer); var p_pt_2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)); var p_eta_2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)); var p_phi_2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)); var p_E_2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(double)); var e2 = Expression.Call(typeof(TLZHelper).GetMethod("CreateTLZBE"), p_pt_2, p_eta_2, p_phi_2, p_E_2); var e2Value = target.CodeMethodCall(e2, gc, MEFUtilities.MEFContainer); gc.DumpCodeToConsole(); // Now, extract the two main statements. Assert.AreEqual(2, gc.CodeBody.Statements.Count(), "# of statements"); var s1 = gc.CodeBody.Statements.First() as ICMStatementInfo; var s2 = gc.CodeBody.Statements.Skip(1).First() as ICMStatementInfo; // Now, see if we can do the requirement. var renames = new Tuple <string, string>[] { new Tuple <string, string>(p_pt_2.RawValue, p_pt_1.RawValue), new Tuple <string, string>(p_eta_2.RawValue, p_eta_1.RawValue) }; var r = s1.RequiredForEquivalence(s2, renames); Assert.IsTrue(r.Item1, "We should be able to do the translation"); Assert.AreEqual(3, r.Item2.Count(), "# of variable translations required"); }
public void TestMultipleSavers() { var index1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var seen1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); var index2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var seen2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); var index3 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var index4 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var s1 = new StatementRecordValue(index1, new ValSimple("i", typeof(int)), seen1, true); s1.AddNewSaver(index3, new ValSimple("j", typeof(int))); var s2 = new StatementRecordValue(index2, new ValSimple("i", typeof(int)), seen2, true); s2.AddNewSaver(index4, new ValSimple("j", typeof(int))); var dop = new DummyTrackingOptimizationService(); Assert.IsTrue(s1.TryCombineStatement(s2, dop), "Combined 2 multi-saver guys"); Assert.AreEqual(3, dop._renameRequests.Count, "# of rename requests"); Assert.AreEqual(Tuple.Create(index2.RawValue, index1.RawValue), dop._renameRequests[0], "first rename"); Assert.AreEqual(Tuple.Create(index4.RawValue, index3.RawValue), dop._renameRequests[1], "second rename"); }
public void ForLoopRenameTwiceAsSource() { var c1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var s1 = new StatementForLoop(c1, new ValSimple("5", typeof(int))); var a1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var v1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); s1.Add(new StatementAssign(a1, new ValSimple("10", typeof(int)))); s1.Add(new StatementAssign(a1, new ValSimple($"{a1.RawValue}+{a1.RawValue}", typeof(int), new IDeclaredParameter[] { a1 }))); var c2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var s2 = new StatementForLoop(c1, new ValSimple("6", typeof(int))); var a2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var v2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); s2.Add(new StatementAssign(a2, new ValSimple("10", typeof(int)))); s2.Add(new StatementAssign(a2, new ValSimple($"{a2.RawValue}+{v2.RawValue}", typeof(int), new IDeclaredParameter[] { a2, v2 }))); var r = s1.RequiredForEquivalence(s2); // Since only loop variable matters here, we don't care, and we can do the rename. Assert.IsFalse(r.Item1, "Should be equivalent"); }
public void TestObjectPointer() { CPPTranslator target = new CPPTranslator(); var obj = DeclarableParameter.CreateDeclarableParameterExpression(typeof(ROOTNET.NTH1F)); GeneratedCode code = new GeneratedCode(); code.SetResult(obj); var r = TranslateGeneratedCode(target, code); var rlist = r["ResultVariables"] as IEnumerable <CPPTranslator.VarInfo>; var rv = rlist.First(); Assert.AreEqual("TH1F*", rv.VariableType, "type is not right"); var inFiles = code.IncludeFiles.ToArray(); foreach (var item in inFiles) { Console.WriteLine("include file '{0}'", item); } Assert.IsTrue(inFiles.Contains("TH1F.h"), "Missing include file"); }
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 }); }
public void TestCombineWithRenameAtDifferentLevels() { // Try to combine two statements that look like they should combine, // but one variable is declared at a different "level" than the other // up the hierarchy. var inline1 = new StatementInlineBlock(); var inline11 = new StatementInlineBlock(); inline1.Add(inline11); var inline2 = new StatementInlineBlock(); var inline22 = new StatementInlineBlock(); inline2.Add(inline22); var vdecl1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var vdecl2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); inline1.Add(vdecl1); inline22.Add(vdecl2); var s1 = new CombineTestStatement(vdecl1); inline11.Add(s1); var s2 = new CombineTestStatement(vdecl2); inline22.Add(s2); var result = inline1.TryCombineStatement(inline2, null); Assert.IsTrue(result, "try combine should go ok"); Assert.AreEqual(1, inline1.Statements.Count(), "# statements inside inline 1"); var innerBlock = inline1.Statements.First() as IBookingStatementBlock; Assert.IsNotNull(innerBlock, "inner block a booking statement"); Assert.AreEqual(2, innerBlock.Statements.Count(), "Statements in inner block should not have combined"); }
public void TestCombineNestedForLoop() { var limit = new LINQToTTreeLib.Variables.ValSimple("5", typeof(int)); var loopP1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var loop1 = new StatementForLoop(loopP1, limit); var loopP2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var loop2 = new StatementForLoop(loopP2, limit); loop1.Add(loop2); var limit2 = new LINQToTTreeLib.Variables.ValSimple("5", typeof(int)); var loopP12 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var loop12 = new StatementForLoop(loopP12, limit); var loopP22 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var loop22 = new StatementForLoop(loopP22, limit); loop12.Add(loop22); var r = loop1.TryCombineStatement(loop12, new dummyOpt()); Assert.IsTrue(r, "combination should work"); Assert.IsNull(loop1.Parent, "loop 1 parent"); Assert.AreEqual(loop1, loop2.Parent, "Loop 2 parent"); }
public void ForLoopSimilarStatements() { var c1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var s1 = new StatementForLoop(c1, new ValSimple("5", typeof(int))); var a1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); s1.Add(new StatementAssign(a1, new ValSimple("10", typeof(int)))); var c2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var s2 = new StatementForLoop(c2, new ValSimple("5", typeof(int))); var a2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); s2.Add(new StatementAssign(a2, new ValSimple("10", typeof(int)))); var r = s1.RequiredForEquivalence(s2); // Since only loop variable matters here, we don't care, and we can do the rename. Assert.IsTrue(r.Item1, "Should be equivalent"); var renames = r.Item2.ToArray(); Assert.AreEqual(1, renames.Length, "# of renames"); Assert.AreEqual(a2.RawValue, renames[0].Item1, "from rename"); Assert.AreEqual(a1.RawValue, renames[0].Item2, "to rename"); }
public void TestRename() { var indiciesToInspect = DeclarableParameter.CreateDeclarableParameterArrayExpression(typeof(int)); var index1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var index2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var passedArray = DeclarableParameter.CreateDeclarableParameterArrayExpression(typeof(bool)); var s1 = new StatementCheckLoopPairwise(indiciesToInspect, index1, index2, passedArray); s1.Add(new StatementSimpleStatement(string.Format("{0} = fork", index2.RawValue))); s1.RenameVariable(indiciesToInspect.RawValue, "dude1"); Assert.AreEqual("dude1", indiciesToInspect.RawValue, "indices 1"); s1.RenameVariable(index1.RawValue, "dude2"); Assert.AreEqual(index1.RawValue, "dude2", "index1 didn't get set"); s1.RenameVariable(index2.RawValue, "dude3"); Assert.AreEqual(index2.RawValue, "dude3", "index2 didn't get set"); s1.RenameVariable(passedArray.RawValue, "dude4"); Assert.AreEqual(passedArray.RawValue, "dude4", "passed array didn't get set"); Assert.AreEqual("dude3 = fork", (s1.Statements.First() as StatementSimpleStatement).Line, "statement 1 didn't get translated"); }
/// <summary> /// Add the code to do the pair-wise loop. /// </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) { var ro = resultOperator as PairWiseAllResultOperator; if (ro == null) { throw new ArgumentNullException("Result operator is not of PairWiseAll type"); } // // First, record all the good indicies for this array // var arrayRecord = DeclarableParameter.CreateDeclarableParameterArrayExpression(typeof(int)); gc.AddOutsideLoop(arrayRecord); var recordIndexStatement = new StatementRecordIndicies(ExpressionToCPP.GetExpression(cc.LoopIndexVariable.AsExpression(), gc, cc, container), arrayRecord); gc.Add(recordIndexStatement); gc.Pop(); /// /// Next, we create a loop that will mark all the guys as "good" that /// the pair-wise function. Hopefully the statement below will be efficient and /// not double-try anything! The lambda we've been passed we have to evaluate - twice - /// for each, and pass it as a "test" to the statement. It will be some horrendus expression /// I suppose! /// var passAll = DeclarableParameter.CreateDeclarableParameterArrayExpression(typeof(bool)); gc.Add(passAll); var index1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var index2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var index1Lookup = cc.LoopVariable.ReplaceSubExpression(cc.LoopIndexVariable.AsExpression(), index1); //Expression.ArrayIndex(array, index1); var index2Lookup = cc.LoopVariable.ReplaceSubExpression(cc.LoopIndexVariable.AsExpression(), index2); //Expression.ArrayIndex(array, index2); var callLambda = Expression.Invoke(ro.Test, index1Lookup, index2Lookup ); var xcheck = new Statements.StatementCheckLoopPairwise(arrayRecord, index1, index2, passAll); gc.Add(xcheck); var test = new Statements.StatementTestLoopPairwise( passAll, ExpressionToCPP.GetExpression(callLambda, gc, cc, container)); gc.Add(test); gc.Pop(); // // Ok, the result of that will be the array we have here is now filled with the // "proper" stuff. That is - we have "true" in everthing that is good. So we will // now just loop over that and apply the index as needed. // var goodIndex = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); gc.Add(goodIndex); var loopOverGood = new Statements.StatementLoopOverGood(arrayRecord, passAll, goodIndex); gc.Add(loopOverGood); cc.SetLoopVariable(cc.LoopVariable.ReplaceSubExpression(cc.LoopIndexVariable.AsExpression(), goodIndex), goodIndex); }
public void TestForROOTTH1F() { var v = DeclarableParameter.CreateDeclarableParameterExpression(typeof(ROOTNET.Interface.NTH1F)); Assert.IsTrue(CanHandle(new SaveVarObject(), v), "TH1F"); }
public StatementWithSideEffects(DeclarableParameter loopP, DeclarableParameter result = null) { this._trackedVar = loopP; this._resultVar = result; }
public void TestSimpleFind() { var t = FindDeclarableParameters.FindAll(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))).Count(); Assert.AreEqual(t, 1, "single decl statement."); }
/// <summary> /// Code up the min/max result operators. We run the loop out, and then /// we return the result whatever it is. We only work when the type is /// something simple we can deal with! /// </summary> /// <param name="resultOperator"></param> /// <param name="queryModel"></param> /// <param name="_codeEnv"></param> /// <param name="_codeContext"></param> /// <param name="container"></param> /// <returns></returns> public Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container) { /// /// Some argument checking /// if (cc == null) { throw new ArgumentNullException("cc"); } if (gc == null) { throw new ArgumentNullException("gc"); } if (gc.Depth == 1) { throw new ArgumentException("The Max/Min operators can't be used as result operators for a query - they can only be used in a sub-query"); } /// /// Is it min or max? /// var minOperator = resultOperator as MinResultOperator; var maxOperator = resultOperator as MaxResultOperator; if (minOperator == null && maxOperator == null) { throw new InvalidOperationException("Should always have min or max operator!"); } bool doMax = maxOperator != null; bool returnDefaultValue = false; if (doMax) { returnDefaultValue = maxOperator.ReturnDefaultWhenEmpty; } else { returnDefaultValue = minOperator.ReturnDefaultWhenEmpty; } /// /// Next, look at the type of the current result that is running. /// var valueExpr = queryModel.SelectClause.Selector; if (!TimeCanBeCompared(valueExpr.Type)) { throw new ArgumentException(string.Format("I don't know how to fix the min or max of a sequence of '{0}'s", cc.LoopVariable.Type.Name)); } /// /// Now, declare two variables, one bool which gets set when we get the first value, /// and the other to hold the min/max value! Note that we initalize the variable to /// the proper type. We don't declare minmax holder - as it may end up be used /// externally. /// var vIsFilled = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); vIsFilled.InitialValue = new ValSimple("false", typeof(bool), null); var vMaxMin = DeclarableParameter.CreateDeclarableParameterExpression(valueExpr.Type); vMaxMin.InitialValue = new ValSimple("0", typeof(int), null); gc.AddOutsideLoop(vIsFilled); /// /// The expression we want to mimize or maximize /// var exprToMinOrMaximize = ExpressionToCPP.GetExpression(valueExpr, gc, cc, container); /// /// Now, we just have to put the x-checks in there. /// var ifStatement = new Statements.StatementMinMaxTest(vIsFilled, vMaxMin, exprToMinOrMaximize, doMax); gc.Add(ifStatement); return(vMaxMin); }
/// <summary> /// Write up the code for the any or the all /// </summary> /// <param name="resultOperator"></param> /// <param name="queryModel"></param> /// <param name="gc"></param> /// <param name="cc"></param> /// <param name="container"></param> /// <returns></returns> public Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container) { if (cc == null) { throw new ArgumentNullException("cc"); } if (gc == null) { throw new ArgumentNullException("gc"); } var all = resultOperator as AllResultOperator; var any = resultOperator as AnyResultOperator; /// /// Next, change the predicate into something that can be tested (as an if statement) /// For All: /// initial: aresult = true; /// if (aresult && !pred) { aresult = false; } /// For Any: /// initial: aresult = false; /// if (!aresult && pred) { aresult = true; } /// var aresult = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); IValue predicate = null; IValue predicateFastTest = null; string initialValue = ""; string markedValue = ""; if (all != null) { predicateFastTest = ExpressionToCPP.GetExpression(aresult, gc, cc, container); var notPredicate = Expression.Not(all.Predicate); predicate = ExpressionToCPP.GetExpression(notPredicate, gc, cc, container); initialValue = "true"; markedValue = "false"; } else { predicate = null; predicateFastTest = ExpressionToCPP.GetExpression(Expression.Not(aresult), gc, cc, container); initialValue = "false"; markedValue = "true"; } /// /// The result is a simple bool. This is what we will be handing back. /// aresult.SetInitialValue(initialValue); /// /// And the statements now. Instead of building up the code, we instead do a "global" statement. /// This makes it easier to re-combine later when we collapse queires. /// var ifstatement = new Statements.StatementAnyAllDetector(predicate, aresult, predicateFastTest, markedValue); gc.Add(ifstatement); /// /// Done! /// return(aresult); }
public void TestAddOutsideLoopWithNothing() { var target = new GeneratedCode(); target.AddOutsideLoop(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); }
public void TestForROOTTObject() { var v = DeclarableParameter.CreateDeclarableParameterExpression(typeof(ROOTNET.Interface.NTObject)); Assert.IsFalse(CanHandle(new SaveVarObject(), v), "TObject array should be false"); }
/// <summary> /// Generate the code for a tree filling. /// </summary> /// <param name="stream"></param> /// <param name="value"></param> public StatementFillTree(DeclarableParameter stream, Tuple <IValue, string>[] value) { this._fileAndTreePair = stream; this._columnValues = value; }
/// <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); }
public void TestCombinePreserveOrder() { // We will have two if statements to do the combination with. They basically "hide" the modification. var checkVar1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); var if1s1 = new StatementFilter(new ValSimple(checkVar1.RawValue, typeof(bool))); var if1s2 = new StatementFilter(new ValSimple(checkVar1.RawValue, typeof(bool))); var checkVar2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); var if2s1 = new StatementFilter(new ValSimple(checkVar2.RawValue, typeof(bool))); var if2s2 = new StatementFilter(new ValSimple(checkVar2.RawValue, typeof(bool))); var blockWithModified = new StatementInlineBlock(); var blockWithoutModified = new StatementInlineBlock(); blockWithModified.Add(checkVar1); blockWithModified.Add(checkVar2); blockWithoutModified.Add(checkVar1); blockWithoutModified.Add(checkVar2); // Not the opposite order we put them in here! blockWithModified.Add(if1s1); blockWithModified.Add(if2s1); blockWithoutModified.Add(if2s2); blockWithoutModified.Add(if1s2); // Have the modified if statement contain the modification now. var varToBeModified = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var statementModifier = new StatementAssign(varToBeModified, new ValSimple("1", typeof(int))); blockWithModified.Add(varToBeModified); if1s1.Add(statementModifier); // Next, we need to use the variable in the second if statement. Which, since it is like the first, should be pushed back up there. var finalVar = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var assignment = new StatementAssign(finalVar, varToBeModified); blockWithModified.Add(finalVar); if2s1.Add(assignment); // Combine var r = blockWithoutModified.TryCombineStatement(blockWithModified, null); Assert.IsTrue(r, "try combine result"); foreach (var s in blockWithoutModified.CodeItUp()) { System.Diagnostics.Trace.WriteLine(s); } // Make sure the checkVar guy comes after the modified statement. var topLevelStatementForAssign = findStatementThatContains(blockWithoutModified, assignment); var posOfUse = findStatementIndex(blockWithoutModified, topLevelStatementForAssign); var topLevelStatementForModification = findStatementThatContains(blockWithoutModified, statementModifier); var posOfMod = findStatementIndex(blockWithoutModified, topLevelStatementForModification); Assert.IsTrue(posOfMod < posOfUse, string.Format("Modification happens after use. modification: {0} use {1}", posOfMod, posOfUse)); }
public void TestAddOneLevelUpTopLevel() { GeneratedCode gc = new GeneratedCode(); gc.AddOneLevelUp(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int))); }
public void CreateDeclarableParameterMapExpressionTest() { var r = DeclarableParameter.CreateDeclarableParameterMapExpression(typeof(int), typeof(double)); Assert.AreEqual(typeof(Dictionary <int, double>), r.Type, "map type not right"); }
/// <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> /// Sort the current stream of the query. To do this we run through all the results, sort them, /// and then start a new loop. /// </summary> /// <param name="ordering"></param> /// <param name="queryModel"></param> /// <param name="orderByClause"></param> /// <param name="index"></param> public override void VisitOrdering(Ordering ordering, QueryModel queryModel, OrderByClause orderByClause, int index) { // // Only number types can be sorted. // if (!ordering.Expression.Type.IsNumberType()) { throw new InvalidOperationException(string.Format("Don't know how to sort query by type '{0}'.", ordering.Expression.Type.Name)); } // // First, record all the indicies and the values. This is what we are going to be sorting. // var mapRecord = DeclarableParameter.CreateDeclarableParameterMapExpression(ordering.Expression.Type, _codeContext.LoopIndexVariable.Type.MakeArrayType()); _codeEnv.AddOutsideLoop(mapRecord); var savePairValues = new StatementRecordPairValues(mapRecord, ExpressionToCPP.GetExpression(ordering.Expression, _codeEnv, _codeContext, MEFContainer), ExpressionToCPP.GetExpression(_codeContext.LoopIndexVariable.AsExpression(), _codeEnv, _codeContext, MEFContainer)); _codeEnv.Add(savePairValues); var otherSavers = _codeEnv.GetUsedQuerySourceVariables(savePairValues, _codeContext.LoopIndexVariable) .Select(v => { var mr = DeclarableParameter.CreateDeclarableParameterMapExpression(ordering.Expression.Type, v.Type.MakeArrayType()); _codeEnv.AddOutsideLoop(mr); savePairValues.AddSaver(mr, v); return(Tuple.Create(v, mr)); }) .ToArray(); // Get back to the results level now, where we do the sorting! _codeEnv.PopToResultsLevel(); // // Now, we need to sort and loop over the variables in the map. This is a bit of a messy // multi-line statement, and it is a compound statement. // var sortAndRunLoop = new StatementLoopOverSortedPairValue(mapRecord, ordering.OrderingDirection == OrderingDirection.Asc); _codeEnv.Add(sortAndRunLoop); var pindex = sortAndRunLoop.IndexVariable; var lv = _codeContext.LoopIndexVariable.RawValue; _codeContext.Add(lv, pindex); foreach (var savers in otherSavers) { var newVarName = sortAndRunLoop.RestoreOtherSaver(savers.Item2); _codeContext.Add(savers.Item1.RawValue, newVarName); } _codeContext.SetLoopVariable(_codeContext.LoopVariable.ReplaceSubExpression(_codeContext.LoopIndexVariable.AsExpression(), pindex), pindex); }
public Expression ProcessResultOperator(ResultOperatorBase resultOperator, QueryModel queryModel, IGeneratedQueryCode gc, ICodeContext cc, CompositionContainer container) { if (resultOperator == null) { throw new ArgumentNullException("resultOperator"); } if (cc == null) { throw new ArgumentNullException("CodeContext can't be null"); } // Determine the type of the result operator we are processing and // anything we need to know about it. Type sumType; sumType = cc.LoopVariable.Type; bool doAverage = false; if (resultOperator is SumResultOperator) { doAverage = false; } else { doAverage = true; } // We only know how to sum basic types if (!sumType.IsNumberType()) { throw new InvalidOperationException(string.Format("Do not know how to generate C++ to sum type {0}.", sumType.Name)); } var accumulator = DeclarableParameter.CreateDeclarableParameterExpression(sumType); accumulator.SetInitialValue("0"); // Sum and average are a alike in that we are going to add everything we see up. var add = Expression.Add(accumulator, cc.LoopVariable); var addResolved = ExpressionToCPP.GetExpression(add, gc, cc, container); gc.Add(new StatementAggregate(accumulator, addResolved)); // If this is a sum no further work needs to happen. if (!doAverage) { return(accumulator); } // If this is a average then we need to add a simple count. var counter = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); counter.SetInitialValue("0"); var incbyone = Expression.Add(counter, Expression.Constant(1)); gc.Add(new StatementAggregate(counter, ExpressionToCPP.GetExpression(incbyone, gc, cc, container))); // Next, we have to delcare the counter and the accumulator. These are now both temprorary variables. if (cc.LoopIndexVariable == null) { throw new AverageNotAllowedAtTopLevelException("Attempt to use Average at top level, accross events. Not currently implemented."); } gc.AddOutsideLoop(counter); gc.AddOutsideLoop(accumulator); // It is an error to average a sequence with no elements. So we need to throw a C++ exception. We need to pop up out of the loop in order // to do this. // http://msdn.microsoft.com/en-us/library/bb354760.aspx (for specs on Average on this). var testForSomething = Expression.Equal(counter, Expression.Constant(0)); gc.AddAtResultScope(new StatementThrowIfTrue(ExpressionToCPP.GetExpression(testForSomething, gc, cc, container), "Can't take an average of a null sequence")); var returnType = DetermineAverageReturnType(sumType); var faccumulator = Expression.Convert(accumulator, returnType); var fcount = Expression.Convert(counter, returnType); var divide = Expression.Divide(faccumulator, fcount); // We are done with this calculation, so pop up and out. gc.Pop(); return(divide); }
/// <summary> /// Process the First/last. This means adding a pointer (or not if we are looking at a plane type) and /// then filling it till it is full or filling it till the loop is done. Bomb out if we are asked to at the end!! /// </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) { /// /// First, do data normalization /// var asFirst = resultOperator as FirstResultOperator; var asLast = resultOperator as LastResultOperator; if (asFirst == null && asLast == null) { throw new ArgumentNullException("First/Last operator must be either first or last, and not null!"); } bool isFirst = asFirst != null; bool bombIfNothing = true; if (isFirst) { bombIfNothing = !asFirst.ReturnDefaultWhenEmpty; } else { bombIfNothing = !asLast.ReturnDefaultWhenEmpty; } // // Figure out if we need to cache the result: // - simple variable which has a default value which can be used later on. // like a double, etc. // - We actually allow for a default variable. // bool cacheResult = cc.LoopVariable.Type.IsNumberType(); cacheResult = cacheResult && !bombIfNothing; // // Next, make sure we are looping over something. This had better be an array we are looking at! // if (cc.LoopIndexVariable == null) { throw new InvalidOperationException(string.Format("Can't apply First operator when we aren't looping over some well formed array '{0}'", cc.LoopVariable.ToString())); } var indexExpr = cc.LoopIndexVariable; // // We need to hold onto either the first or the last item here, so we create a statement that holds nnto the // first or the last time. It also has to mark the thing as valid! It will break when it is done. // While the bool can be used later on to get at the exception we might be throwing, the actual // result may be used much further on down. To protect against that, we set the array index to be -1, // and then hope there is a crash later on! :-) // // It is possible that this is part of a dual selection. For example, if you are interested in the jet that has the closest track, and the // loop is constructed over the jets first, and then the tracks. This First will likely be for a track index, but we will be looking up the // track later. So we need to record both the jet and track index. To get the other indicies, we just look for all loop variables between here and // the result scope. // var valueWasSeen = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); var indexSeen = DeclarableParameter.CreateDeclarableParameterExpression(indexExpr.Type); if (indexSeen.Type.IsNumberType()) { indexSeen.SetInitialValue("-1"); } gc.AddAtResultScope(valueWasSeen); gc.AddAtResultScope(indexSeen); var rv = new Statements.StatementRecordValue(indexSeen, indexExpr, valueWasSeen, isFirst); gc.Add(rv); foreach (var v in gc.GetUsedQuerySourceVariables(rv, indexExpr)) { var saver = DeclarableParameter.CreateDeclarableParameterExpression(v.Type); gc.AddAtResultScope(saver); rv.AddNewSaver(saver, v); cc.Add(v.RawValue, saver); } gc.Pop(true); if (bombIfNothing) { var test = ExpressionToCPP.GetExpression(Expression.Not(valueWasSeen), gc, cc, container); gc.Add(new Statements.StatementThrowIfTrue(test, string.Format("First/Last predicate executed on a null sequence: {0}", queryModel.ToString()))); } // // Finally, we need the new expression. For this we basically just ask for the translated expression. We // also add a substitution for later on for more complex expressions. // var firstlastValue = cc.LoopVariable; cc.Add(indexExpr.RawValue, indexSeen); Debug.WriteLine("First/Last: {0} for QM {1}", indexSeen.ToString(), queryModel.ToString()); // Reset the expression we are looking at in the loop. var newIndexExpr = firstlastValue.ReplaceSubExpression(indexExpr.AsExpression(), indexSeen); cc.SetLoopVariable(newIndexExpr, indexSeen); if (cacheResult) { // // Set the default value // var actualValue = DeclarableParameter.CreateDeclarableParameterExpression(cc.LoopVariable.Type); actualValue.SetInitialValue("0"); // // If everything went well, then we can do the assignment. Otherwise, we leave // it as above (having the default value). // gc.Add(new Statements.StatementFilter(valueWasSeen)); gc.Add(new Statements.StatementAssign(actualValue, ExpressionToCPP.GetExpression(firstlastValue, gc, cc, container))); gc.Pop(); return(actualValue); } else { // No need to cache the result - so no need to add extra code. return(newIndexExpr); } }
/// <summary> /// Generate the code for a tree filling. /// </summary> /// <param name="stream"></param> /// <param name="value"></param> public StatementFillTree(DeclarableParameter stream, Tuple<IValue, string>[] value) { this._fileAndTreePair = stream; this._columnValues = value; }
public void TestCombineMinimalOrdering() { // We will have two if statements to do the combination with. They basically "hide" the modification. var checkVar1 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); var if1s1 = new StatementFilter(new ValSimple(checkVar1.RawValue, typeof(bool))); var if1s2 = new StatementFilter(new ValSimple(checkVar1.RawValue, typeof(bool))); var checkVar2 = DeclarableParameter.CreateDeclarableParameterExpression(typeof(bool)); var if2s1 = new StatementFilter(new ValSimple(checkVar2.RawValue, typeof(bool))); var if2s2 = new StatementFilter(new ValSimple(checkVar2.RawValue, typeof(bool))); var dummyVar = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var blockWithModified = new StatementInlineBlock(); var blockWithoutModified = new StatementInlineBlock(); blockWithModified.Add(checkVar1); blockWithModified.Add(checkVar2); blockWithModified.Add(dummyVar); blockWithoutModified.Add(checkVar1); blockWithoutModified.Add(checkVar2); blockWithoutModified.Add(dummyVar); // Not the opposite order we put them in here! blockWithModified.Add(if1s1); blockWithModified.Add(if2s1); blockWithoutModified.Add(if2s2); blockWithoutModified.Add(if1s2); if1s1.Add(new StatementAssign(dummyVar, new ValSimple("1", typeof(int)))); if2s1.Add(new StatementAssign(dummyVar, new ValSimple("2", typeof(int)))); if1s2.Add(new StatementAssign(dummyVar, new ValSimple("3", typeof(int)))); if2s2.Add(new StatementAssign(dummyVar, new ValSimple("4", typeof(int)))); // Have the modified if statement contain the modification now. var varToBeModified = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var statementModifier = new StatementAssign(varToBeModified, new ValSimple("1", typeof(int))); blockWithModified.Add(varToBeModified); if1s1.Add(statementModifier); // Next, we need to use the variable in the second if statement. Which, since it is like the first, should be pushed back up there. var finalVar = DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)); var assignment = new StatementAssign(finalVar, varToBeModified); blockWithModified.Add(finalVar); if2s1.Add(assignment); // Combine var r = blockWithoutModified.TryCombineStatement(blockWithModified, null); Assert.IsTrue(r, "try combine result"); foreach (var s in blockWithoutModified.CodeItUp()) { System.Diagnostics.Trace.WriteLine(s); } // Make sure the checkVar guy comes after the modified statement. // To get this right (the 3 should be a 2), we need to implement a full blown statement optimizer. Assert.AreEqual(3, blockWithoutModified.Statements.Where(s => s is StatementFilter).Count(), "# of if statements."); }