Ejemplo n.º 1
0
        public sealed override object VisitCFG(ControlFlowGraph x)
        {
            OnVisitCFG(x);

            ExploredColor  = x.NewColor();
            ChangedColor   = x.NewColor();
            RepairedColor  = x.NewColor();
            _updatedBlocks = null;

            // Traverse the whole graph and possibly obtain new versions of start and exit
            var updatedStart = (StartBlock)Accept(x.Start);
            var updatedExit  = TryGetNewVersion(x.Exit);

            // Assume that yields and unreachable blocks stay the same
            var yields            = x.Yields;
            var unreachableBlocks = x.UnreachableBlocks;

            // Fix the structure of the graph if any changes were performed
            if (_updatedBlocks != null)
            {
                Debug.Assert(updatedStart != x.Start);

                // Rescan and repair nodes and edges if any blocks were modified
                var repairer = new GraphRepairer(this);
                updatedStart = (StartBlock)updatedStart.Accept(repairer);
                updatedExit  = TryGetNewVersion(x.Exit);

                // Handle newly unreachable blocks
                var newlyUnreachableBlocks =
                    _possiblyUnreachableBlocks?.Where(b => !IsExplored(b)).ToList()  // Confirm that they are unexplored
                    ?? Enumerable.Empty <BoundBlock>();
                if (newlyUnreachableBlocks.Any())
                {
                    // Scan all the newly unreachable blocks (for yields, declarations,...)
                    var unreachableProcessor = new UnreachableProcessor(this, ExploredColor);
                    newlyUnreachableBlocks.ForEach(b => b.Accept(unreachableProcessor));

                    // Remove the discovered yields from the next CFG version
                    if (unreachableProcessor.Yields != null)
                    {
                        yields = yields.RemoveRange(unreachableProcessor.Yields);
                    }
                }

                // Repair all the unreachable blocks so that they reference the updated versions of the blocks
                // (enables to properly produce reachability diagnostics)
                unreachableBlocks =
                    unreachableBlocks.Concat(newlyUnreachableBlocks)
                    .Select(b => (BoundBlock)b.Accept(repairer))
                    .ToImmutableArray();
            }

            // Create a new CFG from the new versions of blocks and edges (expressions and statements are reused where unchanged)
            return(x.Update(
                       updatedStart,
                       updatedExit,
                       x.Labels,    // Keep all the labels, they are here only for the diagnostic purposes
                       yields,
                       unreachableBlocks));
        }
Ejemplo n.º 2
0
        public void TestUnreach2()
        {
            Gramm gr = new Gramm();

            gr.Terms.Add("a");
            gr.Terms.Add("+");

            gr.NonTerms.Add("A");
            gr.NonTerms.Add("B");
            gr.NonTerms.Add("C");
            gr.NonTerms.Add("D");

            gr.St = "B";

            gr.Rules.Add(new Rule("A", new List <string>()
            {
                "a", "A"
            }));
            gr.Rules.Add(new Rule("A", new List <string>()
            {
                "+", "D"
            }));
            gr.Rules.Add(new Rule("B", new List <string>()
            {
                "B", "A"
            }));
            gr.Rules.Add(new Rule("B", new List <string>()
            {
                "A", "B", "+"
            }));
            gr.Rules.Add(new Rule("C", new List <string>()
            {
                "a", "A", "a"
            }));
            gr.Rules.Add(new Rule("C", new List <string>()
            {
                "D", "+", "A"
            }));
            gr.Rules.Add(new Rule("D", new List <string>()
            {
                "B", "C"
            }));
            gr.Rules.Add(new Rule("D", new List <string>()
            {
                "a"
            }));

            Gramm newGr = UnreachableProcessor.RemoveUnreachable(gr);

            Assert.IsTrue(newGr.NonTerms.Contains("A"));
            Assert.IsTrue(newGr.NonTerms.Contains("B"));
            Assert.IsTrue(newGr.NonTerms.Contains("C"));
            Assert.IsTrue(newGr.NonTerms.Contains("D"));

            Assert.AreEqual(8, newGr.Rules.Count);
            Assert.IsNotNull(newGr.Rules.Find(x => x.Left == "C"));
        }