/// <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 };
        }
Exemple #4
0
        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");
        }
Exemple #5
0
        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
            };
        }
Exemple #7
0
        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");
        }
Exemple #8
0
        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");
        }
Exemple #10
0
        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");
        }
Exemple #12
0
        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 });
        }
Exemple #13
0
        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");
        }
Exemple #14
0
        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");
        }
Exemple #15
0
        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");
        }
Exemple #17
0
        /// <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);
        }
Exemple #18
0
        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.");
        }
Exemple #21
0
        /// <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);
        }
Exemple #22
0
        /// <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);
        }
Exemple #23
0
        public void TestAddOutsideLoopWithNothing()
        {
            var target = new GeneratedCode();

            target.AddOutsideLoop(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)));
        }
Exemple #24
0
        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);
        }
Exemple #27
0
        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));
        }
Exemple #28
0
        public void TestAddOneLevelUpTopLevel()
        {
            GeneratedCode gc = new GeneratedCode();

            gc.AddOneLevelUp(DeclarableParameter.CreateDeclarableParameterExpression(typeof(int)));
        }
Exemple #29
0
        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);
        }
Exemple #32
0
        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);
        }
Exemple #33
0
        /// <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;
 }
Exemple #35
0
        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.");
        }