示例#1
0
        ///////////////////////////////////////////////////////////////////////
        // MAKING ATOMIC STEPS
        ///////////////////////////////////////////////////////////////////////

        private void DetermineAtomicPaths()
        {
            allPCs = new List <ArmadaPC>();
            symbols.AllMethods.AppendAllPCs(allPCs);

            var tauPathPrefix = new AtomicPathPrefix(this, new List <NextRoutine> {
                symbols.TauNextRoutine
            }, true, null);

            tauPath     = new AtomicPath(tauPathPrefix);
            atomicPaths = new List <AtomicPath> {
                tauPath
            };
            rootPathPrefixesByPC = new Dictionary <ArmadaPC, List <AtomicPathPrefix> >();

            foreach (var startPC in allPCs)
            {
                rootPathPrefixesByPC[startPC] = new List <AtomicPathPrefix>();
                if (GetPCAtomicType(startPC) != PCAtomicType.Nonyielding)
                {
                    List <NextRoutine> nextRoutines;
                    if (pcToNextRoutines.TryGetValue(startPC, out nextRoutines))
                    {
                        foreach (var nextRoutine in nextRoutines)
                        {
                            var rootAtomicPathPrefix = new AtomicPathPrefix(this, new List <NextRoutine> {
                                nextRoutine
                            }, false, null);
                            rootPathPrefixesByPC[startPC].Add(rootAtomicPathPrefix);
                            PopulateAtomicPathPrefix(rootAtomicPathPrefix);
                        }
                    }
                }
            }
        }
示例#2
0
        ///////////////////////////////////////////////////////////////////////
        // SEARCHING FOR AN ATOMIC PATH
        ///////////////////////////////////////////////////////////////////////

        public AtomicPathPrefix FindAtomicPathPrefixByNextRoutines(List <NextRoutine> nextRoutines)
        {
            if (nextRoutines.Count == 0)
            {
                return(null);
            }

            var firstRoutine = nextRoutines[0];

            if (firstRoutine.nextType == NextType.Tau)
            {
                return(null);
            }

            AtomicPathPrefix pathPrefix = null;

            foreach (var nextRoutine in nextRoutines)
            {
                var children = (pathPrefix == null ? rootPathPrefixesByPC[firstRoutine.startPC] : pathPrefix.Extensions);
                pathPrefix = children.FirstOrDefault(p => p.LastNextRoutine == nextRoutine);
                if (pathPrefix == null)
                {
                    return(null);
                }
            }

            return(pathPrefix);
        }
示例#3
0
        public AtomicPath FindAtomicPathByPCs(List <ArmadaPC> pcs, bool stopping)
        {
            if (pcs.Count == 0)
            {
                return(null);
            }

            AtomicPathPrefix pathPrefix = null;

            for (var i = 1; i < pcs.Count; ++i)
            {
                var pc           = pcs[i];
                var children     = (i == 1) ? rootPathPrefixesByPC[pcs[0]] : pathPrefix.Extensions;
                var findStopping = stopping && (i == pcs.Count - 1);
                if (pc == null)
                {
                    pathPrefix = children.FirstOrDefault(p => p.LastNextRoutine.endPC == null && p.Stopping == findStopping);
                }
                else
                {
                    pathPrefix = children.FirstOrDefault(p => pc.Equals(p.LastNextRoutine.endPC) && p.Stopping == findStopping);
                }
                if (pathPrefix == null)
                {
                    return(null);
                }
            }

            return(pathPrefix.PathVal);
        }
示例#4
0
        private void PopulateAtomicPathPrefix(AtomicPathPrefix pathPrefix)
        {
            var currentPC = pathPrefix.EndPC;

            if (pathPrefix.Stopping || currentPC == null || GetPCAtomicType(currentPC) != PCAtomicType.Nonyielding)
            {
                pathPrefix.PathVal = new AtomicPath(pathPrefix);
                atomicPaths.Add(pathPrefix.PathVal);
                return;
            }

            List <NextRoutine> subsequentRoutines;

            if (pcToNextRoutines.TryGetValue(currentPC, out subsequentRoutines))
            {
                foreach (var subsequentRoutine in subsequentRoutines)
                {
                    var childNextRoutines = new List <NextRoutine>(pathPrefix.NextRoutines);
                    childNextRoutines.Add(subsequentRoutine);
                    var childPathPrefix = new AtomicPathPrefix(this, childNextRoutines, false, pathPrefix);
                    PopulateAtomicPathPrefix(childPathPrefix);
                }
            }
        }
示例#5
0
        public AtomicPathPrefix(AtomicSpec i_atomicSpec, List <NextRoutine> i_nextRoutines, bool i_tau, AtomicPathPrefix parent)
        {
            atomicSpec   = i_atomicSpec;
            nextRoutines = new List <NextRoutine>(i_nextRoutines);
            tau          = i_tau;
            startPC      = nextRoutines[0].startPC;
            endPC        = nextRoutines[nextRoutines.Count - 1].endPC;
            startType    = atomicSpec.GetPCAtomicType(startPC);
            endType      = nextRoutines[nextRoutines.Count - 1].Stopping ? PCAtomicType.Stopping : atomicSpec.GetPCAtomicType(endPC);
            extensions   = new List <AtomicPathPrefix>();
            path         = null;

            if (parent != null)
            {
                parent.AddExtension(this);
            }

            if (tau)
            {
                name = "Tau";
            }
            else
            {
                name  = UndefinedBehavior ? "UB_" : "";
                name += $"From_{startPC.methodName}_{startPC.Name}";

                // It's possible for two atomic paths to have the same start
                // and end PCs.  But, every path has to have a distinct name,
                // so we sometimes have to name a path with more than just the
                // start and end PCs.
                //
                // One way for two atomic paths with the same start and end
                // PCs to differ is via returning to different PCs.  For
                // instance, consider the following code:
                //
                //   method {:atomic} A {
                //     S1;
                //   label L:
                //     S2;
                //   }
                //
                //   method B {
                //     atomic {
                //       A();
                //       A();
                //       A();
                //     }
                //   }
                //
                // Here, there are two ways to get from label L to label L:
                // (1) by returning from B's first call to A and then making
                // B's second call to A, and (2) by returning from B's second
                // call to A and then making B's third call to A.  So, to make
                // sure such paths have different names, we include in the
                // name every returned-to PC in a step other than the last one
                // in the path.
                //
                // Another way for two atomic paths with the same start and
                // end PCs to differ is via branch outcomes.  For instance,
                // consider the following code:
                //
                //   atomic {
                //     if P {
                //       S1;
                //     }
                //     S2;
                //   }
                //
                // Here, there are two ways to get from the beginning to the
                // end: via the true branch of the if (passing through
                // statement S1) or via the false branch.  So we distinguish
                // the names of such paths by the branch outcomes.

                bool justBranched = false;
                for (var i = 0; i < nextRoutines.Count; ++i)
                {
                    var nextRoutine = nextRoutines[i];
                    if (i < nextRoutines.Count - 1 && nextRoutine.nextType == NextType.Return)
                    {
                        var returnToPC = nextRoutine.endPC;
                        name        += $"_Via_{returnToPC.methodName}_{returnToPC.Name}";
                        justBranched = false;
                    }

                    bool branchOutcome;
                    if (nextRoutine.TryGetBranchOutcome(out branchOutcome))
                    {
                        if (!justBranched)
                        {
                            name += "_";
                        }
                        name        += (branchOutcome ? "T" : "F");
                        justBranched = true;
                    }
                }

                if (endPC == null)
                {
                    name += "_to_exit";
                }
                else
                {
                    name += $"_To_{endPC.methodName}_{endPC.Name}";
                }
            }
        }
示例#6
0
 public AtomicPath(AtomicPathPrefix i_pathPrefix)
 {
     pathPrefix = i_pathPrefix;
     stopping   = i_pathPrefix.Stopping;
     name       = pathPrefix.Name;
 }
示例#7
0
 public void AddExtension(AtomicPathPrefix other)
 {
     extensions.Add(other);
 }