Beispiel #1
0
 public AtomicPathPrefix(AtomicSpec i_atomicSpec, ArmadaPC pc)
 {
     atomicSpec   = i_atomicSpec;
     nextRoutines = new List <NextRoutine>();
     tau          = false;
     startPC      = endPC = pc;
     startType    = endType = atomicSpec.GetPCAtomicType(pc);
     extensions   = new List <AtomicPathPrefix>();
     path         = null;
 }
Beispiel #2
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}";
                }
            }
        }