public List <BaseBlock> sort() { var sorted = new Sorter(scopeBlock, scopeBlock.BaseBlocks, false).sort(); return(new ForwardScanOrder(scopeBlock, sorted).fix()); }
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; }
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]); } }