예제 #1
0
        public List <BaseBlock> sort()
        {
            var sorted = new Sorter(scopeBlock, scopeBlock.BaseBlocks, false).sort();

            return(new ForwardScanOrder(scopeBlock, sorted).fix());
        }
예제 #2
0
            void Visit(BlockInfo info)
            {
                // This method used to be recursive but to prevent stack overflows,
                // it's not recursive anymore.

                var state = new VisitState(info);

recursive_call:
                if (state.Info.baseBlock == firstBlock)
                {
                    throw new ApplicationException("Can't visit firstBlock");
                }
                stack.Push(state.Info);
                state.Info.onStack   = true;
                state.Info.dfsNumber = dfsNumber;
                state.Info.low       = dfsNumber;
                dfsNumber++;

                state.Targets     = GetTargets(state.Info.baseBlock);
                state.TargetIndex = 0;
return_to_caller:
                for (; state.TargetIndex < state.Targets.Count; state.TargetIndex++)
                {
                    state.TargetInfo = GetInfo(state.Targets[state.TargetIndex]);
                    if (state.TargetInfo == null)
                    {
                        continue;
                    }
                    if (state.TargetInfo.baseBlock == firstBlock)
                    {
                        continue;
                    }

                    if (!state.TargetInfo.Visited())
                    {
                        visitStateStack.Push(state);
                        state = new VisitState(state.TargetInfo);
                        goto recursive_call;
                    }
                    else if (state.TargetInfo.onStack)
                    {
                        state.Info.low = Math.Min(state.Info.low, state.TargetInfo.dfsNumber);
                    }
                }

                if (state.Info.low != state.Info.dfsNumber)
                {
                    goto return_from_method;
                }
                var sccBlocks = new List <BaseBlock>();

                while (true)
                {
                    var poppedInfo = stack.Pop();
                    poppedInfo.onStack = false;
                    sccBlocks.Add(poppedInfo.baseBlock);
                    if (ReferenceEquals(state.Info, poppedInfo))
                    {
                        break;
                    }
                }
                if (sccBlocks.Count > 1)
                {
                    sccBlocks.Reverse();
                    var result = new Sorter(scopeBlock, sccBlocks, true).Sort();
                    SortLoopBlock(result);
                    sorted.InsertRange(0, result);
                }
                else
                {
                    sorted.Insert(0, sccBlocks[0]);
                }

return_from_method:
                if (visitStateStack.Count == 0)
                {
                    return;
                }
                state          = visitStateStack.Pop();
                state.Info.low = Math.Min(state.Info.low, state.TargetInfo.low);
                state.TargetIndex++;
                goto return_to_caller;
            }
예제 #3
0
            void visit(BlockInfo info)
            {
                if (info.baseBlock == firstBlock)
                {
                    throw new ApplicationException("Can't visit firstBlock");
                }
                stack.Push(info);
                info.onStack   = true;
                info.dfsNumber = dfsNumber;
                info.low       = dfsNumber;
                dfsNumber++;

                foreach (var tmp in getTargets(info.baseBlock))
                {
                    var targetInfo = getInfo(tmp);
                    if (targetInfo == null)
                    {
                        continue;
                    }
                    if (targetInfo.baseBlock == firstBlock)
                    {
                        continue;
                    }

                    if (!targetInfo.visited())
                    {
                        visit(targetInfo);
                        info.low = Math.Min(info.low, targetInfo.low);
                    }
                    else if (targetInfo.onStack)
                    {
                        info.low = Math.Min(info.low, targetInfo.dfsNumber);
                    }
                }

                if (info.low != info.dfsNumber)
                {
                    return;
                }
                var sccBlocks = new List <BaseBlock>();

                while (true)
                {
                    var poppedInfo = stack.Pop();
                    poppedInfo.onStack = false;
                    sccBlocks.Add(poppedInfo.baseBlock);
                    if (ReferenceEquals(info, poppedInfo))
                    {
                        break;
                    }
                }
                if (sccBlocks.Count > 1)
                {
                    sccBlocks.Reverse();
                    var result = new Sorter(scopeBlock, sccBlocks, true).sort();
                    sortLoopBlock(result);
                    sorted.InsertRange(0, result);
                }
                else
                {
                    sorted.Insert(0, sccBlocks[0]);
                }
            }