internal Containers Where(Predicate <IStatement> predicate) { Containers result = new Containers(); for (int i = 0; i < inputs.Count; i++) { IStatement container = inputs[i]; if (predicate(container)) { result.inputs.Add(container); result.outputs.Add(outputs[i]); } } return(result); }
/// <summary> /// Get the minimal set of containers needed to evaluate an expression, along with the first index in the context stack at which the expression's variables are all declared. /// </summary> /// <param name="context">The transform context</param> /// <param name="expr">Any expression</param> /// <param name="ancIndex">On exit, the first index in the context stack at which the expression's variables are all declared.</param> /// <returns>The minimal set of containers needed to evaluate expr</returns> internal static Containers GetContainersNeededForExpression(BasicTransformContext context, IExpression expr, out int ancIndex) { Containers containers = GetContainersNeededForExpression(context, expr); if (containers == null) { ancIndex = -1; return(null); } ancIndex = containers.GetMatchingAncestorIndex(context); // append any conditionals with constant conditions //List<IStatement> loopsMissing = Containers.GetLoopsNeededForExpression(context, expr, ancIndex-1, true); //containers = Containers.Append(containers, loopsMissing); //containers.OrderByContext(context); return(containers); }
internal static Containers InsideOf(BasicTransformContext context, int exclude) { Containers containers = new Containers(); for (int i = exclude + 1; i < context.InputStack.Count; i++) { TransformInfo ti = context.InputStack[i]; IStatement inputElement = ti.inputElement as IStatement; if (IsContainer(inputElement) && !context.InputAttributes.Has <ConvergenceLoop>(inputElement)) { containers.inputs.Add(CreateContainer(inputElement)); containers.outputs.Add((IStatement)ti.PrimaryOutput); } } return(containers); }
/// <summary> /// Collect all containers that are not in the context at the given index. /// </summary> /// <param name="context"></param> /// <param name="ancestorIndex">If 0, all containers are returned.</param> /// <returns></returns> internal Containers GetContainersNotInContext(BasicTransformContext context, int ancestorIndex) { Containers result = new Containers(); for (int i = 0; i < inputs.Count; i++) { IStatement container = inputs[i]; int index = GetAncestorIndex(context, container); if (index == -1 || index >= ancestorIndex) { result.inputs.Add(container); result.outputs.Add(outputs[i]); } } return(result); }
internal static Containers Append(Containers containers, Containers extraContainers) { Containers result = new Containers(); result.inputs = new List <IStatement>(containers.inputs); result.outputs = new List <IStatement>(containers.outputs); for (int i = 0; i < extraContainers.inputs.Count; i++) { IStatement input = extraContainers.inputs[i]; if (!containers.Contains(input)) { result.inputs.Add(input); result.outputs.Add(extraContainers.outputs[i]); } } return(result); }
internal Containers Replace(Func <IStatement, IStatement> getReplacement) { Containers result = new Containers(); for (int i = 0; i < inputs.Count; i++) { IStatement container = inputs[i]; IStatement replacement = getReplacement(container); result.inputs.Add(replacement); if (!ContainersAreEqual(outputs[i], inputs[i])) { throw new Exception("outputs[i] != inputs[i]"); } result.outputs.Add(replacement); } return(result); }
/// <summary> /// Returns the outermost container in the context that is not in this. /// </summary> /// <param name="context"></param> /// <returns></returns> internal int GetMatchingAncestorIndex(BasicTransformContext context) { int ancIndex = context.FindAncestorIndex <IStatement>(); foreach (IStatement container in Containers.FindContainers(context)) { if (context.InputAttributes.Has <ConvergenceLoop>(container)) { continue; } if (!this.Contains(container)) { // found a container unique to the current context. // statements must be added here. ancIndex = context.GetAncestorIndex(container); break; } } return(ancIndex); }
internal static Containers RemoveStochasticConditionals(Containers containers, BasicTransformContext context) { Containers result = new Containers(); for (int i = 0; i < containers.inputs.Count; i++) { IStatement container = containers.inputs[i]; if (container is IConditionStatement) { IConditionStatement ics = (IConditionStatement)container; if (CodeRecognizer.IsStochastic(context, ics.Condition)) { continue; } } result.inputs.Add(container); result.outputs.Add(containers.outputs[i]); } return(result); }
/// <summary> /// Check that the replacements are safe. /// </summary> /// <param name="context"></param> /// <param name="expr"></param> /// <param name="replacedIndexVars"></param> private static void CheckReplacements(BasicTransformContext context, IExpression expr, Dictionary <IVariableDeclaration, IExpression> replacedIndexVars) { foreach (var v in Recognizer.GetVariables(expr)) { Containers containers = context.InputAttributes.Get <Containers>(v); if (containers != null && !replacedIndexVars.ContainsKey(v)) { foreach (IStatement container in containers.inputs) { if (container is IForStatement ifs) { IVariableDeclaration loopVar = Recognizer.LoopVariable(ifs); if (replacedIndexVars.TryGetValue(loopVar, out IExpression actualIndex)) { context.Error($"Cannot index {expr} by {loopVar.Name}={actualIndex} since {v.Name} has an implicit dependency on {loopVar.Name}. Try making the dependency explicit by putting {v.Name} into an array indexed by {loopVar.Name}"); } } } } } }
/// <summary> /// Returns the containers common to both, preserving the order in the first argument. /// </summary> /// <param name="containers"></param> /// <param name="containers2"></param> /// <param name="allowBrokenLoops"></param> /// <param name="ignoreLoopDirection"></param> /// <returns></returns> internal static Containers Intersect(Containers containers, Containers containers2, bool allowBrokenLoops = false, bool ignoreLoopDirection = false) { Containers result = new Containers(); for (int i = 0; i < containers.inputs.Count; i++) { IStatement container = containers.inputs[i]; for (int j = 0; j < containers2.inputs.Count; j++) { IStatement container2 = containers2.inputs[j]; IStatement intersected = Intersect(container, container2, allowBrokenLoops, ignoreLoopDirection); if (intersected != null) { result.inputs.Add(intersected); var intersectedOutput = Intersect(containers.outputs[i], containers2.outputs[j], allowBrokenLoops, ignoreLoopDirection); result.outputs.Add(intersectedOutput); } } } return(result); }
internal Containers RemoveOneRepeat(IRepeatStatement irs) { bool found = false; Containers result = new Containers(); for (int i = 0; i < inputs.Count; i++) { IStatement container = inputs[i]; if (!found && container is IRepeatStatement rs) { if (rs.Count.Equals(irs.Count)) { found = true; continue; } } result.inputs.Add(container); result.outputs.Add(outputs[i]); } return(result); }
private Containers(Containers c) { inputs.AddRange(c.inputs); outputs.AddRange(c.outputs); }
/// <summary> /// Remove loops (and their dependent containers) that are not needed to evaluate the expression. /// </summary> /// <param name="containers"></param> /// <param name="context"></param> /// <param name="needed"></param> /// <returns></returns> internal static Containers RemoveUnusedLoops(Containers containers, BasicTransformContext context, Containers needed) { Containers result = new Containers(); Set <IVariableDeclaration> allowedVars = Containers.GetConditionedLoopVariables(context); allowedVars.Clear(); // for ReplicateWithConditionedIndexTest for (int i = 0; i < containers.inputs.Count; i++) { IStatement container = containers.inputs[i]; if (container is IForStatement) { IForStatement ifs = container as IForStatement; IVariableDeclaration loopVar = Recognizer.LoopVariable(ifs); if (!allowedVars.Contains(loopVar) && !needed.Contains(container)) { continue; } } result.inputs.Add(container); result.outputs.Add(containers.outputs[i]); } // Removing unused loops may have left us with containers that refer to the removed loop index. We must remove these also. // Note this routine could be merged with RemoveUnusedLoops. result = Containers.RemoveInvalidConditions(result, context); return(result); }
/// <summary> /// Remove loops (and their dependent containers) that are not needed to evaluate the expression. /// </summary> /// <param name="containers"></param> /// <param name="context"></param> /// <param name="expr"></param> /// <returns></returns> internal static Containers RemoveUnusedLoops(Containers containers, BasicTransformContext context, IExpression expr) { Containers needed = Containers.GetContainersNeededForExpression(context, expr); return(RemoveUnusedLoops(containers, context, needed)); }
internal static Containers RemoveInvalidConditions(Containers containers, BasicTransformContext context) { Containers result = new Containers(); for (int i = 0; i < containers.inputs.Count; i++) { IStatement container = containers.inputs[i]; if (container is IConditionStatement) { IConditionStatement ics = (IConditionStatement)container; IExpression condition = ics.Condition; if (condition is IBinaryExpression && ((IBinaryExpression)condition).Operator == BinaryOperator.BooleanAnd) { // split the condition into conjuncts List <IExpression> conditions = new List <IExpression>(); IExpression newCondition = null; bool changed = false; ForEachConjunct(condition, delegate(IExpression expr) { if (ContainsExpression(containers.inputs, context, expr)) { if (newCondition == null) { newCondition = expr; } else { newCondition = Builder.BinaryExpr(BinaryOperator.BooleanAnd, newCondition, expr); } } else { changed = true; } }); if (changed) { if (newCondition != null) { IConditionStatement cs = Builder.CondStmt(newCondition, Builder.BlockStmt()); result.inputs.Add(cs); result.outputs.Add(cs); } continue; } } else { if (!ContainsExpression(containers.inputs, context, condition)) { continue; } } } else if (container is IRepeatStatement) { IRepeatStatement irs = (IRepeatStatement)container; if (!ContainsExpression(containers.inputs, context, irs.Count)) { continue; } } result.inputs.Add(container); result.outputs.Add(containers.outputs[i]); } return(result); }
internal Containers Remove(Containers containers) { return(Remove(containers.inputs)); }
internal bool SetEquals(Containers c) { return(Contains(c) && c.Contains(this)); }