예제 #1
0
        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));
        }
예제 #2
0
        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);
        }