summaryrefslogtreecommitdiff
path: root/pp2cc.py
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-28 08:58:56 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-28 08:58:56 +0000
commit9b35c5c68a7242d9633e298ec777edb7ae90746b (patch)
tree815498cd800dc18f6b3aeb43ec039ce4ef9f41c8 /pp2cc.py
parenteadd65d83414bb11bf1d1a821a783b716e5f0d1b (diff)
downloadpp2cc-9b35c5c68a7242d9633e298ec777edb7ae90746b.tar.gz
Differentiate between statements and expressions
Diffstat (limited to 'pp2cc.py')
-rwxr-xr-xpp2cc.py127
1 files changed, 71 insertions, 56 deletions
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 = {