private void FixSpacingAroundKeywordFor(IForStatement item) { List<string> keywordSearch = new List<string> { "for" }; foreach (var key in keywordSearch) { item.Text = this.whiteSpaceHelper.RemoveWhiteSpaceAroundKeyword(item.Text, key); } }
protected override void PlaceExpression( IForStatement forStatement, ICSharpExpression expression, CSharpElementFactory factory) { var condition = (IRelationalExpression) forStatement.Condition; if (LengthPropertyName == null) { condition.RightOperand.ReplaceBy(expression); } else { var lengthAccess = factory.CreateReferenceExpression("expr.$0", LengthPropertyName); lengthAccess = condition.RightOperand.ReplaceBy(lengthAccess); lengthAccess.QualifierExpression.NotNull().ReplaceBy(expression); } }
protected override void PlaceExpression( IForStatement forStatement, ICSharpExpression expression, CSharpElementFactory factory) { var variable = (ILocalVariableDeclaration)forStatement.Initializer.Declaration.Declarators[0]; var initializer = (IExpressionInitializer)variable.Initial; if (LengthPropertyName == null) { var value = initializer.Value.ReplaceBy(expression); value.ReplaceBy(factory.CreateExpression("$0 - 1", value)); } else { var lengthAccess = factory.CreateReferenceExpression("expr.$0", LengthPropertyName); lengthAccess = initializer.Value.ReplaceBy(lengthAccess); lengthAccess.QualifierExpression.NotNull().ReplaceBy(expression); lengthAccess.ReplaceBy(factory.CreateExpression("$0 - 1", lengthAccess)); } }
private void CheckIssuesForReferencedLocalOrField(CheckCodeIssuesEventArgs ea, IForStatement loop, IElement lambda, IElement element) { if (element.ElementType == LanguageElementType.ElementReferenceExpression) { IElement declaration = element.GetDeclaration(); if (declaration.ElementType == LanguageElementType.Variable || declaration.ElementType == LanguageElementType.InitializedVariable) { if (loop.Initializers.Contains(declaration) || !declaration.IsParentedBy(loop)) { ea.AddWarning(element.ToLanguageElement().Range, "Possible unintended closure scope misuse"); } } return; } foreach (IElement child in element.Children) { CheckIssuesForReferencedLocalOrField(ea, loop, lambda, child); } }
protected override IStatement ConvertFor(IForStatement ifs) { var loopSize = Recognizer.LoopSizeExpression(ifs); if (!((loopSize is IVariableReferenceExpression) || (loopSize is IArrayIndexerExpression) || (loopSize is IArgumentReferenceExpression) || (loopSize is ILiteralExpression) || (loopSize is IPropertyReferenceExpression))) { Error("Invalid expression type for the size of a loop (" + loopSize.GetType().Name + "): " + loopSize); return ifs; } if (loopSize is ILiteralExpression ile) { // remove loops that execute for 0 iterations int loopSizeAsInt = (int)ile.Value; if (loopSizeAsInt == 0) return null; } Containers c = Containers.GetContainersNeededForExpression(context, loopSize); c.Add(ifs); IVariableDeclaration loopVar = Recognizer.LoopVariable(ifs); context.InputAttributes.Remove<Containers>(loopVar); context.InputAttributes.Set(loopVar, c); return base.ConvertFor(ifs); }
internal static void WriteDebugString(IExpression expr, IEnumerable <IStatement> containers) { string containerString = StringUtil.ToString(containers.Select(c => { if (c is IForStatement) { IForStatement ifs = (IForStatement)c; if (c is IBrokenForStatement) { return(ifs.Initializer.ToString() + " // broken"); } else { return(ifs.Initializer.ToString()); } } else { return(((IConditionStatement)c).Condition.ToString()); } })); Trace.WriteLine(StringUtil.JoinColumns(expr, " ", containerString)); }
protected override IStatement ConvertFor(IForStatement ifs) { bool isIterationLoop = false; var loopVar = Recognizer.LoopVariable(ifs); if (loopVar.Name == "iteration") { iterationVar = loopVar; tableOfIndexVars.Clear(); isIterationLoop = true; } IStatement ist = base.ConvertFor(ifs); if (isIterationLoop) { IForStatement fs = (IForStatement)ist; foreach (var table in tableOfIndexVars.Values) { WriteTable(table, fs.Body.Statements); } iterationVar = null; } return(ist); }
// For the first assignment to a local variable in a block before a control statement is hit, // if the local variable is not mentioned previously, we turn this assignment into a local declaration. private void AddDeclarationsWithInitialValues(IEnumerable <ILocalDefinition> localVariables, BasicBlock block) { List <ILocalDefinition> topLevelLocals = new List <ILocalDefinition>(localVariables); List <ILocalDefinition> localsMet = new List <ILocalDefinition>(); for (int i = 0; i < block.Statements.Count; i++) { if (topLevelLocals.Count == 0) { break; } IExpressionStatement expressionStatement = block.Statements[i] as IExpressionStatement; if (expressionStatement != null) { IAssignment assignment = expressionStatement.Expression as IAssignment; if (assignment != null) { ILocalDefinition localDef = assignment.Target.Definition as ILocalDefinition; if (localDef != null && topLevelLocals.Contains(localDef) && !localsMet.Contains(localDef) && !this.declaredLocals.ContainsKey(localDef)) { LocalDeclarationStatement localDecl = new LocalDeclarationStatement() { LocalVariable = localDef, InitialValue = assignment.Source, Locations = new List <ILocation>(expressionStatement.Locations), }; this.declaredLocals.Add(localDef, true); block.Statements[i] = localDecl; topLevelLocals.Remove(localDef); localsMet.Add(localDef); } } } LocalFinder finder = new LocalFinder(); finder.Traverse(block.Statements[i]); foreach (ILocalDefinition local in finder.FoundLocals) { if (!localsMet.Contains(local)) { localsMet.Add(local); } } //Once we see a statement that can transfer control somewhere else, we //no longer know that any subsequent assignment dominates all references //and hence cannot postpone adding the declaration until we can unify it with the assignment. IGotoStatement gotoStatement = block.Statements[i] as IGotoStatement; if (gotoStatement != null) { break; } IConditionalStatement conditionalStatement = block.Statements[i] as IConditionalStatement; if (conditionalStatement != null) { break; } ISwitchStatement switchStatement = block.Statements[i] as ISwitchStatement; if (switchStatement != null) { break; } IForEachStatement foreachStatement = block.Statements[i] as IForEachStatement; if (foreachStatement != null) { break; } IForStatement forStatement = block.Statements[i] as IForStatement; if (forStatement != null) { break; } ITryCatchFinallyStatement tryStatement = block.Statements[i] as ITryCatchFinallyStatement; if (tryStatement != null) { break; } } }
/// <summary> /// Traverses the for statement. /// </summary> public void Traverse(IForStatement forStatement) { Contract.Requires(forStatement != null); if (this.preorderVisitor != null) this.preorderVisitor.Visit(forStatement); if (this.StopTraversal) return; this.TraverseChildren(forStatement); if (this.StopTraversal) return; if (this.postorderVisitor != null) this.postorderVisitor.Visit(forStatement); }
void CompileForStatement(IForStatement statement) { statement.Accept(this); }
public override void VisitForStatement(IForStatement forStatement, IHighlightingConsumer consumer) { VisitLoop(forStatement, consumer); }
public virtual void onASTElement(IForStatement forStatement) { }
protected override IStatement ConvertFor(IForStatement ifs) { if (context.InputAttributes.Has <ConvergenceLoop>(ifs)) { SerialSchedulingInfo info = context.InputAttributes.Get <SerialSchedulingInfo>(ifs); if (info != null) { sequentialLoops.Clear(); foreach (SerialLoopInfo loopInfo in info.loopInfos) { sequentialLoops.Add(loopInfo.loopVar); } } } ifs = (IForStatement)base.ConvertFor(ifs); // collect a list of all nested loops List <IForStatement> loops = new List <IForStatement>(); List <IForStatement> otherLoops = new List <IForStatement>(); IForStatement fs = ifs; while (true) { IExpression loopStart = Recognizer.LoopStartExpression(fs); IExpression loopSize = Recognizer.LoopSizeExpression(fs); containsLoopVar = false; ConvertExpression(loopStart); ConvertExpression(loopSize); if (!containsLoopVar) { loops.Add(fs); } else { otherLoops.Add(fs); } if (fs is IBrokenForStatement) { break; } if (fs.Body.Statements.Count != 1) { break; } if (!(fs.Body.Statements[0] is IForStatement)) { break; } fs = (IForStatement)fs.Body.Statements[0]; } if (loops.Count + otherLoops.Count == 1) { return(ifs); } IList <IStatement> innermostBody = fs.Body.Statements; innermostBody = Containers.WrapWithContainers(innermostBody, otherLoops.ConvertAll(s => (IStatement)s)); loops.Sort(CompareLoops); IStatement wrapped = Containers.WrapWithContainers(innermostBody, loops.ConvertAll(s => (IStatement)s))[0]; context.InputAttributes.CopyObjectAttributesTo(ifs, context.OutputAttributes, wrapped); return(wrapped); }
protected IExpression ConvertWithReplication(IExpression expr) { IVariableDeclaration baseVar = Recognizer.GetVariableDeclaration(expr); // Check if this is an index local variable if (baseVar == null) return expr; // Check if the variable is stochastic if (!CodeRecognizer.IsStochastic(context, baseVar)) return expr; // Get the loop context for this variable LoopContext lc = context.InputAttributes.Get<LoopContext>(baseVar); if (lc == null) { Error("Loop context not found for '" + baseVar.Name + "'."); return expr; } // Get the reference loop context for this expression RefLoopContext rlc = lc.GetReferenceLoopContext(context); // If the reference is in the same loop context as the declaration, do nothing. if (rlc.loops.Count == 0) return expr; // the set of loop variables that are constant wrt the expr Set<IVariableDeclaration> constantLoopVars = new Set<IVariableDeclaration>(); constantLoopVars.AddRange(lc.loopVariables); // collect set of all loop variable indices in the expression Set<int> embeddedLoopIndices = new Set<int>(); List<IList<IExpression>> brackets = Recognizer.GetIndices(expr); foreach (IList<IExpression> bracket in brackets) { foreach (IExpression index in bracket) { IExpression indExpr = index; if (indExpr is IBinaryExpression ibe) { indExpr = ibe.Left; } IVariableDeclaration indVar = Recognizer.GetVariableDeclaration(indExpr); if (indVar != null) { if (!constantLoopVars.Contains(indVar)) { int loopIndex = rlc.loopVariables.IndexOf(indVar); if (loopIndex != -1) { // indVar is a loop variable constantLoopVars.Add(rlc.loopVariables[loopIndex]); } else { // indVar is not a loop variable LoopContext lc2 = context.InputAttributes.Get<LoopContext>(indVar); foreach (var ivd in lc2.loopVariables) { if (!constantLoopVars.Contains(ivd)) { int loopIndex2 = rlc.loopVariables.IndexOf(ivd); if (loopIndex2 != -1) embeddedLoopIndices.Add(loopIndex2); else Error($"Index {ivd} is not in {rlc} for expression {expr}"); } } } } } else { foreach(var ivd in Recognizer.GetVariables(indExpr)) { if (!constantLoopVars.Contains(ivd)) { // copied from above LoopContext lc2 = context.InputAttributes.Get<LoopContext>(ivd); foreach (var ivd2 in lc2.loopVariables) { if (!constantLoopVars.Contains(ivd2)) { int loopIndex2 = rlc.loopVariables.IndexOf(ivd2); if (loopIndex2 != -1) embeddedLoopIndices.Add(loopIndex2); else Error($"Index {ivd2} is not in {rlc} for expression {expr}"); } } } } } } } // Find loop variables that must be constant due to condition statements. List<IStatement> ancestors = context.FindAncestors<IStatement>(); foreach (IStatement ancestor in ancestors) { if (!(ancestor is IConditionStatement ics)) continue; ConditionBinding binding = new ConditionBinding(ics.Condition); IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(binding.lhs); IVariableDeclaration ivd2 = Recognizer.GetVariableDeclaration(binding.rhs); int index = rlc.loopVariables.IndexOf(ivd); if (index >= 0 && IsConstantWrtLoops(ivd2, constantLoopVars)) { constantLoopVars.Add(ivd); continue; } int index2 = rlc.loopVariables.IndexOf(ivd2); if (index2 >= 0 && IsConstantWrtLoops(ivd, constantLoopVars)) { constantLoopVars.Add(ivd2); continue; } } // Determine if this expression is being defined (is on the LHS of an assignment) bool isDef = Recognizer.IsBeingMutated(context, expr); Containers containers = context.InputAttributes.Get<Containers>(baseVar); IExpression originalExpr = expr; for (int currentLoop = 0; currentLoop < rlc.loopVariables.Count; currentLoop++) { IVariableDeclaration loopVar = rlc.loopVariables[currentLoop]; if (constantLoopVars.Contains(loopVar)) continue; IForStatement loop = rlc.loops[currentLoop]; // must replicate across this loop. if (isDef) { Error("Cannot re-define a variable in a loop. Variables on the left hand side of an assignment must be indexed by all containing loops."); continue; } if (embeddedLoopIndices.Contains(currentLoop)) { string warningText = "This model will consume excess memory due to the indexing expression {0} inside of a loop over {1}. Try simplifying this expression in your model, perhaps by creating auxiliary index arrays."; Warning(string.Format(warningText, originalExpr, loopVar.Name)); } // split expr into a target and extra indices, where target will be replicated and extra indices will be added later var extraIndices = new List<IEnumerable<IExpression>>(); AddUnreplicatedIndices(rlc.loops[currentLoop], expr, extraIndices, out IExpression exprToReplicate); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); IExpression loopSize = Recognizer.LoopSizeExpression(loop); IList<IStatement> stmts = Builder.StmtCollection(); List<IList<IExpression>> inds = Recognizer.GetIndices(exprToReplicate); IVariableDeclaration newIndexVar = loopVar; // if loopVar is already an indexVar of varInfo, create a new variable if (varInfo.HasIndexVar(loopVar)) { newIndexVar = VariableInformation.GenerateLoopVar(context, "_a"); context.InputAttributes.CopyObjectAttributesTo(loopVar, context.OutputAttributes, newIndexVar); } IVariableDeclaration repVar = varInfo.DeriveArrayVariable(stmts, context, VariableInformation.GenerateName(context, varInfo.Name + "_rep"), loopSize, newIndexVar, inds, useArrays: true); if (!context.InputAttributes.Has<DerivedVariable>(repVar)) context.OutputAttributes.Set(repVar, new DerivedVariable()); if (context.InputAttributes.Has<ChannelInfo>(baseVar)) { VariableInformation repVarInfo = VariableInformation.GetVariableInformation(context, repVar); ChannelInfo ci = ChannelInfo.UseChannel(repVarInfo); ci.decl = repVar; context.OutputAttributes.Set(repVar, ci); } // Create replicate factor Type returnType = Builder.ToType(repVar.VariableType); IMethodInvokeExpression repMethod = Builder.StaticGenericMethod( new Func<PlaceHolder, int, PlaceHolder[]>(Clone.Replicate), new Type[] {returnType.GetElementType()}, exprToReplicate, loopSize); IExpression assignExpression = Builder.AssignExpr(Builder.VarRefExpr(repVar), repMethod); // Copy attributes across from variable to replication expression context.InputAttributes.CopyObjectAttributesTo<Algorithm>(baseVar, context.OutputAttributes, repMethod); context.InputAttributes.CopyObjectAttributesTo<DivideMessages>(baseVar, context.OutputAttributes, repMethod); context.InputAttributes.CopyObjectAttributesTo<GivePriorityTo>(baseVar, context.OutputAttributes, repMethod); stmts.Add(Builder.ExprStatement(assignExpression)); // add any containers missing from context. containers = new Containers(context); // RemoveUnusedLoops will also remove conditionals involving those loop variables. // TODO: investigate whether removing these conditionals could cause a problem, e.g. when the condition is a conjunction of many terms. containers = Containers.RemoveUnusedLoops(containers, context, repMethod); if (context.InputAttributes.Has<DoNotSendEvidence>(baseVar)) containers = Containers.RemoveStochasticConditionals(containers, context); //Containers shouldBeEmpty = containers.GetContainersNotInContext(context, context.InputStack.Count); //if (shouldBeEmpty.inputs.Count > 0) { Error("Internal: Variable is out of scope"); return expr; } if (containers.Contains(loop)) { Error("Internal: invalid containers for replicating " + baseVar); break; } int ancIndex = containers.GetMatchingAncestorIndex(context); Containers missing = containers.GetContainersNotInContext(context, ancIndex); stmts = Containers.WrapWithContainers(stmts, missing.inputs); context.OutputAttributes.Set(repVar, containers); List<IForStatement> loops = context.FindAncestors<IForStatement>(ancIndex); foreach (IStatement container in missing.inputs) { if (container is IForStatement ifs) loops.Add(ifs); } context.OutputAttributes.Set(repVar, new LoopContext(loops)); // must convert the output since it may contain 'if' conditions context.AddStatementsBeforeAncestorIndex(ancIndex, stmts, true); baseVar = repVar; expr = Builder.ArrayIndex(Builder.VarRefExpr(repVar), Builder.VarRefExpr(loopVar)); expr = Builder.JaggedArrayIndex(expr, extraIndices); } return expr; }
/// <summary> /// This method does all the work of converting literal indexing expressions. /// </summary> /// <param name="iaie"></param> /// <returns></returns> protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { IndexAnalysisTransform.IndexInfo info; if (!analysis.indexInfoOf.TryGetValue(iaie, out info)) { return(base.ConvertArrayIndexer(iaie)); } // Determine if this is a definition i.e. the variable is on the left hand side of an assignment // This must be done before base.ConvertArrayIndexer changes the expression! bool isDef = Recognizer.IsBeingMutated(context, iaie); if (info.clone != null) { if (isDef) { // check that extra literal indices in the target are zero. // for example, if iae is x[i][0] = (...) then it is safe to add x_uses[i] = Rep(x[i]) // if iae is x[i][1] = (...) then it is safe to add x_uses[i][1] = Rep(x[i][1]) // but not x_uses[i] = Rep(x[i]) since this will be a duplicate. bool extraLiteralsAreZero = true; int parentIndex = context.InputStack.Count - 2; object parent = context.GetAncestor(parentIndex); while (parent is IArrayIndexerExpression) { IArrayIndexerExpression parent_iaie = (IArrayIndexerExpression)parent; foreach (IExpression index in parent_iaie.Indices) { if (index is ILiteralExpression) { int value = (int)((ILiteralExpression)index).Value; if (value != 0) { extraLiteralsAreZero = false; break; } } } parentIndex--; parent = context.GetAncestor(parentIndex); } if (false && extraLiteralsAreZero) { // change: // array[0] = f() // into: // array_item0 = f() // array[0] = Copy(array_item0) IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { iaie.GetExpressionType() }, info.clone); IStatement copySt = Builder.AssignStmt(iaie, copy); context.AddStatementAfterCurrent(copySt); } } return(info.clone); } if (isDef) { // do not clone the lhs of an array create assignment. IAssignExpression assignExpr = context.FindAncestor <IAssignExpression>(); if (assignExpr.Expression is IArrayCreateExpression) { return(iaie); } } IVariableDeclaration originalBaseVar = Recognizer.GetVariableDeclaration(iaie); // If the variable is not stochastic, return if (!CodeRecognizer.IsStochastic(context, originalBaseVar)) { return(iaie); } IExpression newExpr = null; IVariableDeclaration baseVar = originalBaseVar; IVariableDeclaration newvd = null; IExpression rhsExpr = null; Containers containers = info.containers; Type tp = iaie.GetExpressionType(); if (tp == null) { Error("Could not determine type of expression: " + iaie); return(iaie); } var stmts = Builder.StmtCollection(); var stmtsAfter = Builder.StmtCollection(); // does the expression have the form array[indices[k]][indices2[k]][indices3[k]]? if (newvd == null && UseGetItems && iaie.Target is IArrayIndexerExpression && iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index3 = (IArrayIndexerExpression)iaie.Indices[0]; IArrayIndexerExpression iaie2 = (IArrayIndexerExpression)iaie.Target; if (index3.Indices.Count == 1 && index3.Indices[0] is IVariableReferenceExpression && iaie2.Target is IArrayIndexerExpression && iaie2.Indices.Count == 1 && iaie2.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index2 = (IArrayIndexerExpression)iaie2.Indices[0]; IArrayIndexerExpression iaie3 = (IArrayIndexerExpression)iaie2.Target; if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression && iaie3.Indices.Count == 1 && iaie3.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index = (IArrayIndexerExpression)iaie3.Indices[0]; IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); if (index.Indices.Count == 1 && index2.Indices[0].Equals(innerIndex) && index3.Indices[0].Equals(innerIndex) && innerLoop != null && AreLoopsDisjoint(innerLoop, iaie3.Target, index.Target)) { // expression has the form array[indices[k]][indices2[k]][indices3[k]] if (isDef) { Error("fancy indexing not allowed on left hand side"); return(iaie); } WarnIfLocal(index.Target, iaie3.Target, iaie); WarnIfLocal(index2.Target, iaie3.Target, iaie); WarnIfLocal(index3.Target, iaie3.Target, iaie); containers = RemoveReferencesTo(containers, innerIndex); IExpression loopSize = Recognizer.LoopSizeExpression(innerLoop); var indices = Recognizer.GetIndices(iaie); // Build name of replacement variable from index values StringBuilder sb = new StringBuilder("_item"); AppendIndexString(sb, iaie3); AppendIndexString(sb, iaie2); AppendIndexString(sb, iaie); string name = ToString(iaie3.Target) + sb.ToString(); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex), indices); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <IReadOnlyList <PlaceHolder> > >, IReadOnlyList <int>, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromDeepJagged), new Type[] { tp }, iaie3.Target, index.Target, index2.Target, index3.Target); context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems)); newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex); rhsExpr = getItems; } } } } // does the expression have the form array[indices[k]][indices2[k]]? if (newvd == null && UseGetItems && iaie.Target is IArrayIndexerExpression && iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index2 = (IArrayIndexerExpression)iaie.Indices[0]; IArrayIndexerExpression target = (IArrayIndexerExpression)iaie.Target; if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression && target.Indices.Count == 1 && target.Indices[0] is IArrayIndexerExpression) { IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index2.Indices[0]; IArrayIndexerExpression index = (IArrayIndexerExpression)target.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); if (index.Indices.Count == 1 && index.Indices[0].Equals(innerIndex) && innerLoop != null && AreLoopsDisjoint(innerLoop, target.Target, index.Target)) { // expression has the form array[indices[k]][indices2[k]] if (isDef) { Error("fancy indexing not allowed on left hand side"); return(iaie); } var innerLoops = new List <IForStatement>(); innerLoops.Add(innerLoop); var indexTarget = index.Target; var index2Target = index2.Target; // check if the index array is jagged, i.e. array[indices[k][j]] while (indexTarget is IArrayIndexerExpression && index2Target is IArrayIndexerExpression) { IArrayIndexerExpression indexTargetExpr = (IArrayIndexerExpression)indexTarget; IArrayIndexerExpression index2TargetExpr = (IArrayIndexerExpression)index2Target; if (indexTargetExpr.Indices.Count == 1 && indexTargetExpr.Indices[0] is IVariableReferenceExpression && index2TargetExpr.Indices.Count == 1 && index2TargetExpr.Indices[0] is IVariableReferenceExpression) { IVariableReferenceExpression innerIndexTarget = (IVariableReferenceExpression)indexTargetExpr.Indices[0]; IVariableReferenceExpression innerIndex2Target = (IVariableReferenceExpression)index2TargetExpr.Indices[0]; IForStatement indexTargetLoop = Recognizer.GetLoopForVariable(context, innerIndexTarget); if (indexTargetLoop != null && AreLoopsDisjoint(indexTargetLoop, target.Target, indexTargetExpr.Target) && innerIndexTarget.Equals(innerIndex2Target)) { innerLoops.Add(indexTargetLoop); indexTarget = indexTargetExpr.Target; index2Target = index2TargetExpr.Target; } else { break; } } else { break; } } WarnIfLocal(indexTarget, target.Target, iaie); WarnIfLocal(index2Target, target.Target, iaie); innerLoops.Reverse(); var loopSizes = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopSizeExpression(ifs) }); var newIndexVars = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopVariable(ifs) }); // Build name of replacement variable from index values StringBuilder sb = new StringBuilder("_item"); AppendIndexString(sb, target); AppendIndexString(sb, iaie); string name = ToString(target.Target) + sb.ToString(); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); var indices = Recognizer.GetIndices(iaie); newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSizes, newIndexVars, indices); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression getItems; if (innerLoops.Count == 1) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromJagged), new Type[] { tp }, target.Target, indexTarget, index2Target); } else if (innerLoops.Count == 2) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <IReadOnlyList <int> >, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItemsFromJagged), new Type[] { tp }, target.Target, indexTarget, index2Target); } else { throw new NotImplementedException($"innerLoops.Count = {innerLoops.Count}"); } context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems)); var newIndices = newIndexVars.ListSelect(ivds => Util.ArrayInit(ivds.Length, i => Builder.VarRefExpr(ivds[i]))); newExpr = Builder.JaggedArrayIndex(Builder.VarRefExpr(newvd), newIndices); rhsExpr = getItems; } else if (HasAnyCommonLoops(index, index2)) { Warning($"This model will consume excess memory due to the indexing expression {iaie} since {index} and {index2} have larger depth than the compiler can handle."); } } } if (newvd == null) { IArrayIndexerExpression originalExpr = iaie; if (UseGetItems) { iaie = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie); } if (!object.ReferenceEquals(iaie.Target, originalExpr.Target) && false) { // TODO: determine if this warning is useful or not string warningText = "This model may consume excess memory due to the jagged indexing expression {0}"; Warning(string.Format(warningText, originalExpr)); } // get the baseVar of the new expression. baseVar = Recognizer.GetVariableDeclaration(iaie); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); var indices = Recognizer.GetIndices(iaie); // Build name of replacement variable from index values StringBuilder sb = new StringBuilder("_item"); AppendIndexString(sb, iaie); string name = ToString(iaie.Target) + sb.ToString(); // does the expression have the form array[indices[k]]? if (UseGetItems && iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index = (IArrayIndexerExpression)iaie.Indices[0]; if (index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression) { // expression has the form array[indices[k]] IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); if (innerLoop != null && AreLoopsDisjoint(innerLoop, iaie.Target, index.Target)) { if (isDef) { Error("fancy indexing not allowed on left hand side"); return(iaie); } var innerLoops = new List <IForStatement>(); innerLoops.Add(innerLoop); var indexTarget = index.Target; // check if the index array is jagged, i.e. array[indices[k][j]] while (indexTarget is IArrayIndexerExpression) { IArrayIndexerExpression index2 = (IArrayIndexerExpression)indexTarget; if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression) { IVariableReferenceExpression innerIndex2 = (IVariableReferenceExpression)index2.Indices[0]; IForStatement innerLoop2 = Recognizer.GetLoopForVariable(context, innerIndex2); if (innerLoop2 != null && AreLoopsDisjoint(innerLoop2, iaie.Target, index2.Target)) { innerLoops.Add(innerLoop2); indexTarget = index2.Target; // This limit must match the number of handled cases below. if (innerLoops.Count == 3) { break; } } else { break; } } else { break; } } WarnIfLocal(indexTarget, iaie.Target, originalExpr); innerLoops.Reverse(); var loopSizes = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopSizeExpression(ifs) }); var newIndexVars = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopVariable(ifs) }); newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSizes, newIndexVars, indices); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression getItems; if (innerLoops.Count == 1) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItems), new Type[] { tp }, iaie.Target, indexTarget); } else if (innerLoops.Count == 2) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItems), new Type[] { tp }, iaie.Target, indexTarget); } else if (innerLoops.Count == 3) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <IReadOnlyList <IReadOnlyList <int> > >, PlaceHolder[][][]>(Collection.GetDeepJaggedItems), new Type[] { tp }, iaie.Target, indexTarget); } else { throw new NotImplementedException($"innerLoops.Count = {innerLoops.Count}"); } context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems)); var newIndices = newIndexVars.ListSelect(ivds => Util.ArrayInit(ivds.Length, i => Builder.VarRefExpr(ivds[i]))); newExpr = Builder.JaggedArrayIndex(Builder.VarRefExpr(newvd), newIndices); rhsExpr = getItems; } } } if (newvd == null) { if (UseGetItems && info.count < 2) { return(iaie); } try { newvd = varInfo.DeriveIndexedVariable(stmts, context, name, indices, copyInitializer: isDef); } catch (Exception ex) { Error(ex.Message, ex); return(iaie); } context.OutputAttributes.Remove <DerivedVariable>(newvd); newExpr = Builder.VarRefExpr(newvd); rhsExpr = iaie; if (isDef) { // change: // array[0] = f() // into: // array_item0 = f() // array[0] = Copy(array_item0) IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy), new Type[] { tp }, newExpr); IStatement copySt = Builder.AssignStmt(iaie, copy); stmtsAfter.Add(copySt); if (!context.InputAttributes.Has <DerivedVariable>(baseVar)) { context.InputAttributes.Set(baseVar, new DerivedVariable()); } } else if (!info.IsAssignedTo) { // change: // x = f(array[0]) // into: // array_item0 = Copy(array[0]) // x = f(array_item0) IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy), new Type[] { tp }, iaie); IStatement copySt = Builder.AssignStmt(Builder.VarRefExpr(newvd), copy); //if (attr != null) context.OutputAttributes.Set(copySt, attr); stmts.Add(copySt); context.InputAttributes.Set(newvd, new DerivedVariable()); } } } // Reduce memory consumption by declaring the clone outside of unnecessary loops. // This way, the item is cloned outside the loop and then replicated, instead of replicating the entire array and cloning the item. containers = Containers.RemoveUnusedLoops(containers, context, rhsExpr); if (context.InputAttributes.Has <DoNotSendEvidence>(originalBaseVar)) { containers = Containers.RemoveStochasticConditionals(containers, context); } if (true) { IStatement st = GetBindingSetContainer(FilterBindingSet(info.bindings, binding => Containers.ContainsExpression(containers.inputs, context, binding.GetExpression()))); if (st != null) { containers.Add(st); } } // To put the declaration in the desired containers, we find an ancestor which includes as many of the containers as possible, // then wrap the declaration with the remaining containers. int ancIndex = containers.GetMatchingAncestorIndex(context); Containers missing = containers.GetContainersNotInContext(context, ancIndex); stmts = Containers.WrapWithContainers(stmts, missing.outputs); context.AddStatementsBeforeAncestorIndex(ancIndex, stmts); stmtsAfter = Containers.WrapWithContainers(stmtsAfter, missing.outputs); context.AddStatementsAfterAncestorIndex(ancIndex, stmtsAfter); context.InputAttributes.Set(newvd, containers); info.clone = newExpr; return(newExpr); }
public override void VisitForStatement <TExpression, TForInitializerStatement, TStatement>(IForStatement <TExpression, TForInitializerStatement, TStatement> forStatement) { Value = new Statement() { ForStatement = new ForStatementFactory(forStatement).Value }; }
public void Visit(IForStatement forStatement) { this.traverser.Traverse(forStatement); }
public override void Visit(IForStatement forStatement) { allElements.Add(new InvokInfo(Traverser, "IForStatement", forStatement)); }
/// <summary> /// Generates IL for the specified for statement. /// </summary> /// <param name="forStatement">For statement.</param> public override void TraverseChildren(IForStatement forStatement) { ILGeneratorLabel savedCurrentBreakTarget = this.currentBreakTarget; ILGeneratorLabel savedCurrentContinueTarget = this.currentContinueTarget; this.currentBreakTarget = new ILGeneratorLabel(); this.currentContinueTarget = new ILGeneratorLabel(); if (this.currentTryCatch != null) { this.mostNestedTryCatchFor.Add(this.currentBreakTarget, this.currentTryCatch); this.mostNestedTryCatchFor.Add(this.currentContinueTarget, this.currentTryCatch); } ILGeneratorLabel conditionCheck = new ILGeneratorLabel(); ILGeneratorLabel loopStart = new ILGeneratorLabel(); this.Traverse(forStatement.InitStatements); this.generator.Emit(OperationCode.Br, conditionCheck); this.generator.MarkLabel(loopStart); this.Traverse(forStatement.Body); this.generator.MarkLabel(this.currentContinueTarget); this.Traverse(forStatement.IncrementStatements); this.generator.MarkLabel(conditionCheck); this.EmitSequencePoint(forStatement.Condition.Locations); this.VisitBranchIfTrue(forStatement.Condition, loopStart); this.generator.MarkLabel(this.currentBreakTarget); this.currentBreakTarget = savedCurrentBreakTarget; this.currentContinueTarget = savedCurrentContinueTarget; this.lastStatementWasUnconditionalTransfer = false; }
/// <summary> /// This method does all the work of converting literal indexing expressions. /// </summary> /// <param name="iaie"></param> /// <returns></returns> protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { IndexAnalysisTransform.IndexInfo info; if (!analysis.indexInfoOf.TryGetValue(iaie, out info)) { return(base.ConvertArrayIndexer(iaie)); } // Determine if this is a definition i.e. the variable is on the left hand side of an assignment // This must be done before base.ConvertArrayIndexer changes the expression! bool isDef = Recognizer.IsBeingMutated(context, iaie); if (info.clone != null) { if (isDef) { // check that extra literal indices in the target are zero. // for example, if iae is x[i][0] = (...) then it is safe to add x_uses[i] = Rep(x[i]) // if iae is x[i][1] = (...) then it is safe to add x_uses[i][1] = Rep(x[i][1]) // but not x_uses[i] = Rep(x[i]) since this will be a duplicate. bool extraLiteralsAreZero = true; int parentIndex = context.InputStack.Count - 2; object parent = context.GetAncestor(parentIndex); while (parent is IArrayIndexerExpression parent_iaie) { foreach (IExpression index in parent_iaie.Indices) { if (index is ILiteralExpression ile) { int value = (int)ile.Value; if (value != 0) { extraLiteralsAreZero = false; break; } } } parentIndex--; parent = context.GetAncestor(parentIndex); } if (false && extraLiteralsAreZero) { // change: // array[0] = f() // into: // array_item0 = f() // array[0] = Copy(array_item0) IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { iaie.GetExpressionType() }, info.clone); IStatement copySt = Builder.AssignStmt(iaie, copy); context.AddStatementAfterCurrent(copySt); } } return(info.clone); } if (isDef) { // do not clone the lhs of an array create assignment. IAssignExpression assignExpr = context.FindAncestor <IAssignExpression>(); if (assignExpr.Expression is IArrayCreateExpression) { return(iaie); } } IVariableDeclaration originalBaseVar = Recognizer.GetVariableDeclaration(iaie); // If the variable is not stochastic, return if (!CodeRecognizer.IsStochastic(context, originalBaseVar)) { return(iaie); } IExpression newExpr = null; IVariableDeclaration baseVar = originalBaseVar; IVariableDeclaration newvd = null; IExpression rhsExpr = null; Containers containers = info.containers; Type tp = iaie.GetExpressionType(); if (tp == null) { Error("Could not determine type of expression: " + iaie); return(iaie); } var stmts = Builder.StmtCollection(); var stmtsAfter = Builder.StmtCollection(); // does the expression have the form array[indices[k]][indices2[k]][indices3[k]]? if (newvd == null && UseGetItems && iaie.Indices.Count == 1) { if (iaie.Target is IArrayIndexerExpression iaie2 && iaie.Indices[0] is IArrayIndexerExpression index3 && index3.Indices.Count == 1 && index3.Indices[0] is IVariableReferenceExpression innerIndex3 && iaie2.Target is IArrayIndexerExpression iaie3 && iaie2.Indices.Count == 1 && iaie2.Indices[0] is IArrayIndexerExpression index2 && index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression innerIndex2 && innerIndex2.Equals(innerIndex3) && iaie3.Indices.Count == 1 && iaie3.Indices[0] is IArrayIndexerExpression index && index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression innerIndex && innerIndex.Equals(innerIndex2)) { IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); if (innerLoop != null && AreLoopsDisjoint(innerLoop, iaie3.Target, index.Target)) { // expression has the form array[indices[k]][indices2[k]][indices3[k]] if (isDef) { Error("fancy indexing not allowed on left hand side"); return(iaie); } WarnIfLocal(index.Target, iaie3.Target, iaie); WarnIfLocal(index2.Target, iaie3.Target, iaie); WarnIfLocal(index3.Target, iaie3.Target, iaie); containers = RemoveReferencesTo(containers, innerIndex); IExpression loopSize = Recognizer.LoopSizeExpression(innerLoop); var indices = Recognizer.GetIndices(iaie); // Build name of replacement variable from index values StringBuilder sb = new StringBuilder("_item"); AppendIndexString(sb, iaie3); AppendIndexString(sb, iaie2); AppendIndexString(sb, iaie); string name = ToString(iaie3.Target) + sb.ToString(); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex), indices); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <IReadOnlyList <PlaceHolder> > >, IReadOnlyList <int>, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromDeepJagged), new Type[] { tp }, iaie3.Target, index.Target, index2.Target, index3.Target); context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems)); newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex); rhsExpr = getItems; } } } // does the expression have the form array[indices[k]][indices2[k]]? if (newvd == null && UseGetItems && iaie.Indices.Count == 1) { if (iaie.Target is IArrayIndexerExpression target && iaie.Indices[0] is IArrayIndexerExpression index2 && index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression innerIndex && target.Indices.Count == 1 && target.Indices[0] is IArrayIndexerExpression index) { IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); if (index.Indices.Count == 1 && index.Indices[0].Equals(innerIndex) && innerLoop != null && AreLoopsDisjoint(innerLoop, target.Target, index.Target)) { // expression has the form array[indices[k]][indices2[k]] if (isDef) { Error("fancy indexing not allowed on left hand side"); return(iaie); } var innerLoops = new List <IForStatement>(); innerLoops.Add(innerLoop); var indexTarget = index.Target; var index2Target = index2.Target; // check if the index array is jagged, i.e. array[indices[k][j]] while (indexTarget is IArrayIndexerExpression indexTargetExpr && index2Target is IArrayIndexerExpression index2TargetExpr) { if (indexTargetExpr.Indices.Count == 1 && indexTargetExpr.Indices[0] is IVariableReferenceExpression innerIndexTarget && index2TargetExpr.Indices.Count == 1 && index2TargetExpr.Indices[0] is IVariableReferenceExpression innerIndex2Target) { IForStatement indexTargetLoop = Recognizer.GetLoopForVariable(context, innerIndexTarget); if (indexTargetLoop != null && AreLoopsDisjoint(indexTargetLoop, target.Target, indexTargetExpr.Target) && innerIndexTarget.Equals(innerIndex2Target)) { innerLoops.Add(indexTargetLoop); indexTarget = indexTargetExpr.Target; index2Target = index2TargetExpr.Target; } else { break; } } else { break; } } WarnIfLocal(indexTarget, target.Target, iaie); WarnIfLocal(index2Target, target.Target, iaie); innerLoops.Reverse(); var loopSizes = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopSizeExpression(ifs) }); var newIndexVars = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopVariable(ifs) }); // Build name of replacement variable from index values StringBuilder sb = new StringBuilder("_item"); AppendIndexString(sb, target); AppendIndexString(sb, iaie); string name = ToString(target.Target) + sb.ToString(); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); var indices = Recognizer.GetIndices(iaie); newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSizes, newIndexVars, indices); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression getItems; if (innerLoops.Count == 1) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromJagged), new Type[] { tp }, target.Target, indexTarget, index2Target); } else if (innerLoops.Count == 2) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <IReadOnlyList <int> >, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItemsFromJagged), new Type[] { tp }, target.Target, indexTarget, index2Target); } else { throw new NotImplementedException($"innerLoops.Count = {innerLoops.Count}"); } context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems)); var newIndices = newIndexVars.ListSelect(ivds => Util.ArrayInit(ivds.Length, i => Builder.VarRefExpr(ivds[i]))); newExpr = Builder.JaggedArrayIndex(Builder.VarRefExpr(newvd), newIndices); rhsExpr = getItems; } else if (HasAnyCommonLoops(index, index2)) { Warning($"This model will consume excess memory due to the indexing expression {iaie} since {index} and {index2} have larger depth than the compiler can handle."); } }
public override void TraverseChildren(IForStatement forStatement) { Result++; base.TraverseChildren(forStatement); }
public void Visit(IForStatement forStatement) { Contract.Requires(forStatement != null); throw new NotImplementedException(); }
void WriteTable(TableInfo table, ICollection <IStatement> output) { string writerName = VariableInformation.GenerateName(context, "_writer"); ITypeDeclaration td = context.FindOutputForAncestor <ITypeDeclaration, ITypeDeclaration>(); IFieldDeclaration fd = Builder.FieldDecl(writerName, typeof(StreamWriter), td); fd.Documentation = "Writes " + table.Name; context.AddMember(fd); td.Fields.Add(fd); var writer = Builder.FieldRefExpr(fd); IForStatement innerForStatement; IForStatement fs = Builder.NestedForStmt(table.indexVars, table.sizes, out innerForStatement); ICollection <IStatement> output2; if (fs != null) { output.Add(fs); output2 = innerForStatement.Body.Statements; } else { output2 = output; } StringBuilder header = new StringBuilder(); header.Append("iteration"); output2.Add(GetWriteStatement(writer, Builder.VarRefExpr(iterationVar))); string delimiter = UseToString ? "\t" : ","; var writeDelimiter = GetWriteStatement(writer, Builder.LiteralExpr(delimiter)); foreach (var indexVar in table.indexVars) { header.Append(delimiter); header.Append(indexVar.Name); output2.Add(writeDelimiter); output2.Add(GetWriteStatement(writer, Builder.VarRefExpr(indexVar))); } foreach (var messageBaseExpr in table.messageExprs) { Stack <IExpression> conditions = new Stack <IExpression>(); object messageVar = Recognizer.GetDeclaration(messageBaseExpr); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, messageVar); IExpression messageExpr = messageBaseExpr; foreach (var bracket in varInfo.indexVars) { if (!messageExpr.GetExpressionType().IsValueType) { conditions.Push(Builder.BinaryExpr(BinaryOperator.IdentityEquality, messageExpr, Builder.LiteralExpr(null))); } var indices = Util.ArrayInit(bracket.Length, i => Builder.VarRefExpr(bracket[i])); messageExpr = Builder.ArrayIndex(messageExpr, indices); } if (!messageExpr.GetExpressionType().IsValueType) { conditions.Push(Builder.BinaryExpr(BinaryOperator.IdentityEquality, messageExpr, Builder.LiteralExpr(null))); } if (messageExpr.GetExpressionType().IsPrimitive) { header.Append(delimiter); header.Append(varInfo.Name); output2.Add(writeDelimiter); output2.Add(GetWriteStatement(writer, AddConditions(messageExpr, conditions))); } else { Dictionary <string, IExpression> dict = GetProperties(messageExpr); foreach (var entry in dict) { header.Append(delimiter); header.Append(varInfo.Name + entry.Key); output2.Add(writeDelimiter); output2.Add(GetWriteStatement(writer, AddConditions(entry.Value, conditions))); } } } output2.Add(GetWriteLineStatement(writer)); output.Add(GetFlushStatement(writer)); if (traceWriterMethod == null) { MakeTraceWriterMethod(); } fd.Initializer = Builder.StaticMethod(traceWriterMethod, Builder.LiteralExpr(table.Name), Builder.LiteralExpr(header.ToString())); if (disposeMethod == null) { MakeDisposeMethod(); } disposeMethod.Body.Statements.Add(GetDisposeStatement(writer)); }
protected override IStatement ConvertCondition(IConditionStatement ics) { context.SetPrimaryOutput(ics); ConvertExpression(ics.Condition); IForStatement loop = null; ConditionBinding binding = GateTransform.GetConditionBinding(ics.Condition, context, out loop); IExpression caseValue = binding.rhs; if (!GateTransform.IsLiteralOrLoopVar(context, caseValue, out loop)) { Error("If statement condition must compare to a literal or loop counter, was: " + ics.Condition); return(ics); } bool isStochastic = CodeRecognizer.IsStochastic(context, binding.lhs); IExpression gateBlockKey; if (isStochastic) { gateBlockKey = binding.lhs; } else { // definitions must not be unified across deterministic gate conditions gateBlockKey = binding.GetExpression(); } GateBlock gateBlock = null; Set <ConditionBinding> bindings = ConditionBinding.Copy(conditionContext); Dictionary <IExpression, GateBlock> blockMap; if (!gateBlocks.TryGetValue(bindings, out blockMap)) { // first time seeing these bindings blockMap = new Dictionary <IExpression, GateBlock>(); gateBlocks[bindings] = blockMap; } if (!blockMap.TryGetValue(gateBlockKey, out gateBlock)) { // first time seeing this lhs gateBlock = new GateBlock(); blockMap[gateBlockKey] = gateBlock; } if (gateBlock.hasLoopCaseValue && loop == null) { Error("Cannot compare " + binding.lhs + " to a literal, since it was previously compared to a loop counter. Put this test inside the loop."); } if (!gateBlock.hasLoopCaseValue && gateBlock.caseValues.Count > 0 && loop != null) { Error("Cannot compare " + binding.lhs + " to a loop counter, since it was previously compared to a literal. Put the literal case inside the loop."); } gateBlock.caseValues.Add(caseValue); if (loop != null) { gateBlock.hasLoopCaseValue = true; } gateBlockContext.Add(gateBlock); context.OutputAttributes.Set(ics, gateBlock); int startIndex = conditionContext.Count; conditionContext.Add(binding); ConvertBlock(ics.Then); if (ics.Else != null) { conditionContext.RemoveRange(startIndex, conditionContext.Count - startIndex); binding = binding.FlipCondition(); conditionContext.Add(binding); ConvertBlock(ics.Else); } conditionContext.RemoveRange(startIndex, conditionContext.Count - startIndex); gateBlockContext.RemoveAt(gateBlockContext.Count - 1); // remove any uses that match a def //RemoveUsesOfDefs(gateBlock); if (gateBlockContext.Count > 0) { GateBlock currentBlock = gateBlockContext[gateBlockContext.Count - 1]; // all variables defined/used in the inner block must be processed by the outer block foreach (ExpressionWithBindings eb in gateBlock.variablesDefined.Values) { if (eb.Bindings.Count > 0) { foreach (List <ConditionBinding> binding2 in eb.Bindings) { ProcessUse(eb.Expression, true, Union(conditionContext, binding2)); } } else { ProcessUse(eb.Expression, true, conditionContext); } } foreach (List <ExpressionWithBindings> ebs in gateBlock.variablesUsed.Values) { foreach (ExpressionWithBindings eb in ebs) { if (eb.Bindings.Count > 0) { foreach (ICollection <ConditionBinding> binding2 in eb.Bindings) { ProcessUse(eb.Expression, false, Union(conditionContext, binding2)); } } else { ProcessUse(eb.Expression, false, conditionContext); } } } } return(ics); }
/// <summary> /// Rewrites the given for statement. /// </summary> /// <param name="forStatement"></param> public virtual IStatement Rewrite(IForStatement forStatement) { return forStatement; }
protected override IStatement DoConvertStatement(IStatement ist) { if (ist is IExpressionStatement) { bool isAccumulator = false; IExpressionStatement ies = (IExpressionStatement)ist; if (ies.Expression is IAssignExpression) { IAssignExpression iae = (IAssignExpression)ies.Expression; AccumulationInfo ac = context.InputAttributes.Get <AccumulationInfo>(ies); if (ac != null) { // This statement defines an accumulator. // Delete the statement and replace with any remaining accumulations. if (!ac.isInitialized) { context.AddStatementBeforeCurrent(ac.initializer); } ac.isInitialized = false; context.AddStatementsBeforeCurrent(ac.statements); isAccumulator = true; } object ivd = Recognizer.GetVariableDeclaration(iae.Target); if (ivd == null) { ivd = Recognizer.GetFieldReference(iae.Target); } if (ivd != null) { MessageArrayInformation mai = context.InputAttributes.Get <MessageArrayInformation>(ivd); bool oneUse = (mai != null) && (mai.useCount == 1); List <AccumulationInfo> ais = context.InputAttributes.GetAll <AccumulationInfo>(ivd); foreach (AccumulationInfo ai in ais) { if (!context.InputAttributes.Has <OperatorStatement>(ist)) { if (oneUse) { return(null); // remove the statement } else { continue; } } // assuming that we only accumulate one statement, we should always initialize if (true || !ai.isInitialized) { // add the initializer in the same containers as the original accumulation statement int ancIndex = ai.containers.GetMatchingAncestorIndex(context); Containers missing = ai.containers.GetContainersNotInContext(context, ancIndex); context.AddStatementBeforeAncestorIndex(ancIndex, Containers.WrapWithContainers(ai.initializer, missing.outputs)); ai.isInitialized = true; } // This statement defines a variable that contributes to an accumulator. IList <IStatement> stmts = Builder.StmtCollection(); IExpression target = iae.Target; Type exprType = target.GetExpressionType(); IExpression accumulator = ai.accumulator; Type accumulatorType = ai.type; int rank; Type eltType = Util.GetElementType(exprType, out rank); if (rank == 1 && eltType == accumulatorType) { // This statement defines an array of items to be accumulated. VariableInformation varInfo = context.InputAttributes.Get <VariableInformation>(mai.ci.decl); int indexingDepth = Recognizer.GetIndexingDepth(iae.Target); if (mai.loopVarInfo != null) { indexingDepth -= mai.loopVarInfo.indexVarRefs.Length; } IExpression size = varInfo.sizes[indexingDepth][0]; IVariableDeclaration indexVar = varInfo.indexVars[indexingDepth][0]; IForStatement ifs = Builder.ForStmt(indexVar, size); target = Builder.ArrayIndex(target, Builder.VarRefExpr(indexVar)); ifs.Body.Statements.Add(ai.GetAccumulateStatement(context, accumulator, target)); stmts.Add(ifs); } else { Stack <IList <IExpression> > indexStack = new Stack <IList <IExpression> >(); while (exprType != accumulatorType && target is IArrayIndexerExpression) { // The accumulator is an array type, and this statement defines an element of the accumulator type. // Peel off the indices of the target. IArrayIndexerExpression iaie = (IArrayIndexerExpression)target; indexStack.Push(iaie.Indices); target = iaie.Target; accumulatorType = Util.GetElementType(accumulatorType); } while (indexStack.Count > 0) { // Attach the indices of the target to the accumulator, in reverse order that they were peeled. accumulator = Builder.ArrayIndex(accumulator, indexStack.Pop()); } if (exprType == accumulatorType) { if (oneUse && !isAccumulator) { // convert // msg = expr; // into // T temp = expr; // acc = SetToProduct(acc, temp); // and move into ai.statement. tempVarCount++; string name = "_temp" + tempVarCount; IVariableDeclaration tempVar = Builder.VarDecl(name, exprType); IStatement newStatement = Builder.AssignStmt(Builder.VarDeclExpr(tempVar), iae.Expression); context.AddStatementBeforeCurrent(newStatement); context.AddStatementBeforeCurrent(ai.GetAccumulateStatement(context, accumulator, Builder.VarRefExpr(tempVar))); return(null); } else { // must keep the original statement. // add // acc = SetToProduct(acc, msg); // to ai.statements. context.AddStatementAfterCurrent(ai.GetAccumulateStatement(context, accumulator, iae.Target)); } } else { Error("Unrecognized variable type: " + StringUtil.TypeToString(exprType)); } } Containers containers = new Containers(context); containers = containers.Remove(ai.containers); IList <IStatement> output2 = Builder.StmtCollection(); Containers.AddStatementWithContainers(output2, stmts, containers.inputs); foreach (IStatement ist2 in output2) { context.AddStatementAfterCurrent(ist2); } } } } if (!isAccumulator) { return(ist); } else { return(null); } } else { return(base.DoConvertStatement(ist)); } }
public override void TraverseChildren(IForStatement forStatement) { throw new TranslationException("For statements are not handled"); }
protected override IStatement ConvertFor(IForStatement ifs) { loopVariables.Add(Recognizer.LoopVariable(ifs)); return(base.ConvertFor(ifs)); }
/// <summary> /// Add localInfo for expr to the current containerInfo. /// </summary> /// <param name="decl"></param> /// <param name="expr"></param> /// <param name="localInfo"></param> /// <param name="closedContainer"></param> protected LocalInfo AddLocalInfo(object decl, IExpression expr, LocalInfo localInfo, IForStatement closedContainer) { if (containerInfos.Count == 0) { return(localInfo); } ContainerInfo containerInfo = containerInfos.Peek(); UsageInfo usageInfo; if (!containerInfo.usageInfoOfVariable.TryGetValue(decl, out usageInfo)) { usageInfo = new UsageInfo(); containerInfo.usageInfoOfVariable[decl] = usageInfo; } LocalInfo info; if (!usageInfo.localInfos.TryGetValue(expr, out info)) { info = localInfo.Clone(); info.containingStatements.IntersectWith(openContainers); IVariableDeclaration loopVar = Recognizer.LoopVariable(closedContainer); int index = info.containers.inputs.FindIndex(container => Containers.ContainersAreEqual(container, closedContainer, allowBrokenLoops: true, ignoreLoopDirection: true)); bool conditionsContainLoopVar = info.containers.inputs.Skip(index + 1).Any(container => Recognizer.GetVariables(GetContainerExpression(container)).Contains(loopVar)); IStatement replacement = null; if (conditionsContainLoopVar) { replacement = Builder.BrokenForStatement(closedContainer); info.containingStatements.Add(replacement); } else { var loopSize = Recognizer.LoopSizeExpression(closedContainer); bool loopMustExecute = false; if (loopSize is ILiteralExpression ile) { int loopSizeAsInt = (int)ile.Value; if (loopSizeAsInt > 0) { loopMustExecute = true; } } if (!loopMustExecute) { var condition = Builder.BinaryExpr(loopSize, BinaryOperator.GreaterThan, Builder.LiteralExpr(0)); replacement = Builder.CondStmt(condition, Builder.BlockStmt()); } } if (info.containers.inputs.Contains(replacement)) { replacement = null; } if (replacement == null) { info.containers = info.containers.Where(container => !Containers.ContainersAreEqual(container, closedContainer, true, true)); } else { // this only replaces containers.inputs info.containers = info.containers.Replace(container => !Containers.ContainersAreEqual(container, closedContainer, true, true) ? container : replacement); } int previousCount = info.containers.Count; info.containers = Containers.RemoveInvalidConditions(info.containers, context); if (info.containers.Count != previousCount && expr is IArrayIndexerExpression) { // when dropping conditionals, we need to show that if the indices were valid inside the conditionals, they remain valid outside the conditionals. // This is automatically true if the indices match the indexVars. expr = GetPrefixIndexedByIndexVars(expr); } usageInfo.localInfos[expr] = info; } else { info.Add(localInfo); } info.appearsInNestedLoop = true; return(info); }
public void Visit(IForStatement forStatement) { this.result = this.copier.Copy(forStatement); }
public override void TraverseChildren(IForStatement forStatement) { MethodEnter(forStatement); base.TraverseChildren(forStatement); MethodExit(); }
//^ ensures this.path.Count == old(this.path.Count); /// <summary> /// Traverses the given for statement. /// </summary> /// <param name="forStatement"></param> public virtual void Visit(IForStatement forStatement) { if (this.stopTraversal) return; //^ int oldCount = this.path.Count; this.path.Push(forStatement); this.Visit(forStatement.InitStatements); this.Visit(forStatement.Condition); this.Visit(forStatement.IncrementStatements); this.Visit(forStatement.Body); //^ assume this.path.Count == oldCount+1; //True because all of the virtual methods of this class promise not decrease this.path.Count. this.path.Pop(); }
/// <summary> /// Converts variable declarations inside loops into array declarations at the top level. /// </summary> /// <param name="ivde"></param> /// <returns></returns> protected override IExpression ConvertVariableDeclExpr(IVariableDeclarationExpression ivde) { IVariableDeclaration ivd = ivde.Variable; bool isLoneDeclaration = (context.FindAncestorIndex <IExpressionStatement>() == context.Depth - 2); List <IForStatement> loops = context.FindAncestors <IForStatement>(); if (loops.Count == 0) { List <IConditionStatement> ifs = context.FindAncestors <IConditionStatement>(); if (ifs.Count == 0) { return(ivde); } // Add declaration outside the if IStatement outermostContainer = ifs[0]; int ancIndex = context.GetAncestorIndex(outermostContainer); var defaultExpr = Builder.DefaultExpr(ivd.VariableType); var assignSt = Builder.AssignStmt(ivde, defaultExpr); context.OutputAttributes.Set(assignSt, new Initializer()); context.AddStatementBeforeAncestorIndex(ancIndex, assignSt); if (isLoneDeclaration) { return(null); } else { return(Builder.VarRefExpr(ivd)); } } // ignore declaration of a loop variable if (Recognizer.LoopVariable(loops[loops.Count - 1]) == ivd) { return(ivde); } // Declaration is inside one or more loops, find their sizes and index variables Type type = Builder.ToType(ivd.VariableType); Type arrayType = type; LoopVarInfo lvi = new LoopVarInfo(loops); for (int i = 0; i < loops.Count; i++) { IForStatement loop = loops[i]; lvi.indexVarRefs[i] = Builder.VarRefExpr(Recognizer.LoopVariable(loop)); arrayType = Util.MakeArrayType(arrayType, 1); } Predicate <int> isPartitionedAtDepth = (depth => context.InputAttributes.Has <Partitioned>(Recognizer.GetVariableDeclaration(lvi.indexVarRefs[depth]))); Type messageType = Distributions.Distribution.IsDistributionType(type) ? MessageTransform.GetDistributionType(arrayType, type, type, 0, loops.Count, isPartitionedAtDepth) : MessageTransform.GetArrayType(arrayType, type, 0, isPartitionedAtDepth); lvi.arrayvd = Builder.VarDecl(ivd.Name, messageType); loopVarInfos[ivd] = lvi; MessageArrayInformation mai = context.InputAttributes.Get <MessageArrayInformation>(ivd); if (mai != null) { mai.loopVarInfo = lvi; } context.InputAttributes.CopyObjectAttributesTo(ivd, context.OutputAttributes, lvi.arrayvd); context.InputAttributes.Remove <VariableInformation>(lvi.arrayvd); VariableInformation vi = VariableInformation.GetVariableInformation(context, ivd); VariableInformation vi2 = VariableInformation.GetVariableInformation(context, lvi.arrayvd); vi2.IsStochastic = vi.IsStochastic; // Initialise the array to the appropriate sizes // TODO: change to work over loop brackets not loops IExpression expr = Builder.VarDeclExpr(lvi.arrayvd); for (int i = 0; i < loops.Count; i++) { IForStatement loop = loops[i]; IExpression loopSize = Recognizer.LoopSizeExpression(loop); IExpressionStatement assignSt = Builder.AssignStmt(expr, MessageTransform.GetArrayCreateExpression(expr, expr.GetExpressionType(), new IExpression[] { loopSize })); context.OutputAttributes.Set(assignSt.Expression, new DescriptionAttribute("Create array for replicates of '" + ivd.Name + "'")); context.OutputAttributes.Set(assignSt, new Initializer()); if (expr is IVariableDeclarationExpression) { expr = Builder.VarRefExpr(lvi.arrayvd); } expr = Builder.ArrayIndex(expr, lvi.indexVarRefs[i]); vi2.indexVars.Add(new IVariableDeclaration[] { Recognizer.GetVariableDeclaration(lvi.indexVarRefs[i]) }); vi2.sizes.Add(new IExpression[] { loopSize }); // Add declaration outside the loop int ancIndex = context.GetAncestorIndex(loop); context.AddStatementBeforeAncestorIndex(ancIndex, assignSt); } vi2.indexVars.AddRange(vi.indexVars); vi2.sizes.AddRange(vi.sizes); // If the variable declaration was a statement by itself, then return null (i.e. delete the statement). if (isLoneDeclaration) { return(null); } // Return a reference to the newly created array else { return(expr); } }
public override void Visit(IForStatement forStatement) { if(Process(forStatement)){visitor.Visit(forStatement);} base.Visit(forStatement); }
/// <summary> /// Performs some computation with the given for statement. /// </summary> /// <param name="forStatement"></param> public virtual void Visit(IForStatement forStatement) { }
/// <summary> /// Traverses the children of the for statement. /// </summary> public virtual void TraverseChildren(IForStatement forStatement) { Contract.Requires(forStatement != null); this.TraverseChildren((IStatement)forStatement); if (this.StopTraversal) return; this.Traverse(forStatement.InitStatements); if (this.StopTraversal) return; this.Traverse(forStatement.Condition); if (this.StopTraversal) return; this.Traverse(forStatement.IncrementStatements); if (this.StopTraversal) return; this.Traverse(forStatement.Body); }
/// <summary> /// Returns a deep copy of the given for statement. /// </summary> /// <param name="forStatement"></param> public ForStatement Copy(IForStatement forStatement) { Contract.Requires(forStatement != null); Contract.Ensures(Contract.Result<ForStatement>() != null); var mutableCopy = this.shallowCopier.Copy(forStatement); mutableCopy.InitStatements = this.Copy(mutableCopy.InitStatements); mutableCopy.Condition = this.Copy(mutableCopy.Condition); mutableCopy.IncrementStatements = this.Copy(mutableCopy.IncrementStatements); mutableCopy.Body = this.Copy(mutableCopy.Body); return mutableCopy; }
/// <summary> /// Performs some computation with the given for statement. /// </summary> /// <param name="forStatement"></param> public virtual void Visit(IForStatement forStatement) { this.Visit((IStatement)forStatement); }
/// <summary> /// Returns a shallow copy of the given for statement. /// </summary> /// <param name="forStatement"></param> public ForStatement Copy(IForStatement forStatement) { Contract.Requires(forStatement != null); Contract.Ensures(Contract.Result<ForStatement>() != null); var mutable = forStatement as ForStatement; if (mutable != null) return mutable.Clone(); return new ForStatement(forStatement); }
public void Visit(IForStatement forStatement) { throw new NotImplementedException(); }
protected override void DoConvertMethodBody(IList <IStatement> outputs, IList <IStatement> inputs) { List <int> whileNumberOfNode = new List <int>(); List <int> fusedCountOfNode = new List <int>(); List <List <IStatement> > containersOfNode = new List <List <IStatement> >(); // the code may have multiple while(true) loops, however these must be disjoint. // therefore we treat 'while' as one container, but give each loop a different 'while number'. int outerWhileCount = 0; int currentOuterWhileNumber = 0; int currentFusedCount = 0; List <Set <IVariableDeclaration> > loopVarsOfWhileNumber = new List <Set <IVariableDeclaration> >(); // build the dependency graph var g = new DependencyGraph2(context, inputs, DependencyGraph2.BackEdgeHandling.Ignore, delegate(IWhileStatement iws) { if (iws is IFusedBlockStatement) { if (iws.Condition is IVariableReferenceExpression) { currentFusedCount++; } } else { outerWhileCount++; currentOuterWhileNumber = outerWhileCount; } }, delegate(IWhileStatement iws) { if (iws is IFusedBlockStatement) { if (iws.Condition is IVariableReferenceExpression) { currentFusedCount--; } } else { currentOuterWhileNumber = 0; } }, delegate(IConditionStatement ics) { }, delegate(IConditionStatement ics) { }, delegate(IStatement ist, int targetIndex) { int whileNumber = currentOuterWhileNumber; whileNumberOfNode.Add(whileNumber); fusedCountOfNode.Add(currentFusedCount); List <IStatement> containers = new List <IStatement>(); LoopMergingTransform.UnwrapStatement(ist, containers); containersOfNode.Add(containers); for (int i = 0; i < currentFusedCount; i++) { if (containers[i] is IForStatement ifs) { var loopVar = Recognizer.LoopVariable(ifs); if (loopVarsOfWhileNumber.Count <= whileNumber) { while (loopVarsOfWhileNumber.Count <= whileNumber) { loopVarsOfWhileNumber.Add(new Set <IVariableDeclaration>()); } } Set <IVariableDeclaration> loopVars = loopVarsOfWhileNumber[whileNumber]; loopVars.Add(loopVar); } } }); var nodes = g.nodes; var dependencyGraph = g.dependencyGraph; for (int whileNumber = 1; whileNumber < loopVarsOfWhileNumber.Count; whileNumber++) { foreach (var loopVar in loopVarsOfWhileNumber[whileNumber]) { // Any statement (in the while loop) that has a forward descendant and a backward descendant will be cloned, so we want to minimize the number of such nodes. // The free variables in this problem are the loop directions at the leaf statements, since all other loop directions are forced by these. // We find the optimal labeling of the free variables by solving a min cut problem on a special network. // The network is constructed so that the cost of a cut is equal to the number of statements that will be cloned. // The network has 2 nodes for every statement: an in-node and an out-node. // For a non-leaf statement, there is a capacity 1 edge from the in-node to out-node. This edge is cut when the statement is cloned. // For a leaf statement, there is an infinite capacity edge in both directions, or equivalently a single node. // If statement A depends on statement B, then there is an infinite capacity edge from in-A to in-B, and from out-B to out-A, // representing the fact that cloning A requires cloning B, but not the reverse. // If a statement must appear with a forward loop, it is connected to the source. // If a statement must appear with a backward loop, it is connected to the sink. // construct a capacitated graph int inNodeStart = 0; int outNodeStart = inNodeStart + dependencyGraph.Nodes.Count; int sourceNode = outNodeStart + dependencyGraph.Nodes.Count; int sinkNode = sourceNode + 1; int cutNodeCount = sinkNode + 1; Func <NodeIndex, int> getInNode = node => node + inNodeStart; Func <NodeIndex, int> getOutNode = node => node + outNodeStart; IndexedGraph network = new IndexedGraph(cutNodeCount); const float infinity = 1000000f; List <float> capacity = new List <float>(); List <NodeIndex> nodesOfInterest = new List <NodeIndex>(); foreach (var node in dependencyGraph.Nodes) { if (whileNumberOfNode[node] != whileNumber) { continue; } NodeIndex source = node; List <IStatement> containersOfSource = containersOfNode[source]; bool hasLoopVar = containersOfSource.Any(container => container is IForStatement && Recognizer.LoopVariable((IForStatement)container) == loopVar); if (!hasLoopVar) { continue; } nodesOfInterest.Add(node); IStatement sourceSt = nodes[source]; var readAfterWriteEdges = dependencyGraph.EdgesOutOf(source).Where(edge => !g.isWriteAfterRead[edge]); bool isLeaf = true; int inNode = getInNode(node); int outNode = getOutNode(node); foreach (var target in readAfterWriteEdges.Select(dependencyGraph.TargetOf)) { List <IStatement> containersOfTarget = containersOfNode[target]; IStatement targetSt = nodes[target]; ForEachMatchingLoopVariable(containersOfSource, containersOfTarget, (loopVar2, afs, bfs) => { if (loopVar2 == loopVar) { int inTarget = getInNode(target); int outTarget = getOutNode(target); network.AddEdge(inTarget, inNode); capacity.Add(infinity); network.AddEdge(outNode, outTarget); capacity.Add(infinity); isLeaf = false; } }); } if (isLeaf) { if (debug) { log.Add($"loopVar={loopVar.Name} leaf {sourceSt}"); } network.AddEdge(inNode, outNode); capacity.Add(infinity); network.AddEdge(outNode, inNode); capacity.Add(infinity); } else { network.AddEdge(inNode, outNode); capacity.Add(1f); } int fusedCount = fusedCountOfNode[node]; Direction desiredDirectionOfSource = GetDesiredDirection(loopVar, containersOfSource, fusedCount); if (desiredDirectionOfSource == Direction.Forward) { if (debug) { log.Add($"loopVar={loopVar.Name} forward {sourceSt}"); } network.AddEdge(sourceNode, inNode); capacity.Add(infinity); } else if (desiredDirectionOfSource == Direction.Backward) { if (debug) { log.Add($"loopVar={loopVar.Name} backward {sourceSt}"); } network.AddEdge(outNode, sinkNode); capacity.Add(infinity); } } network.IsReadOnly = true; // compute the min cut MinCut <NodeIndex, EdgeIndex> mc = new MinCut <EdgeIndex, EdgeIndex>(network, e => capacity[e]); mc.Sources.Add(sourceNode); mc.Sinks.Add(sinkNode); Set <NodeIndex> sourceGroup = mc.GetSourceGroup(); foreach (NodeIndex node in nodesOfInterest) { IStatement sourceSt = nodes[node]; bool forwardIn = sourceGroup.Contains(getInNode(node)); bool forwardOut = sourceGroup.Contains(getOutNode(node)); if (forwardIn != forwardOut) { if (debug) { log.Add($"loopVar={loopVar.Name} will clone {sourceSt}"); } } else if (forwardIn) { if (debug) { log.Add($"loopVar={loopVar.Name} wants forward {sourceSt}"); } } else { if (debug) { log.Add($"loopVar={loopVar.Name} wants backward {sourceSt}"); } var containers = containersOfNode[node]; bool isForwardLoop = true; foreach (var container in containers) { if (container is IForStatement) { IForStatement ifs = (IForStatement)container; if (Recognizer.LoopVariable(ifs) == loopVar) { isForwardLoop = Recognizer.IsForwardLoop(ifs); } } } if (isForwardLoop) { Set <IVariableDeclaration> loopVarsToReverse; if (!loopVarsToReverseInStatement.TryGetValue(sourceSt, out loopVarsToReverse)) { // TODO: re-use equivalent sets loopVarsToReverse = new Set <IVariableDeclaration>(); loopVarsToReverseInStatement.Add(sourceSt, loopVarsToReverse); } loopVarsToReverse.Add(loopVar); } } } } } base.DoConvertMethodBody(outputs, inputs); }
private void FixSpacingFor(IForStatement item) { }
private void WriteForStatement(IForStatement statement, IFormatter formatter) { this.WriteStatementSeparator(formatter); formatter.WriteKeyword("for"); formatter.Write(" ("); this.forLoop = true; this.WriteStatement(statement.Initializer, formatter); formatter.Write("; "); this.WriteExpression(statement.Condition, formatter); formatter.Write("; "); this.WriteStatement(statement.Increment, formatter); formatter.Write(")"); this.forLoop = false; formatter.Write(" {"); formatter.WriteLine(); formatter.WriteIndent(); if (statement.Body != null) { this.WriteStatement(statement.Body, formatter); } formatter.WriteLine(); formatter.WriteOutdent(); formatter.WriteKeyword("}"); }
/// <summary> /// Collect all loops in the context whose index is referenced by expr or by the size expression of another collected loop. /// </summary> /// <param name="context"></param> /// <param name="expr"></param> /// <param name="excludeAncestorIndex">Only loops whose ancestor index is greater than excludeAncestorIndex will be collected.</param> /// <param name="includeConditionals">Include condition statements</param> /// <returns>A list of IForStatements, starting with outermost.</returns> internal static List <IStatement> GetLoopsNeededForExpression( BasicTransformContext context, IExpression expr, int excludeAncestorIndex, bool includeConditionals) { List <IStatement> loopsNeeded = new List <IStatement>(); List <IStatement> ancestors = context.FindAncestorsBelow <IStatement>(excludeAncestorIndex); ancestors.Reverse(); List <IExpression> containedExpressions = new List <IExpression>(); AddToContainedExpressions(containedExpressions, expr, context); // loop ancestors starting from innermost foreach (IStatement ist in ancestors) { if (ist is IForStatement loop) { IVariableDeclaration loopVar = Recognizer.LoopVariable(loop); try { IExpression loopVarRef = Builder.VarRefExpr(loopVar); foreach (IExpression containedExpression in containedExpressions) { if (Builder.ContainsExpression(containedExpression, loopVarRef)) { IForStatement replacedLoop = Builder.ForStmt(Recognizer.LoopVariable(loop), Recognizer.LoopSizeExpression(loop)); loopsNeeded.Add(replacedLoop); AddToContainedExpressions(containedExpressions, Recognizer.LoopSizeExpression(loop), context); break; } } } catch (Exception ex) { context.Error("GetLoopsNeededForExpression", ex); } } else if (includeConditionals && (ist is IConditionStatement ics)) { bool found = false; var conditionVariables = Recognizer.GetVariables(ics.Condition).Select(Builder.VarRefExpr); foreach (IExpression conditionVariable in conditionVariables) { foreach (IExpression containedExpression in containedExpressions) { if (Builder.ContainsExpression(containedExpression, conditionVariable)) { loopsNeeded.Add(ics); AddToContainedExpressions(containedExpressions, ics.Condition, context); found = true; break; } } if (found) { break; } } } } loopsNeeded.Reverse(); return(loopsNeeded); }
protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie) { IExpression result = base.ConvertMethodInvoke(imie); if (result is IMethodInvokeExpression) { imie = (IMethodInvokeExpression)result; } else { return(result); } if (UseJaggedSubarray && Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, IReadOnlyList <PlaceHolder> >(Collection.Subarray))) { // check for the form Subarray(arrayExpr, indices[i]) where arrayExpr does not depend on i IExpression arrayExpr = imie.Arguments[0]; IExpression arg1 = imie.Arguments[1]; if (arg1 is IArrayIndexerExpression) { IArrayIndexerExpression index = (IArrayIndexerExpression)arg1; if (index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression) { // index has the form indices[i] List <IStatement> targetLoops = Containers.GetLoopsNeededForExpression(context, arrayExpr, -1, false); List <IStatement> indexLoops = Containers.GetLoopsNeededForExpression(context, index.Target, -1, false); Set <IStatement> parentLoops = new Set <IStatement>(); parentLoops.AddRange(targetLoops); parentLoops.AddRange(indexLoops); IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); foreach (IStatement loop in parentLoops) { if (Containers.ContainersAreEqual(loop, innerLoop)) { // arrayExpr depends on i return(imie); } } IVariableDeclaration arrayVar = Recognizer.GetVariableDeclaration(arrayExpr); // If the variable is not stochastic, return if (arrayVar == null) { return(imie); } VariableInformation arrayInfo = VariableInformation.GetVariableInformation(context, arrayVar); if (!arrayInfo.IsStochastic) { return(imie); } object indexVar = Recognizer.GetDeclaration(index); VariableInformation indexInfo = VariableInformation.GetVariableInformation(context, indexVar); int depth = Recognizer.GetIndexingDepth(index); IExpression resultSize = indexInfo.sizes[depth][0]; var indices = Recognizer.GetIndices(index); int replaceCount = 0; resultSize = indexInfo.ReplaceIndexVars(context, resultSize, indices, null, ref replaceCount); indexInfo.DefineIndexVarsUpToDepth(context, depth + 1); IVariableDeclaration resultIndex = indexInfo.indexVars[depth][0]; Type arrayType = arrayExpr.GetExpressionType(); Type elementType = Util.GetElementType(arrayType); // create a new variable arrayExpr_indices = JaggedSubarray(arrayExpr, indices) string name = ToString(arrayExpr) + "_" + ToString(index.Target); var stmts = Builder.StmtCollection(); var arrayIndices = Recognizer.GetIndices(arrayExpr); var bracket = Builder.ExprCollection(); bracket.Add(Builder.ArrayIndex(index, Builder.VarRefExpr(resultIndex))); arrayIndices.Add(bracket); IExpression loopSize = Recognizer.LoopSizeExpression(innerLoop); IVariableDeclaration temp = arrayInfo.DeriveArrayVariable(stmts, context, name, resultSize, resultIndex, arrayIndices); VariableInformation tempInfo = VariableInformation.GetVariableInformation(context, temp); stmts.Clear(); IVariableDeclaration newvd = tempInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex)); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression rhs = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, int[][], PlaceHolder[][]>(Collection.JaggedSubarray), new Type[] { elementType }, arrayExpr, index.Target); context.InputAttributes.CopyObjectAttributesTo <Algorithm>(newvd, context.OutputAttributes, rhs); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), rhs)); // Reduce memory consumption by declaring the clone outside of unnecessary loops. // This way, the item is cloned outside the loop and then replicated, instead of replicating the entire array and cloning the item. Containers containers = new Containers(context); containers = RemoveReferencesTo(containers, innerIndex); containers = Containers.RemoveUnusedLoops(containers, context, rhs); if (context.InputAttributes.Has <DoNotSendEvidence>(arrayVar)) { containers = Containers.RemoveStochasticConditionals(containers, context); } // To put the declaration in the desired containers, we find an ancestor which includes as many of the containers as possible, // then wrap the declaration with the remaining containers. int ancIndex = containers.GetMatchingAncestorIndex(context); Containers missing = containers.GetContainersNotInContext(context, ancIndex); stmts = Containers.WrapWithContainers(stmts, missing.outputs); context.AddStatementsBeforeAncestorIndex(ancIndex, stmts); context.InputAttributes.Set(newvd, containers); // convert into arrayExpr_indices[i] IExpression newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex); newExpr = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { newExpr.GetExpressionType() }, newExpr); return(newExpr); } } } return(imie); }
public override void TraverseChildren(IForStatement forStatement) { this.sourceEmitterOutput.Write("for (", true); this.TraverseInitializersOrIncrementers(forStatement.InitStatements); this.sourceEmitterOutput.Write("; "); this.Traverse(forStatement.Condition); this.sourceEmitterOutput.Write("; "); this.TraverseInitializersOrIncrementers(forStatement.IncrementStatements); this.sourceEmitterOutput.WriteLine(")"); this.Traverse(forStatement.Body); }
/// <summary> /// /// </summary> /// <param name="forStatement"></param> public ForStatement(IForStatement forStatement) : base(forStatement) { this.body = forStatement.Body; this.condition = forStatement.Condition; this.incrementStatements = new List<IStatement>(forStatement.IncrementStatements); this.initStatements = new List<IStatement>(forStatement.InitStatements); }
private IForStatement ConvertForWithDistributedSchedule(IForStatement ifs, IVariableDeclaration loopVar, DistributedScheduleExpression dse) { if (dse.scheduleExpression == null && dse.schedulePerThreadExpression == null) { return((IForStatement)base.ConvertFor(ifs)); } Sequential attr = context.InputAttributes.Get <Sequential>(loopVar); if (attr == null || !attr.BackwardPass) { Error($"Range '{loopVar.Name}' has a DistributedSchedule attribute but does not have a Sequential attribute with BackwardPass = true"); } // Convert this loop into for(stage) for(indexInBlock) { ... } IVariableDeclaration loopVarBlock = VariableInformation.GenerateLoopVar(context, loopVar.Name + "_Block"); Sequential sequentialAttr = new Sequential(); context.OutputAttributes.Set(loopVarBlock, sequentialAttr); bool isBackwardLoop = !Recognizer.IsForwardLoop(ifs); this.distributedCommunicationExpressions.Clear(); IForStatement loopInBlock; IExpression zero = Builder.LiteralExpr(0); IExpression distributedStageCount; if (dse.schedulePerThreadExpression != null) { var scheduleForBlock = Builder.ArrayIndex(dse.schedulePerThreadExpression, Builder.VarRefExpr(loopVarBlock)); distributedStageCount = Builder.PropRefExpr(dse.schedulePerThreadExpression, typeof(int[][][][]), "Length"); loopInBlock = ConvertForWithParallelSchedule(ifs, loopVar, new ParallelScheduleExpression(scheduleForBlock)); } else { IVariableDeclaration loopVarInBlock = VariableInformation.GenerateLoopVar(context, loopVar.Name + "_inBlock"); context.OutputAttributes.Set(loopVarInBlock, sequentialAttr); if (!dse.scheduleExpression.GetExpressionType().Equals(typeof(int[][]))) { Error("argument to DistributedSchedule attribute is not of type int[][]"); } IExpression itemsInBlock = Builder.ArrayIndex(dse.scheduleExpression, Builder.VarRefExpr(loopVarBlock)); IExpression itemCountInBlock = Builder.PropRefExpr(itemsInBlock, typeof(int[]), "Length"); distributedStageCount = Builder.PropRefExpr(dse.scheduleExpression, typeof(int[][]), "Length"); loopInBlock = Builder.ForStmt(loopVarInBlock, itemCountInBlock); if (isBackwardLoop) { Recognizer.ReverseLoopDirection(loopInBlock); } var assignLoopVar = Builder.AssignStmt(Builder.VarDeclExpr(loopVar), Builder.ArrayIndex(itemsInBlock, Builder.VarRefExpr(loopVarInBlock))); loopInBlock.Body.Statements.Add(assignLoopVar); ConvertStatements(loopInBlock.Body.Statements, ifs.Body.Statements); } IForStatement loopBlock = Builder.ForStmt(loopVarBlock, distributedStageCount); IExpression commExpr = dse.commExpression; if (isBackwardLoop) { loopBlock.Body.Statements.Add(loopInBlock); foreach (var tuple in this.distributedCommunicationExpressions) { var arrayExpr = tuple.Item1; var dce = tuple.Item2; IExpression sendExpr = Builder.ArrayIndex(dce.arrayIndicesToSendExpression, Builder.VarRefExpr(loopVarBlock)); IExpression receiveExpr = Builder.ArrayIndex(dce.arrayIndicesToReceiveExpression, Builder.VarRefExpr(loopVarBlock)); var sendReceiveMethod = Builder.StaticGenericMethod(new Action <ICommunicator, IList <PlaceHolder>, int[][], int[][]>(Communicator.AlltoallSubarrays), new Type[] { Utilities.Util.GetElementType(arrayExpr.GetExpressionType()) }, commExpr, arrayExpr, receiveExpr, sendExpr); loopBlock.Body.Statements.Add(Builder.ExprStatement(sendReceiveMethod)); } Recognizer.ReverseLoopDirection(loopBlock); } else { foreach (var tuple in this.distributedCommunicationExpressions) { var arrayExpr = tuple.Item1; var dce = tuple.Item2; IExpression sendExpr = Builder.ArrayIndex(dce.arrayIndicesToSendExpression, Builder.VarRefExpr(loopVarBlock)); IExpression receiveExpr = Builder.ArrayIndex(dce.arrayIndicesToReceiveExpression, Builder.VarRefExpr(loopVarBlock)); var sendReceiveMethod = Builder.StaticGenericMethod(new Action <ICommunicator, IList <PlaceHolder>, int[][], int[][]>(Communicator.AlltoallSubarrays), new Type[] { Utilities.Util.GetElementType(arrayExpr.GetExpressionType()) }, commExpr, arrayExpr, sendExpr, receiveExpr); loopBlock.Body.Statements.Add(Builder.ExprStatement(sendReceiveMethod)); } loopBlock.Body.Statements.Add(loopInBlock); } return(loopBlock); }
/// <summary> /// Visits the specified for statement. /// </summary> /// <param name="forStatement">For statement.</param> public override void Visit(IForStatement forStatement) { ForStatement mutableForStatement = new ForStatement(forStatement); this.resultStatement = this.myCodeCopier.DeepCopy(mutableForStatement); }
/// <summary> /// Only converts the contained statements in a for loop, leaving the initializer, /// condition and increment statements unchanged. /// </summary> /// <remarks>This method includes a number of checks to ensure the loop is valid e.g. that the initializer, condition and increment /// are all of the appropriate form.</remarks> protected override IStatement ConvertFor(IForStatement ifs) { IForStatement fs = Builder.ForStmt(); context.SetPrimaryOutput(fs); // Check condition is valid fs.Condition = ifs.Condition; if ((!(fs.Condition is IBinaryExpression)) || (((IBinaryExpression)fs.Condition).Operator != BinaryOperator.LessThan)) { Error("For statement condition must be of the form 'indexVar<loopSize', was " + fs.Condition); } // Check increment is valid fs.Increment = ifs.Increment; IExpressionStatement ies = fs.Increment as IExpressionStatement; bool validIncrement = false; if (ies != null) { if (ies.Expression is IAssignExpression) { IAssignExpression iae = (IAssignExpression)ies.Expression; IBinaryExpression ibe = RemoveCast(iae.Expression) as IBinaryExpression; validIncrement = (ibe != null) && (ibe.Operator == BinaryOperator.Add); } else if (ies.Expression is IUnaryExpression) { IUnaryExpression iue = (IUnaryExpression)ies.Expression; validIncrement = (iue.Operator == UnaryOperator.PostIncrement); } } if (!validIncrement) { Error("For statement increment must be of the form 'varname++' or 'varname=varname+1', was " + fs.Increment + "."); } // Check initializer is valid fs.Initializer = ifs.Initializer; ies = fs.Initializer as IExpressionStatement; if (ies == null) { Error("For statement initializer must be an expression statement, was " + fs.Initializer.GetType()); } else { if (!(ies.Expression is IAssignExpression)) { Error("For statement initializer must be an assignment, was " + fs.Initializer.GetType().Name); } else { IAssignExpression iae2 = (IAssignExpression)ies.Expression; if (!(iae2.Target is IVariableDeclarationExpression)) { Error("For statement initializer must be a variable declaration, was " + iae2.Target.GetType().Name); } if (!Recognizer.IsLiteral(iae2.Expression, 0)) { Error("Loop index must start at 0, was " + iae2.Expression); } } } fs.Body = ConvertBlock(ifs.Body); return(fs); }
/// <summary> /// Returns a deep copy of the given for statement. /// </summary> /// <param name="forStatement"></param> public ForStatement Copy(IForStatement forStatement) { var mutableCopy = this.shallowCopier.Copy(forStatement); mutableCopy.InitStatements = this.Copy(mutableCopy.InitStatements); mutableCopy.Condition = this.Copy(mutableCopy.Condition); mutableCopy.IncrementStatements = this.Copy(mutableCopy.IncrementStatements); mutableCopy.Body = this.Copy(mutableCopy.Body); return mutableCopy; }
/// <summary> /// Returns a shallow copy of the given for statement. /// </summary> /// <param name="forStatement"></param> public ForStatement Copy(IForStatement forStatement) { return new ForStatement(forStatement); }