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)); }
public override ITypeDeclaration Transform(ITypeDeclaration itd) { analysis = new HoistingAnalysisTransform(); Stopwatch watch = null; if (compiler.ShowProgress) { Console.Write($"({analysis.Name} "); watch = Stopwatch.StartNew(); } analysis.Context.InputAttributes = context.InputAttributes; analysis.Transform(itd); if (compiler.ShowProgress) { watch.Stop(); Console.Write("{0}ms) ", watch.ElapsedMilliseconds); } context.Results = analysis.Context.Results; if (!context.Results.IsSuccess) { Error("analysis failed"); return(itd); } // create new variable names foreach (var entry in analysis.infoOfVariable) { var ivd = entry.Key; var info = entry.Value; PromoteDimensions(info); int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; bool hasUnusedIndex = info.maxDepthWhereDimensionCouldMatter.Any(bracket => bracket.Any(depth => depth < arrayDepth)); if (hasUnusedIndex) { info.newVariable = Builder.VarDecl(ivd.Name + "_reduced", GetReducedType(ivd.VariableType.DotNetType, info)); CreateReducedVariableInformation(ivd, info); } } var itdOut = base.Transform(itd); if (context.trackTransform && debug) { IBlockStatement block = Builder.BlockStmt(); foreach (var entry in analysis.infoOfVariable) { var ivd = entry.Key; var info = entry.Value; int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; for (int bracket = 0; bracket < info.maxDepthWhereDimensionCouldMatter.Length; bracket++) { for (int dim = 0; dim < info.maxDepthWhereDimensionCouldMatter[bracket].Length; dim++) { int depth = info.maxDepthWhereDimensionCouldMatter[bracket][dim]; if (depth != arrayDepth) { var varInfo = VariableInformation.GetVariableInformation(context, ivd); block.Statements.Add(Builder.CommentStmt($"{ivd.Name} index {varInfo.indexVars[bracket][dim].Name} only matters at depth {depth}")); } } } } context.OutputAttributes.Add(itdOut, new DebugInfo() { Transform = this, Name = "analysis", Value = block }); } return(itdOut); }