Fix loops processing

This commit is contained in:
Skylot 2013-04-28 22:46:42 +04:00
parent 533883b5aa
commit a6f6115184
3 changed files with 66 additions and 8 deletions

View File

@ -124,17 +124,17 @@ public class RegionMaker {
IfNode ifnode = null;
LoopRegion loopRegion = null;
Set<BlockNode> exitBlocksSet = loop.getExitNodes();
// set exit blocks scan order by priority
// this can help if we have several exit from loop (after using 'break' or 'return' in loop)
// this can help if loop have several exits (after using 'break' or 'return' in loop)
List<BlockNode> exitBlocks = new ArrayList<BlockNode>(exitBlocksSet.size());
if (exitBlocksSet.contains(loop.getEnd())) {
BlockNode nextStart = BlockUtils.getNextBlock(loopStart);
if (nextStart != null && exitBlocksSet.remove(nextStart))
exitBlocks.add(nextStart);
if (exitBlocksSet.remove(loop.getEnd()))
exitBlocks.add(loop.getEnd());
exitBlocksSet.remove(loop.getEnd());
}
if (exitBlocksSet.contains(loopStart)) {
if (exitBlocksSet.remove(loopStart))
exitBlocks.add(loopStart);
exitBlocksSet.remove(loopStart);
}
exitBlocks.addAll(exitBlocksSet);
exitBlocksSet = null;
@ -189,7 +189,11 @@ public class RegionMaker {
stack.pop();
loopStart.getAttributes().add(loop);
return BlockUtils.getNextBlock(loop.getEnd());
BlockNode next = BlockUtils.getNextBlock(loop.getEnd());
if (!RegionUtils.isRegionContainsBlock(body, next))
return next;
else
return null;
}
stack.push(loopRegion);
@ -372,6 +376,10 @@ public class RegionMaker {
}
}
if (BlockUtils.isBackEdge(block, out)) {
out = null;
}
if (stack.containsExit(elseBlock))
elseBlock = null;

View File

@ -48,6 +48,16 @@ public class BlockUtils {
return ret;
}
public static boolean isBackEdge(BlockNode from, BlockNode to) {
if (from.getCleanSuccessors().contains(to))
return false; // already checked
if (!from.getSuccessors().contains(to))
return false; // not even successor
return true;
}
/**
* Remove exception handlers from block nodes bitset
*/

View File

@ -18,6 +18,10 @@ public class TestCF3 extends AbstractTest {
return 1;
}
private int exc() throws Exception {
return 1;
}
public void testSwitchInLoop() throws Exception {
while (true) {
int n = next();
@ -103,6 +107,31 @@ public class TestCF3 extends AbstractTest {
return foundIt;
}
public String testReturnInLoop(List<String> list) {
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String ver = it.next();
if (ver != null)
return ver;
}
return "error";
}
public String testReturnInLoop2(List<String> list) {
try {
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String ver = it.next();
exc();
if (ver != null)
return ver;
}
} catch (Exception e) {
setEnabled(false);
}
return "error";
}
@Override
public boolean testRun() throws Exception {
setEnabled(false);
@ -117,6 +146,17 @@ public class TestCF3 extends AbstractTest {
new ArrayList<String>(Arrays.asList("a1", "a2")),
new ArrayList<String>(Arrays.asList("a1", "b2"))));
List<String> list1 = Arrays.asList(null, "a", "b");
// TODO this line required to omit generic information because it create List<Object>
// List<String> list2 = Arrays.asList(null, null, null);
assertEquals(testReturnInLoop(list1), "a");
assertEquals(testReturnInLoop2(list1), "a");
// assertEquals(testReturnInLoop(list2), "error");
// assertEquals(testReturnInLoop2(list2), "error");
// assertTrue(testLabeledBreakContinue());
return true;
}