changeset 222:c3f1ce8b638f

Fixup of parser
author Windel Bouwman
date Tue, 09 Jul 2013 17:36:31 +0200
parents 848c4b15fd0b
children 85c8105318e7
files python/c3/analyse.py python/c3/astnodes.py python/c3/codegenerator.py python/c3/parser.py python/c3/typecheck.py python/c3/visitor.py python/codegenarm.py python/ir/instruction.py
diffstat 8 files changed, 78 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/python/c3/analyse.py	Mon Jul 08 22:21:44 2013 +0200
+++ b/python/c3/analyse.py	Tue Jul 09 17:36:31 2013 +0200
@@ -84,6 +84,8 @@
     def findRefs(self, sym):
         if type(sym) in [Variable, Constant]:
             sym.typ = self.resolveType(sym.typ, sym.scope)
+        elif type(sym) is TypeCast:
+            sym.to_type = self.resolveType(sym.to_type, sym.scope)
         elif type(sym) is VariableUse:
             sym.target = self.resolveDesignator(sym.target, sym.scope)
         elif type(sym) is FunctionCall:
--- a/python/c3/astnodes.py	Mon Jul 08 22:21:44 2013 +0200
+++ b/python/c3/astnodes.py	Tue Jul 09 17:36:31 2013 +0200
@@ -74,8 +74,12 @@
    def __repr__(self):
       return 'Named type {0} of type {1}'.format(self.name, self.typ)
 
-#class TypeCast(Node):
-#    def __init__(self, 
+class TypeCast(Node):
+    def __init__(self, to_type, x):
+        self.to_type = to_type
+        self.a = x
+    def __repr__(self):
+        return 'TYPECAST'
 
 # Variables, parameters, local variables, constants:
 class Symbol(Node):
@@ -190,7 +194,7 @@
    def __repr__(self):
       return 'RETURN STATEMENT'
 
-class Assignment(Node):
+class Assignment(Statement):
     def __init__(self, lval, rval, loc):
         assert isinstance(lval, Node)
         assert isinstance(rval, Node)
@@ -202,6 +206,14 @@
     def __repr__(self):
         return 'ASSIGNMENT'
 
+class ExpressionStatement(Statement):
+    def __init__(self, ex, loc):
+        self.ex = ex
+        self.loc = loc
+        assert isinstance(loc, SourceLocation)
+    def __repr__(self):
+        return 'Epression'
+
 class IfStatement(Statement):
    def __init__(self, condition, truestatement, falsestatement, loc):
       self.condition = condition
--- a/python/c3/codegenerator.py	Mon Jul 08 22:21:44 2013 +0200
+++ b/python/c3/codegenerator.py	Tue Jul 09 17:36:31 2013 +0200
@@ -1,6 +1,6 @@
 import ir
 from . import astnodes
-from .scope import boolType
+from .scope import boolType, intType
 from ppci import CompilerError
    
 class CodeGenerator:
@@ -17,11 +17,11 @@
 
     # inner helpers:
     def genModule(self, pkg):
-      # Take care of forward declarations:
-      for s in pkg.innerScope.Functions:
+       # Take care of forward declarations:
+       for s in pkg.innerScope.Functions:
             f = self.builder.newFunction(s.name)
             self.funcMap[s] = f
-      for s in pkg.innerScope:
+       for s in pkg.innerScope:
          if type(s) is astnodes.Variable:
               v = self.builder.newVariable(s.name)
               #self.builder.addIns(ir.Alloc(v))
@@ -50,16 +50,19 @@
             print(s)
 
     def genCode(self, code):
-      if type(code) is astnodes.CompoundStatement:
+        assert isinstance(code, astnodes.Statement)
+        if type(code) is astnodes.CompoundStatement:
             for s in code.statements:
                 self.genCode(s)
-      elif type(code) is astnodes.Assignment:
+        elif type(code) is astnodes.Assignment:
          re = self.genExprCode(code.rval)
          # TODO: Handle pointers
          loc = self.genExprCode(code.lval)
          # determine location of variable
          self.builder.addIns(ir.Store(loc, re))
-      elif type(code) is astnodes.IfStatement:
+        elif type(code) is astnodes.ExpressionStatement:
+            self.genExprCode(code.ex)
+        elif type(code) is astnodes.IfStatement:
          bbtrue = self.builder.newBB()
          bbfalse = self.builder.newBB()
          te = self.builder.newBB()
@@ -71,15 +74,15 @@
          self.genCode(code.falsestatement)
          self.builder.addIns(ir.Branch(te))
          self.builder.setBB(te)
-      elif type(code) is astnodes.EmptyStatement:
+        elif type(code) is astnodes.EmptyStatement:
          pass
-      elif type(code) is astnodes.ReturnStatement:
+        elif type(code) is astnodes.ReturnStatement:
          if code.expr:
             re = self.genExprCode(code.expr)
             self.builder.addIns(ir.Return(re))
          else:
             self.builder.addIns(ir.Return())
-      elif type(code) is astnodes.WhileStatement:
+        elif type(code) is astnodes.WhileStatement:
          bbdo = self.builder.newBB()
          bbtest = self.builder.newBB()
          te = self.builder.newBB()
@@ -90,7 +93,7 @@
          self.genCode(code.statement)
          self.builder.addIns(ir.Branch(bbtest))
          self.builder.setBB(te)
-      else:
+        else:
          print('Unknown stmt:', code)
     def genCondCode(self, expr, bbtrue, bbfalse):
       # Implement sequential logical operators
@@ -138,12 +141,18 @@
             # TODO
             return tmp
       elif type(expr) is astnodes.Unop:
+         ra = self.genExprCode(expr.a)
          if expr.op == '&':
             # Address of operator
-            ra = self.genExprCode(expr.a)
             tmp = self.builder.newTmp('addr')
             return tmp
             #self.builder.addIns(ins)
+         elif expr.op == '*':
+            # dereference pointer type:
+            tmp = self.builder.newTmp('deref')
+            ins = ir.Load(ra, tmp)
+            self.builder.addIns(ins)
+            return tmp
          else:
             print('Unknown {0}'.format(expr))
       elif type(expr) is astnodes.Constant:
@@ -161,6 +170,15 @@
          ins = ir.ImmLoad(tmp, expr.val)
          self.builder.addIns(ins)
          return tmp
+      elif type(expr) is astnodes.TypeCast:
+            ar = self.genExprCode(expr.a)
+            if isinstance(expr.to_type, astnodes.PointerType):
+                if expr.a.typ is intType:
+                    return ar
+                elif isinstance(expr.a.typ, astnodes.PointerType):
+                    return ar
+                else:
+                    raise Exception()
       elif type(expr) is astnodes.FunctionCall:
          tmp = self.builder.newTmp("res")
          args = []
--- a/python/c3/parser.py	Mon Jul 08 22:21:44 2013 +0200
+++ b/python/c3/parser.py	Tue Jul 09 17:36:31 2013 +0200
@@ -235,7 +235,7 @@
             rhs = self.Expression()
             return astnodes.Assignment(x, rhs, loc)
         else:
-            return x
+            return astnodes.ExpressionStatement(x, x.loc)
 
     # Expression section:
     # We not implement these C constructs:
@@ -302,20 +302,16 @@
     # Domain of unary expressions:
 
     def CastExpression(self):
-        # TODO: cast conflicts with '(' expr ')', so introduce extra keyword 'cast'
+        # type cast conflicts with '(' expr ')', so introduce extra keyword 'cast'
         if self.Peak == 'cast':
             self.Consume('cast')
             self.Consume('<')
-            print('TODO: implement type cast')
             t = self.parseTypeSpec()
-
-            # Type
             self.Consume('>')
             self.Consume('(')
             ce = self.CastExpression()
             self.Consume(')')
-            # TODO: use type spec here
-            return ce 
+            return astnodes.TypeCast(t, ce)
         else:
             return self.UnaryExpression()
         
--- a/python/c3/typecheck.py	Mon Jul 08 22:21:44 2013 +0200
+++ b/python/c3/typecheck.py	Tue Jul 09 17:36:31 2013 +0200
@@ -11,6 +11,13 @@
         return equalTypes(a.ptype, b.ptype)
    return False
 
+def canCast(fromT, toT):
+    if isinstance(fromT, PointerType) and isinstance(toT, PointerType):
+        return True
+    elif fromT is intType and isinstance(toT, PointerType):
+        return True
+    return False
+
 class TypeChecker:
     def __init__(self, diag):
         self.diag = diag
@@ -118,10 +125,15 @@
          # check initial value type:
          # TODO
          pass
+      elif type(sym) is TypeCast:
+            if canCast(sym.a.typ, sym.to_type):
+                sym.typ = sym.to_type
+            else:
+                self.error('Cannot cast {} to {}'.format(sym.a.typ, sym.to_type))
       elif type(sym) is Constant:
          if not equalTypes(sym.typ, sym.value.typ):
             self.error('Cannot assign {0} to {1}'.format(sym.value.typ, sym.typ), sym.loc)
-      elif type(sym) in [EmptyStatement, CompoundStatement, Package, Function, FunctionType]:
+      elif type(sym) in [EmptyStatement, CompoundStatement, Package, Function, FunctionType, ExpressionStatement]:
          pass
       else:
             raise Exception('Unknown type check {0}'.format(sym))
--- a/python/c3/visitor.py	Mon Jul 08 22:21:44 2013 +0200
+++ b/python/c3/visitor.py	Tue Jul 09 17:36:31 2013 +0200
@@ -43,6 +43,10 @@
          self.do(node.b)
       elif type(node) is Unop:
             self.do(node.a)
+      elif type(node) is ExpressionStatement:
+            self.do(node.ex)
+      elif type(node) is TypeCast:
+            self.do(node.a)
       elif type(node) is Constant:
          self.do(node.value)
       elif type(node) in [EmptyStatement, VariableUse, Variable, Literal, FunctionType]:
--- a/python/codegenarm.py	Mon Jul 08 22:21:44 2013 +0200
+++ b/python/codegenarm.py	Tue Jul 09 17:36:31 2013 +0200
@@ -65,10 +65,10 @@
             lname = ins.target.name + '_ivalue'
             self.emit(arm.ldr_pcrel(arm.r0, ALabel(lname)))
             self.imms.append((lname, ins.value))
-            self.emit(arm.str_sprel(arm.r0, self.addStack(ins.target)))
+            self.emit(arm.str_sprel(arm.r0, arm.MemoryOp(arm.sp, self.addStack(ins.target))))
         elif type(ins) is ir.Store:
             # Load value in r0:
-            self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.value)))
+            self.emit(arm.ldr_sprel(arm.r0, arm.MemoryOp(arm.sp, self.getStack(ins.value))))
             # store in memory:
             self.getGlobal(arm.r1, ins.location)
             self.emit(arm.storeimm5_ins(arm.r0, arm.MemoryOp(arm.r1, 0)))
@@ -76,23 +76,23 @@
             self.getGlobal(arm.r0, ins.location)
             self.emit(arm.loadimm5_ins(arm.r0, arm.MemoryOp(arm.r0, 0)))
             # Store value on stack:
-            self.emit(arm.str_sprel(arm.r0, self.addStack(ins.value)))
+            self.emit(arm.str_sprel(arm.r0, arm.MemoryOp(arm.sp, self.addStack(ins.value))))
         elif type(ins) is ir.BinaryOperator:
             # Load operands:
-            self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.value1)))
-            self.emit(arm.ldr_sprel(arm.r1, self.getStack(ins.value2)))
+            self.emit(arm.ldr_sprel(arm.r0, arm.MemoryOp(arm.sp, self.getStack(ins.value1))))
+            self.emit(arm.ldr_sprel(arm.r1, arm.MemoryOp(arm.sp, self.getStack(ins.value2))))
             # do operation:
             if ins.operation == '+':
                 self.emit(arm.addregs_ins(arm.r0, arm.r0, arm.r1))
             else:
                 print('operation not implemented', ins.operation)
             # Store value back:
-            self.emit(arm.str_sprel(arm.r0, self.addStack(ins.result)))
+            self.emit(arm.str_sprel(arm.r0, arm.MemoryOp(arm.sp, self.addStack(ins.result))))
         elif type(ins) is ir.Return:
             self.emit(arm.pop_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6, arm.r7, arm.pc})))
         elif type(ins) is ir.ConditionalBranch:
-            self.emit(arm.ldr_sprel(arm.r0, self.getStack(ins.a)))
-            self.emit(arm.ldr_sprel(arm.r1, self.getStack(ins.b)))
+            self.emit(arm.ldr_sprel(arm.r0, arm.MemoryOp(arm.sp, self.getStack(ins.a))))
+            self.emit(arm.ldr_sprel(arm.r1, arm.MemoryOp(arm.sp, self.getStack(ins.b))))
             self.emit(arm.cmp_ins(arm.r1, arm.r0))
             tgt_yes = ALabel(ins.lab1.name)
             if ins.cond == '==':
@@ -101,6 +101,8 @@
                 print('TODO', ins.cond)
             tgt_no = ALabel(ins.lab2.name)
             self.emit(arm.jmp_ins(tgt_no))
+        elif type(ins) is ir.Alloc:
+            self.addStack(ins.value)
         else:
             raise CompilerError('IR "{}" not covered'.format(ins))
 
--- a/python/ir/instruction.py	Mon Jul 08 22:21:44 2013 +0200
+++ b/python/ir/instruction.py	Tue Jul 09 17:36:31 2013 +0200
@@ -96,6 +96,7 @@
    """ Allocates space on the stack """
    def __init__(self, value):
       super().__init__()
+      assert isinstance(value, Value)
       self.value = value
       self.addDef(value)
    def __repr__(self):