diff options
-rwxr-xr-x | pp2cc.py | 44 |
1 files changed, 44 insertions, 0 deletions
@@ -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 |