/// <summary> /// Returns the outermost container in the context that is not in this. /// </summary> /// <param name="context"></param> /// <param name="containers"></param> /// <returns></returns> private int GetMatchingAncestorIndex(BasicTransformContext context, ICollection <IStatement> containers) { int ancIndex = context.FindAncestorIndex <IStatement>(); foreach (IStatement container in Containers.FindContainers(context)) { if (context.InputAttributes.Has <ConvergenceLoop>(container)) { continue; } if (!containers.Contains(container)) { // found a container unique to the current context. // statements must be added here. ancIndex = context.GetAncestorIndex(container); break; } } return(ancIndex); }
protected override IExpression ConvertAssign(IAssignExpression iae) { IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iae.Target); HoistingInfo info; if (ivd != null && analysis.infoOfVariable.TryGetValue(ivd, out info) && info.newVariable != null) { int indexingDepth = Recognizer.GetIndexingDepth(iae.Target); bool mustConvertRhs = false; int newRank = 0; int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; for (int bracket = indexingDepth; bracket < info.maxDepthWhereDimensionCouldMatter.Length; bracket++) { for (int dim = 0; dim < info.maxDepthWhereDimensionCouldMatter[bracket].Length; dim++) { if (info.maxDepthWhereDimensionCouldMatter[bracket][dim] != arrayDepth) { mustConvertRhs = true; } else if (bracket == indexingDepth) { newRank++; } } } IExpression newTarget; if (iae.Target is IVariableReferenceExpression) { newTarget = Builder.VarRefExpr(info.newVariable); } else if (iae.Target is IVariableDeclarationExpression) { newTarget = Builder.VarDeclExpr(info.newVariable); } else if (iae.Target is IArrayIndexerExpression) { IExpression target; var indices = Recognizer.GetIndices(iae.Target, out target); newTarget = Builder.VarRefExpr(info.newVariable); for (int bracket = 0; bracket < indexingDepth; bracket++) { if (info.maxDepthWhereDimensionCouldMatter[bracket].Any(d => d == arrayDepth)) { List <IExpression> newIndices = new List <IExpression>(); for (int dim = 0; dim < indices[bracket].Count; dim++) { if (info.maxDepthWhereDimensionCouldMatter[bracket][dim] == arrayDepth) { newIndices.Add(indices[bracket][dim]); } } newTarget = Builder.ArrayIndex(newTarget, newIndices); } } } else { throw new NotSupportedException(); } if (mustConvertRhs) { if (HoistingAnalysisTransform.IsReducibleArrayCreateExpression(iae.Expression)) { IStatement assignStmt = context.FindAncestor <IStatement>(); context.AddStatementAfterCurrent(assignStmt); Type type = info.newVariable.VariableType.DotNetType; int newDepth = Recognizer.GetIndexingDepth(newTarget); for (int bracket = 0; bracket < newDepth; bracket++) { type = Util.GetElementType(type); } IExpression newRhs; if (newRank == 0) { newRhs = Builder.DefaultExpr(type); if (newDepth == 0) { // If we have already initialized newTarget at the top level, there is no need to initialize again. if (info.isInitialized) { return(null); } else if (Containers.FindContainers(context).Count == 0) { info.isInitialized = true; } } } else if (iae.Expression is IArrayCreateExpression iace) { Type elementType = Util.GetElementType(type); newRhs = Builder.ArrayCreateExpr(elementType, GetReducedDimensions(iace.Dimensions, info.maxDepthWhereDimensionCouldMatter[indexingDepth], arrayDepth)); } else if (iae.Expression is IObjectCreateExpression ioce) { newRhs = Builder.NewObject(type, GetReducedDimensions(ioce.Arguments, info.maxDepthWhereDimensionCouldMatter[indexingDepth], arrayDepth)); } else { throw new InferCompilerException($"Unexpected expression type: {iae.Expression.GetType()}"); } return(Builder.AssignExpr(newTarget, newRhs)); } else { throw new NotSupportedException(); } } else { IStatement copyStmt = Builder.AssignStmt(iae.Target, newTarget); IStatement assignStmt = context.FindAncestor <IStatement>(); context.InputAttributes.CopyObjectAttributesTo(assignStmt, context.OutputAttributes, copyStmt); context.AddStatementAfterCurrent(copyStmt); } } return(base.ConvertAssign(iae)); }