summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-30 19:09:16 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-30 19:09:16 +0000
commit16eb62608bbec4781621b67550d3c2ebf9c00ff8 (patch)
treedc60b07e6caa3336a9149ed5cd58c8900b213742
parentd1badbce0b40b1e46dc1ea479aa1f0de0961b381 (diff)
downloadpp2cc-16eb62608bbec4781621b67550d3c2ebf9c00ff8.tar.gz
Support for evil goto and labels (debugging aid!!!)
-rwxr-xr-xpp2cc.py44
1 files changed, 44 insertions, 0 deletions
diff --git a/pp2cc.py b/pp2cc.py
index ca50191..78ce05d 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -289,10 +289,15 @@ class LinkedNode(object):
if defined_names is None:
raise RuntimeError("No object found for storing variables")
self.variables = Variables(defined_names, parent_variables)
+ # Identifiers which are in use (think of variables and labels)
+ self.defined_names = defined_names
if not self.variables:
raise RuntimeError("No variables object found")
if level_increment:
self.incrementLevel()
+ # labels are limited to function contexts
+ if self.type == "FuncDef":
+ self.goto_labels = {}
def handle_post_lines(self, lines):
"""Add post-increment lines to the lines list and clear the queue"""
lines += self.post_lines
@@ -372,6 +377,32 @@ class LinkedNode(object):
if self.parent:
return self.parent.getContinueNode()
return None
+ def setLabel(self, label_name):
+ """Sets the label for this node"""
+ if self.parent:
+ function = self.parent.getFunctionNode()
+ if not self.parent or not function:
+ raise RuntimeError("Labels are only allowed in functions")
+ if label_name in function.goto_labels:
+ raise RuntimeError("Duplicate label '{}'".format(label_name))
+
+ label_asm = "lbl_" + label_name
+ i = 0
+ while label_asm in self.defined_names:
+ label_asm = "lbl_" + label_name + str(i)
+ i += 1
+
+ function.goto_labels[label_name] = label_asm
+ def lookupLabel(self, label_name):
+ """Returns the label name as it appears in assembly for label_name"""
+ # get the nearest function for this node
+ if self.parent:
+ function = self.parent.getFunctionNode()
+ if not self.parent or not function:
+ raise RuntimeError("Labels are only allowed in functions")
+ if label_name in function.goto_labels:
+ return function.goto_labels[label_name]
+ raise RuntimeError("Label '{}' used but not defined".format(name))
class Function(object):
def __init__(self, node):
@@ -1301,6 +1332,19 @@ class Parse(object):
lines.append(self.asm.binary_op("LOAD", name_reg,
"[" + name_reg + "+" + index_reg + "]"))
return lines
+ def parseLabel(self, linked_node):
+ lines = []
+ label_name = linked_node.node.name
+ linked_node.setLabel(label_name)
+ lines.append(self.asm.noop(label_name))
+ lines += self.parseStatement(linked_node.node.stmt, linked_node)
+ return lines
+ def parseGoto(self, linked_node):
+ """Provides support for the infinitely abused goto statement. Use it
+ for debugging only!
+ """
+ label_name = linked_node.lookupLabel(linked_node.node.name)
+ return [self.asm.branch_op("BRA", label_name)]
def parseStatement(self, node, parent_linked_node, level_increment=False):
linked_node = LinkedNode(node, parent_linked_node, level_increment=level_increment)
self.asm.level = linked_node.level