private static void ForEachMatchingLoopVariable(
     List <IStatement> containersOfSource,
     List <IStatement> containersOfTarget,
     Action <IVariableDeclaration, IForStatement, IForStatement> action)
 {
     for (int i = 0; i < System.Math.Min(containersOfTarget.Count, containersOfSource.Count); i++)
     {
         if (containersOfTarget[i] is IForStatement)
         {
             if (!(containersOfSource[i] is IForStatement))
             {
                 break;
             }
             IForStatement        afs     = (IForStatement)containersOfTarget[i];
             IForStatement        bfs     = (IForStatement)containersOfSource[i];
             IVariableDeclaration loopVar = Recognizer.LoopVariable(afs);
             if (Recognizer.LoopVariable(bfs) != loopVar)
             {
                 break;
             }
             // both loops use the same variable.
             action(loopVar, afs, bfs);
         }
         else if (!Containers.ContainersAreEqual(containersOfTarget[i], containersOfSource[i]))
         {
             break;
         }
     }
 }
示例#2
0
        private IList <IStatement> UnwrapStatement(IStatement ist, IList <IStatement> newContainers, IList <int> newPriority, int stmtIndex, bool keepNested)
        {
            List <IStatement>  stmtContainers = new List <IStatement>();
            IList <IStatement> core           = UnwrapStatement(ist, stmtContainers);

            int[] priority           = GetPriorities(stmtContainers);
            int[] openPriority       = Util.ArrayInit(openContainers.Count, i => - 1);
            int   highestNewPriority = 0;

            // determine the set of open containers which can be kept
            for (int j = 0; j < stmtContainers.Count; j++)
            {
                IStatement container = stmtContainers[j];
                if (container is IBrokenForStatement)
                {
                    continue;
                }
                bool found = false;
                for (int i = 0; i < openContainers.Count; i++)
                {
                    IStatement openContainer = openContainers[i];
                    if (Containers.ContainersAreEqual(openContainer, container))
                    {
                        found = true;
                        if (CanAddToContainer(openContainer, stmtIndex))
                        {
                            openPriority[i] = priority[j];
                        }
                        break;
                    }
                }
                if (!found && priority[j] > highestNewPriority)
                {
                    highestNewPriority = priority[j];
                }
            }
            // priority of containers:
            // 1. a sequential container that is already open, and its parent containers (whether they are sequential or not).
            // 2. a new sequential container and its parent containers.
            // 3. a container that is already open.
            if (keepNested)
            {
                // close all open containers whose priority is lower than highestNewPriority
                for (int i = openContainers.Count - 1; i >= 0; i--)
                {
                    if (openPriority[i] < highestNewPriority)
                    {
                        openPriority[i] = -1;
                    }
                    else
                    {
                        break;
                    }
                }
                // close all containers beyond the first closed one
                for (int i = 0; i < openContainers.Count; i++)
                {
                    if (openPriority[i] == -1)
                    {
                        RemoveLast(openContainers, i);
                        break;
                    }
                }
            }
            else
            {
                List <IStatement> keptContainers = new List <IStatement>();
                for (int i = 0; i < openContainers.Count; i++)
                {
                    if (openPriority[i] >= 0)
                    {
                        keptContainers.Add(openContainers[i]);
                    }
                }
                openContainers.Clear();
                openContainers.AddRange(keptContainers);
            }
            List <KeyValuePair <int, IStatement> > newContainersWithPriority = new List <KeyValuePair <int, IStatement> >();

            for (int j = 0; j < stmtContainers.Count; j++)
            {
                IStatement container = stmtContainers[j];
                bool       found     = false;
                for (int i = 0; i < openContainers.Count; i++)
                {
                    IStatement openContainer = openContainers[i];
                    if (Containers.ContainersAreEqual(openContainer, container))
                    {
                        if (openPriority[i] >= 0)
                        {
                            found = true;
                        }
                        break;
                    }
                }
                if (!found)
                {
                    newContainersWithPriority.Add(new KeyValuePair <int, IStatement>(priority[j], container));
                }
            }
            newContainers.Clear();
            newPriority.Clear();
            foreach (var kvp in newContainersWithPriority.OrderByDescending(kvp => kvp.Key))
            {
                newPriority.Add(kvp.Key);
                newContainers.Add(kvp.Value);
            }
            return(core);
        }
        protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie)
        {
            IExpression result = base.ConvertMethodInvoke(imie);

            if (result is IMethodInvokeExpression)
            {
                imie = (IMethodInvokeExpression)result;
            }
            else
            {
                return(result);
            }
            if (UseJaggedSubarray && Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, IReadOnlyList <PlaceHolder> >(Collection.Subarray)))
            {
                // check for the form Subarray(arrayExpr, indices[i]) where arrayExpr does not depend on i
                IExpression arrayExpr = imie.Arguments[0];
                IExpression arg1      = imie.Arguments[1];
                if (arg1 is IArrayIndexerExpression)
                {
                    IArrayIndexerExpression index = (IArrayIndexerExpression)arg1;
                    if (index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression)
                    {
                        // index has the form indices[i]
                        List <IStatement> targetLoops = Containers.GetLoopsNeededForExpression(context, arrayExpr, -1, false);
                        List <IStatement> indexLoops  = Containers.GetLoopsNeededForExpression(context, index.Target, -1, false);
                        Set <IStatement>  parentLoops = new Set <IStatement>();
                        parentLoops.AddRange(targetLoops);
                        parentLoops.AddRange(indexLoops);
                        IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0];
                        IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex);
                        foreach (IStatement loop in parentLoops)
                        {
                            if (Containers.ContainersAreEqual(loop, innerLoop))
                            {
                                // arrayExpr depends on i
                                return(imie);
                            }
                        }
                        IVariableDeclaration arrayVar = Recognizer.GetVariableDeclaration(arrayExpr);
                        // If the variable is not stochastic, return
                        if (arrayVar == null)
                        {
                            return(imie);
                        }
                        VariableInformation arrayInfo = VariableInformation.GetVariableInformation(context, arrayVar);
                        if (!arrayInfo.IsStochastic)
                        {
                            return(imie);
                        }
                        object indexVar = Recognizer.GetDeclaration(index);
                        VariableInformation indexInfo = VariableInformation.GetVariableInformation(context, indexVar);
                        int         depth             = Recognizer.GetIndexingDepth(index);
                        IExpression resultSize        = indexInfo.sizes[depth][0];
                        var         indices           = Recognizer.GetIndices(index);
                        int         replaceCount      = 0;
                        resultSize = indexInfo.ReplaceIndexVars(context, resultSize, indices, null, ref replaceCount);
                        indexInfo.DefineIndexVarsUpToDepth(context, depth + 1);
                        IVariableDeclaration resultIndex = indexInfo.indexVars[depth][0];
                        Type arrayType   = arrayExpr.GetExpressionType();
                        Type elementType = Util.GetElementType(arrayType);

                        // create a new variable arrayExpr_indices = JaggedSubarray(arrayExpr, indices)
                        string name = ToString(arrayExpr) + "_" + ToString(index.Target);

                        var stmts        = Builder.StmtCollection();
                        var arrayIndices = Recognizer.GetIndices(arrayExpr);
                        var bracket      = Builder.ExprCollection();
                        bracket.Add(Builder.ArrayIndex(index, Builder.VarRefExpr(resultIndex)));
                        arrayIndices.Add(bracket);
                        IExpression          loopSize = Recognizer.LoopSizeExpression(innerLoop);
                        IVariableDeclaration temp     = arrayInfo.DeriveArrayVariable(stmts, context, name, resultSize, resultIndex, arrayIndices);
                        VariableInformation  tempInfo = VariableInformation.GetVariableInformation(context, temp);
                        stmts.Clear();
                        IVariableDeclaration newvd = tempInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex));
                        if (!context.InputAttributes.Has <DerivedVariable>(newvd))
                        {
                            context.InputAttributes.Set(newvd, new DerivedVariable());
                        }
                        IExpression rhs = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, int[][], PlaceHolder[][]>(Collection.JaggedSubarray),
                                                                      new Type[] { elementType }, arrayExpr, index.Target);
                        context.InputAttributes.CopyObjectAttributesTo <Algorithm>(newvd, context.OutputAttributes, rhs);
                        stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), rhs));

                        // Reduce memory consumption by declaring the clone outside of unnecessary loops.
                        // This way, the item is cloned outside the loop and then replicated, instead of replicating the entire array and cloning the item.
                        Containers containers = new Containers(context);
                        containers = RemoveReferencesTo(containers, innerIndex);
                        containers = Containers.RemoveUnusedLoops(containers, context, rhs);
                        if (context.InputAttributes.Has <DoNotSendEvidence>(arrayVar))
                        {
                            containers = Containers.RemoveStochasticConditionals(containers, context);
                        }
                        // To put the declaration in the desired containers, we find an ancestor which includes as many of the containers as possible,
                        // then wrap the declaration with the remaining containers.
                        int        ancIndex = containers.GetMatchingAncestorIndex(context);
                        Containers missing  = containers.GetContainersNotInContext(context, ancIndex);
                        stmts = Containers.WrapWithContainers(stmts, missing.outputs);
                        context.AddStatementsBeforeAncestorIndex(ancIndex, stmts);
                        context.InputAttributes.Set(newvd, containers);

                        // convert into arrayExpr_indices[i]
                        IExpression newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex);
                        newExpr = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { newExpr.GetExpressionType() }, newExpr);
                        return(newExpr);
                    }
                }
            }
            return(imie);
        }
示例#4
0
        /// <summary>
        /// Add localInfo for expr to the current containerInfo.
        /// </summary>
        /// <param name="decl"></param>
        /// <param name="expr"></param>
        /// <param name="localInfo"></param>
        /// <param name="closedContainer"></param>
        protected LocalInfo AddLocalInfo(object decl, IExpression expr, LocalInfo localInfo, IForStatement closedContainer)
        {
            if (containerInfos.Count == 0)
            {
                return(localInfo);
            }
            ContainerInfo containerInfo = containerInfos.Peek();
            UsageInfo     usageInfo;

            if (!containerInfo.usageInfoOfVariable.TryGetValue(decl, out usageInfo))
            {
                usageInfo = new UsageInfo();
                containerInfo.usageInfoOfVariable[decl] = usageInfo;
            }
            LocalInfo info;

            if (!usageInfo.localInfos.TryGetValue(expr, out info))
            {
                info = localInfo.Clone();
                info.containingStatements.IntersectWith(openContainers);
                IVariableDeclaration loopVar        = Recognizer.LoopVariable(closedContainer);
                int        index                    = info.containers.inputs.FindIndex(container => Containers.ContainersAreEqual(container, closedContainer, allowBrokenLoops: true, ignoreLoopDirection: true));
                bool       conditionsContainLoopVar = info.containers.inputs.Skip(index + 1).Any(container => Recognizer.GetVariables(GetContainerExpression(container)).Contains(loopVar));
                IStatement replacement              = null;
                if (conditionsContainLoopVar)
                {
                    replacement = Builder.BrokenForStatement(closedContainer);
                    info.containingStatements.Add(replacement);
                }
                else
                {
                    var  loopSize        = Recognizer.LoopSizeExpression(closedContainer);
                    bool loopMustExecute = false;
                    if (loopSize is ILiteralExpression ile)
                    {
                        int loopSizeAsInt = (int)ile.Value;
                        if (loopSizeAsInt > 0)
                        {
                            loopMustExecute = true;
                        }
                    }
                    if (!loopMustExecute)
                    {
                        var condition = Builder.BinaryExpr(loopSize, BinaryOperator.GreaterThan, Builder.LiteralExpr(0));
                        replacement = Builder.CondStmt(condition, Builder.BlockStmt());
                    }
                }
                if (info.containers.inputs.Contains(replacement))
                {
                    replacement = null;
                }
                if (replacement == null)
                {
                    info.containers = info.containers.Where(container => !Containers.ContainersAreEqual(container, closedContainer, true, true));
                }
                else
                {
                    // this only replaces containers.inputs
                    info.containers = info.containers.Replace(container => !Containers.ContainersAreEqual(container, closedContainer, true, true)
                        ? container
                        : replacement);
                }
                int previousCount = info.containers.Count;
                info.containers = Containers.RemoveInvalidConditions(info.containers, context);
                if (info.containers.Count != previousCount && expr is IArrayIndexerExpression)
                {
                    // when dropping conditionals, we need to show that if the indices were valid inside the conditionals, they remain valid outside the conditionals.
                    // This is automatically true if the indices match the indexVars.
                    expr = GetPrefixIndexedByIndexVars(expr);
                }
                usageInfo.localInfos[expr] = info;
            }
            else
            {
                info.Add(localInfo);
            }
            info.appearsInNestedLoop = true;
            return(info);
        }