From 9b35c5c68a7242d9633e298ec777edb7ae90746b Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Mon, 28 Nov 2011 08:58:56 +0000 Subject: Differentiate between statements and expressions --- pp2cc.py | 127 +++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 71 insertions(+), 56 deletions(-) (limited to 'pp2cc.py') diff --git a/pp2cc.py b/pp2cc.py index 8e5c46d..79c2e3e 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -445,10 +445,10 @@ class Parse(object): result_true = self.asm.binary_op("LOAD", reg_result, 1, label=lbl_true) result_false = self.asm.binary_op("LOAD", reg_result, 0, label=lbl_false) - lines = self.parseStatement(node.left, linked_node, level_increment=True) + lines = self.parseExpression(node.left, linked_node, level_increment=True) lines.append(branch_early) - lines += self.parseStatement(node.right, linked_node, level_increment=True) + lines += self.parseExpression(node.right, linked_node, level_increment=True) lines.append(branch_early) # fix indentation self.asm.level = linked_node.level @@ -481,7 +481,7 @@ class Parse(object): raise RuntimeError("Binary op is not implemented yet: " + node.op) # process the first operand, the result is likely in R0 or R1 - ops_first = self.parseStatement(node.left, linked_node, level_increment=True) + ops_first = self.parseExpression(node.left, linked_node, level_increment=True) assert len(ops_first), "Empty operand for binary operation (first part)" lines += ops_first @@ -496,7 +496,7 @@ class Parse(object): else: lines.append(self.asm.push(reg_first)) - ops_second = self.parseStatement(node.right, linked_node, level_increment=True) + ops_second = self.parseExpression(node.right, linked_node, level_increment=True) assert len(ops_second), "Empty operand for binary operation (second part)" lines += ops_second @@ -580,7 +580,7 @@ class Parse(object): """ op = linked_node.node.op # first fetch the operand - lines = self.parseStatement(linked_node.node.expr, linked_node) + lines = self.parseExpression(linked_node.node.expr, linked_node) # determine the register in which the result is stored reg = self.registers.find_register(lines, fatal=True) @@ -631,18 +631,18 @@ class Parse(object): lbl_el = self.uniqLbl("el") # else lbl_end = self.uniqLbl("fi") # endif - lines = self.parseStatement(node.cond, linked_node) + lines = self.parseExpression(node.cond, linked_node) lines.append(self.asm.branch_op("BEQ", lbl_el)) # if true... - then_block = self.parseStatement(node.iftrue, linked_node) + then_block = self.parseExpression(node.iftrue, linked_node) # use a single register for the result, using the one of expr_true result_reg = self.registers.find_register(then_block, fatal=True) lines += then_block lines.append(self.asm.branch_op("BRA", lbl_end)) # else... - else_block = self.parseStatement(node.iffalse, linked_node) + else_block = self.parseExpression(node.iffalse, linked_node) assert len(else_block), "Else block is empty" result_reg_else = self.registers.find_register(else_block, fatal=True) # for consistency with the result of expr_true @@ -707,7 +707,7 @@ class Parse(object): linked_node.incrementLevel() node = linked_node.node - lines = self.parseStatement(node.cond, linked_node) + lines = self.parseExpression(node.cond, linked_node) branch_op = "BEQ" then_block = self.parseStatement(node.iftrue, linked_node) if node.iffalse: @@ -761,7 +761,7 @@ class Parse(object): return_value = linked_node.node.expr if return_value: - lines = self.parseStatement(return_value, linked_node) + lines = self.parseExpression(return_value, linked_node) else: lines = [] if return_value: @@ -782,7 +782,7 @@ class Parse(object): return [self.asm.branch_op("BRS", self.functionLabel(funcname))] def parseCast(self, linked_node): self.logger.warning("Found a type cast, but these are unsupported.", linked_node=linked_node) - return self.parseStatement(linked_node.node.expr, linked_node) + return self.parseExpression(linked_node.node.expr, linked_node) def parseDoWhile(self, linked_node): node = linked_node.node lbl_do = self.uniqLbl("do") @@ -799,7 +799,7 @@ class Parse(object): # while (...) # used for supporting continue lines.append(self.asm.noop(lbl_cond)) - lines += self.parseStatement(node.cond, linked_node) + lines += self.parseExpression(node.cond, linked_node) lines.append(self.asm.branch_op("BNE", lbl_do)) # used for supporting break lines.append(self.asm.noop(lbl_end)) @@ -814,7 +814,7 @@ class Parse(object): # while ( lines = [self.asm.noop(lbl_while)] # .. - lines += self.parseStatement(node.cond, linked_node) + lines += self.parseExpression(node.cond, linked_node) lines.append(self.asm.branch_op("BEQ", lbl_while_end)) # ){.. lines += self.parseStatement(node.stmt, linked_node) @@ -843,17 +843,17 @@ class Parse(object): linked_node.setContinue(lbl_for) if node.init: # init; - lines += self.parseStatement(node.init, linked_node) + lines += self.parseExpression(node.init, linked_node) # while ( lines.append(self.asm.noop(lbl_for)) if node.cond: # if no condition, it's should evaluate to true - lines += self.parseStatement(node.cond, linked_node) + lines += self.parseExpression(node.cond, linked_node) lines.append(self.asm.branch_op("BEQ", lbl_for_end)) # ){ 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 += self.parseExpression(node.next, linked_node) lines.append(self.asm.branch_op("BRA", lbl_for)) # } @@ -862,7 +862,7 @@ class Parse(object): def parseExprList(self, linked_node): lines = [] for expr in linked_node.node.exprs: - lines += self.parseStatement(expr, linked_node) + lines += self.parseExpression(expr, linked_node) return lines def parseAssignment(self, linked_node): lines = [] @@ -879,7 +879,7 @@ class Parse(object): raise RuntimeError("Assignment to undefined variable '{}'".format(name)) var_name = self.nameToVar(node.lvalue.name) - expr_result = self.parseStatement(node.rvalue, linked_node) + expr_result = self.parseExpression(node.rvalue, linked_node) lines += expr_result result_reg = self.registers.find_register(expr_result) if node.op == "=": @@ -897,7 +897,7 @@ class Parse(object): # if the declaration also has a definition if linked_node.node.init: var_name = self.nameToVar(varname) - init_val = self.parseStatement(linked_node.node.init, linked_node) + init_val = self.parseExpression(linked_node.node.init, linked_node) result_reg = self.registers.find_register(init_val) init_val.append(self.asm.binary_op("STOR", result_reg, "[GB+" + var_name + "]")) # if global context (i.e. not in a function) @@ -923,49 +923,64 @@ class Parse(object): linked_node = LinkedNode(node, parent_linked_node, level_increment=level_increment) self.asm.level = linked_node.level lines = [] - if (isinstance(node, c_ast.FuncDecl) or - isinstance(node, c_ast.ArrayDecl) or - isinstance(node, c_ast.ArrayRef) or - isinstance(node, c_ast.Case) or - isinstance(node, c_ast.CompoundLiteral) or - isinstance(node, c_ast.DeclList) or - isinstance(node, c_ast.Default) or - isinstance(node, c_ast.EllipsisParam) or - isinstance(node, c_ast.Enum) or - isinstance(node, c_ast.Enumerator) or - isinstance(node, c_ast.EnumeratorList) or - isinstance(node, c_ast.FuncDecl) or - isinstance(node, c_ast.Goto) or - isinstance(node, c_ast.IdentifierType) or - isinstance(node, c_ast.Label) or - isinstance(node, c_ast.NamedInitializer) or - isinstance(node, c_ast.ParamList) or - isinstance(node, c_ast.PtrDecl) or - isinstance(node, c_ast.Struct) or - isinstance(node, c_ast.StructRef) or - isinstance(node, c_ast.Switch) or - isinstance(node, c_ast.TypeDecl) or - isinstance(node, c_ast.Typedef) or - isinstance(node, c_ast.Typename) or - isinstance(node, c_ast.Union)): - raise RuntimeError("Not implemented for type " + repr(node)) + + for entry in ("Compound", "If", "Return", "DoWhile", "While", "For", + "Decl", "FuncDef", "Break", "Continue", "EmptyStatement"): + if isinstance(node, getattr(c_ast, entry)): + lines += getattr(self, "parse" + entry)(linked_node) + break else: - for entry in ("Compound", "BinaryOp", "If", "Constant", "ID", - "Return", "FuncCall", "UnaryOp", "Cast", - "TernaryOp", "DoWhile", "While", "For", "ExprList", - "Assignment", "Decl", "FuncDef", "Break", - "Continue", "EmptyStatement"): - if isinstance(node, getattr(c_ast, entry)): - lines += getattr(self, "parse" + entry)(linked_node) - break + if (isinstance(node, c_ast.FuncDecl) or + isinstance(node, c_ast.ArrayDecl) or + isinstance(node, c_ast.Case) or + isinstance(node, c_ast.DeclList) or + isinstance(node, c_ast.Default) or + isinstance(node, c_ast.EllipsisParam) or# (int a, ...) + isinstance(node, c_ast.Enum) or # enum type + isinstance(node, c_ast.Enumerator) or # enum value + isinstance(node, c_ast.EnumeratorList) or # list of enum values + isinstance(node, c_ast.FuncDecl) or + isinstance(node, c_ast.Goto) or + isinstance(node, c_ast.Label) or + isinstance(node, c_ast.ParamList) or + isinstance(node, c_ast.PtrDecl) or + isinstance(node, c_ast.Struct) or + isinstance(node, c_ast.TypeDecl) or#? + isinstance(node, c_ast.Typedef) or#? + isinstance(node, c_ast.Switch) or + isinstance(node, c_ast.Union)): + raise RuntimeError("Not implemented for type " + repr(node)) else: - raise RuntimeError("Not implemented and unknown: " + repr(node)) + lines += self.parseExpression(node, parent_linked_node, level_increment) return lines # currently, there is no difference between an expression and statement. This might # change in the future - def parseExpression(self, node, parent): - pass + def parseExpression(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 + lines = [] + + for entry in ("ID", "Constant", "UnaryOp", "FuncCall", "Cast", + "BinaryOp", "TernaryOp", "Assignment", "ExprList"): + if isinstance(node, getattr(c_ast, entry)): + lines += getattr(self, "parse" + entry)(linked_node) + break + else: + for entry in ("Compound", "If", "Return", "DoWhile", "While", "For", + "Decl", "FuncDef", "Break", "Continue", "EmptyStatement"): + if isinstance(node, getattr(c_ast, entry)): + raise RuntimeError("A statement is used in expression context") + if (isinstance(node, c_ast.ArrayRef) or# + isinstance(node, c_ast.CompoundLiteral) or# won't be supported + isinstance(node, c_ast.IdentifierType) or#attribute? remove + isinstance(node, c_ast.NamedInitializer) or#attribute, remove + isinstance(node, c_ast.StructRef) or# + isinstance(node, c_ast.Typename)): + raise RuntimeError("Not implemented for expression type " + repr(node)) + else: + raise RuntimeError("Not implemented expression and unknown type: " + repr(node)) + return lines if __name__ == "__main__": settings = { -- cgit v1.2.1