public void UnionWith(SubstitutionCollection other)
 {
     Substitutions.AddRange(other.Substitutions);
     NextRelation = (NextRelation, other.NextRelation) switch
     {
         (NullLogicalValue _, var v) => v,
         (var v, NullLogicalValue _) => v,
         (var v1, var v2) => new LogicalDisjunctionValue(v1, v2)
     };
 }
Exemple #2
0
        private List <Path> GeneratePaths(
            IBlock currentBlock,
            ILogicalValue currentRelation,
            Path currentPath,
            HashSet <IBlock> cutSet,
            HashSet <IBlock> visited)
        {
            var           paths = new List <Path>();
            var           substitutionCollection = new SubstitutionCollection(Enumerable.Empty <ValueSubstitution>(), new NullLogicalValue());
            List <IBlock> successors;

            while (true)
            {
                visited.Add(currentBlock);
                substitutionCollection.UnionWith(substitutionGenerator.GenerateSubstitutions(currentBlock));

                successors = currentBlock.GetSuccessors().ToList();

                if (successors.Count != 1)
                {
                    break;
                }

                currentBlock = successors[0];
            }

            currentPath = currentPath.Combine(new Path(currentRelation, substitutionCollection.Substitutions));

            // If we reached the end of the CFG, just return the current paths.
            if (successors.Count == 0)
            {
                paths.Add(new Path(currentRelation, substitutionCollection.Substitutions));
                return(paths);
            }

            // If we have an unusual number of successors, throw an exception.
            if (successors.Count != 2)
            {
                throw new InvalidOperationException(
                          $"Expected a block to have 2 successors, found {successors.Count}.");
            }

            // If the next relation is unknown, throw an exception.
            if (substitutionCollection.NextRelation is NullLogicalValue)
            {
                throw new InvalidOperationException(
                          "A block had successors, but the next relation was unknown.");
            }

            Path nextPath;

            if (cutSet.Contains(currentBlock))
            {
                // If we reached a cut point, end the current path.
                nextPath = new Path();
                paths.Add(currentPath);
            }
            else
            {
                // Otherwise, extend the current path.
                nextPath = currentPath;
            }

            if (!visited.Contains(successors[0]))
            {
                paths.AddRange(GeneratePaths(successors[0], substitutionCollection.NextRelation, nextPath, cutSet, visited));
            }

            if (!visited.Contains(successors[1]))
            {
                paths.AddRange(GeneratePaths(successors[1], new LogicalNotValue(substitutionCollection.NextRelation), nextPath, cutSet, visited));
            }

            return(paths);
        }