/// <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> /// 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); }