summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-28 08:14:24 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-28 08:14:24 +0000
commiteadd65d83414bb11bf1d1a821a783b716e5f0d1b (patch)
treee74c8d77ee6fed3f6f5b9488750ed743a9d5b5c7
parente209e62bf26640915f6a7b4095fd9bfa89a7cc43 (diff)
downloadpp2cc-eadd65d83414bb11bf1d1a821a783b716e5f0d1b.tar.gz
Fix bug in continue keyword in for-loop with a next expression which was never executed
-rwxr-xr-xpp2cc.py46
1 files changed, 34 insertions, 12 deletions
diff --git a/pp2cc.py b/pp2cc.py
index a3597aa..8e5c46d 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -196,22 +196,36 @@ class LinkedNode(object):
if hasattr(self.node, "coord"):
return self.node.coord
return "Unknown"
- def setLoop(self, break_label, continue_label):
- """Marks this node as a loop with the labels to continue after a jump
+ def setBreak(self, break_label):
+ """Marks this node as a loop or switch by setting the label for break
Keywords list:
break_label -- The label to continue when using the break keyword
- continue_label -- The label to continue when using the continue keyword
"""
self.break_label = break_label
+ def setContinue(self, continue_label):
+ """Marks this node as a loop by setting the label for continue
+
+ Keywords list:
+ continue_label -- The label to continue when using the continue keyword
+ """
self.continue_label = continue_label
- def getLoopNode(self):
- # continue_label is implied with break_label
+ def getBreakNode(self):
+ """Returns the label to the end of the nearest switch statement or for
+ loop"""
if self.break_label is not None:
return self
if self.parent:
assert isinstance(self.parent, LinkedNode), "parent is not a LinkedNode!"
- return self.parent.getLoopNode()
+ return self.parent.getBreakNode()
+ return None
+ def getContinueNode(self):
+ """Returns the label to the label to continue a loop"""
+ if self.continue_label is not None:
+ return self
+ if self.parent:
+ assert isinstance(self.parent, LinkedNode), "parent is not a LinkedNode!"
+ return self.parent.getContinueNode()
return None
class Function(object):
@@ -775,7 +789,8 @@ class Parse(object):
# used for supporting continue/break
lbl_cond = self.uniqLbl("doCond")
lbl_end = self.uniqLbl("doEnd")
- linked_node.setLoop(lbl_end, lbl_doCond)
+ linked_node.setBreak(lbl_end)
+ linked_node.setContinue(lbl_doCond)
# provides a way to redo the loop
lines = [self.asm.noop(lbl_do)]
@@ -794,7 +809,8 @@ class Parse(object):
lbl_while = self.uniqLbl("while")
lbl_while_end = self.uniqLbl("whileEnd")
# used for supporting break/continue
- linked_node.setLoop(lbl_while_end, lbl_while)
+ linked_node.setBreak(lbl_while_end)
+ linked_node.setContinue(lbl_while)
# while (
lines = [self.asm.noop(lbl_while)]
# ..
@@ -819,7 +835,12 @@ class Parse(object):
lbl_for = self.uniqLbl("for")
lbl_for_end = self.uniqLbl("forEnd")
# used for supporting break/continue
- linked_node.setLoop(lbl_for_end, lbl_for)
+ linked_node.setBreak(lbl_for_end)
+ if node.next:
+ lbl_cont = self.uniqLbl("forNext")
+ linked_node.setContinue(lbl_cont)
+ else:
+ linked_node.setContinue(lbl_for)
if node.init: # init;
lines += self.parseStatement(node.init, linked_node)
@@ -831,6 +852,7 @@ class Parse(object):
# ){ body;
lines += self.parseStatement(node.stmt, linked_node)
if node.next: # next;
+ lines.append(self.asm.noop(lbl_cont))
lines += self.parseStatement(node.next, linked_node)
lines.append(self.asm.branch_op("BRA", lbl_for))
@@ -885,12 +907,12 @@ class Parse(object):
lines += init_val
return lines
def parseBreak(self, linked_node):
- loop_node = linked_node.getLoopNode()
+ loop_node = linked_node.getBreakNode()
if not loop_node:
- raise RuntimeError("break not in a loop")
+ raise RuntimeError("break not in a loop or switch")
return [self.asm.branch_op("BRA", loop_node.break_label)]
def parseContinue(self, linked_node):
- loop_node = linked_node.getLoopNode()
+ loop_node = linked_node.getContinueNode()
if not loop_node:
raise RuntimeError("continue not in a loop")
return [self.asm.branch_op("BRA", loop_node.continue_label)]