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