changeset 228:7f18ed9b6b7e

Removal of emptystatement class
author Windel Bouwman
date Sat, 13 Jul 2013 11:12:24 +0200
parents 82dfe6a32717
children 51d5ed1bd503
files python/c3/astnodes.py python/c3/codegenerator.py python/c3/parser.py python/c3/typecheck.py python/c3/visitor.py python/stm32f4/blink.c3 python/testc3.py
diffstat 7 files changed, 216 insertions(+), 182 deletions(-) [+]
line wrap: on
line diff
--- a/python/c3/astnodes.py	Fri Jul 12 17:42:39 2013 +0200
+++ b/python/c3/astnodes.py	Sat Jul 13 11:12:24 2013 +0200
@@ -32,10 +32,11 @@
 types must be comparable.
 
 There are the following types:
-- base type
-- struct type
-- pointer type
-- typedef type
+- base type -> basic type (built in)
+- struct type -> a composite type that contains a list of named fields 
+            of other types
+- pointer type -> a type that points to some other type
+- typedef type -> a named type indicating another type
 - function type
 """
 
@@ -190,84 +191,89 @@
         return 'BINOP {}'.format(self.op)
 
 class VariableUse(Expression):
-   def __init__(self, target, loc):
-      self.target = target
-      self.loc = loc
-   def __repr__(self):
-      nm = self.target.name if hasattr(self.target, 'name') else ''
-      return 'VAR USE {}'.format(nm)
+    def __init__(self, target, loc):
+        self.target = target
+        self.loc = loc
+    def __repr__(self):
+        nm = self.target
+        return 'VAR USE {}'.format(nm)
 
 class Literal(Expression):
-   def __init__(self, val, loc):
-      self.val = val
-      self.loc = loc
-   def __repr__(self):
-      return 'LITERAL {}'.format(self.val)
+    def __init__(self, val, loc):
+        self.val = val
+        self.loc = loc
+    def __repr__(self):
+        return 'LITERAL {}'.format(self.val)
 
 class FunctionCall(Expression):
-  def __init__(self, proc, args, loc):
-    self.proc = proc
-    self.args = args
-    self.loc = loc
-  def __repr__(self):
-    return 'CALL {0} '.format(self.proc)
+    def __init__(self, proc, args, loc):
+        self.proc = proc
+        self.args = args
+        self.loc = loc
+    def __repr__(self):
+        return 'CALL {0} '.format(self.proc)
 
 # Statements
 class Statement(Node):
-    pass
+    def __init__(self, loc):
+        self.loc = loc
+
 
 class CompoundStatement(Statement):
     def __init__(self, statements):
         self.statements = statements
+        for s in self.statements:
+            assert isinstance(s, Statement)
 
     def __repr__(self):
         return 'COMPOUND STATEMENT'
 
-class EmptyStatement(Statement):
-   def __repr__(self):
-      return 'NOP'
 
 class ReturnStatement(Statement):
-   def __init__(self, expr, loc):
-      self.expr = expr
-      self.loc = loc
-   def __repr__(self):
-      return 'RETURN STATEMENT'
+    def __init__(self, expr, loc):
+        super().__init__(loc)
+        self.expr = expr
+
+    def __repr__(self):
+        return 'RETURN STATEMENT'
 
 class Assignment(Statement):
     def __init__(self, lval, rval, loc):
+        super().__init__(loc)
         assert isinstance(lval, Node)
         assert isinstance(rval, Node)
-        assert isinstance(loc, SourceLocation)
         self.lval = lval
         self.rval = rval
-        self.loc = loc
 
     def __repr__(self):
         return 'ASSIGNMENT'
 
 class ExpressionStatement(Statement):
     def __init__(self, ex, loc):
+        super().__init__(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
-      self.truestatement = truestatement
-      self.falsestatement = falsestatement
-      self.loc = loc
-   def __repr__(self):
-      return 'IF-statement'
+    def __init__(self, condition, truestatement, falsestatement, loc):
+        super().__init__(loc)
+        self.condition = condition
+        self.truestatement = truestatement
+        self.falsestatement = falsestatement
+
+    def __repr__(self):
+        return 'IF-statement'
+
 
 class WhileStatement(Statement):
-   def __init__(self, condition, statement, loc):
-      self.condition = condition
-      self.statement = statement
-      self.loc = loc
-   def __repr__(self):
-      return 'WHILE-statement'
+    def __init__(self, condition, statement, loc):
+        super().__init__(loc)
+        self.condition = condition
+        self.statement = statement
 
+    def __repr__(self):
+        return 'WHILE-statement'
+
--- a/python/c3/codegenerator.py	Fri Jul 12 17:42:39 2013 +0200
+++ b/python/c3/codegenerator.py	Sat Jul 13 11:12:24 2013 +0200
@@ -2,7 +2,7 @@
 from . import astnodes
 from .scope import boolType, intType
 from ppci import CompilerError
-   
+
 class CodeGenerator:
     """ Generates intermediate code from a package """
     def gencode(self, pkg):
@@ -55,91 +55,90 @@
             for s in code.statements:
                 self.genCode(s)
         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))
+            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.ExpressionStatement:
             self.genExprCode(code.ex)
         elif type(code) is astnodes.IfStatement:
-         bbtrue = self.builder.newBB()
-         bbfalse = self.builder.newBB()
-         te = self.builder.newBB()
-         self.genCondCode(code.condition, bbtrue, bbfalse)
-         self.builder.setBB(bbtrue)
-         self.genCode(code.truestatement)
-         self.builder.addIns(ir.Branch(te))
-         self.builder.setBB(bbfalse)
-         self.genCode(code.falsestatement)
-         self.builder.addIns(ir.Branch(te))
-         self.builder.setBB(te)
-        elif type(code) is astnodes.EmptyStatement:
-         pass
+             bbtrue = self.builder.newBB()
+             bbfalse = self.builder.newBB()
+             te = self.builder.newBB()
+             self.genCondCode(code.condition, bbtrue, bbfalse)
+             self.builder.setBB(bbtrue)
+             self.genCode(code.truestatement)
+             self.builder.addIns(ir.Branch(te))
+             self.builder.setBB(bbfalse)
+             if code.falsestatement:
+                 self.genCode(code.falsestatement)
+             self.builder.addIns(ir.Branch(te))
+             self.builder.setBB(te)
         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())
+            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:
-         bbdo = self.builder.newBB()
-         bbtest = self.builder.newBB()
-         te = self.builder.newBB()
-         self.builder.addIns(ir.Branch(bbtest))
-         self.builder.setBB(bbtest)
-         self.genCondCode(code.condition, bbdo, te)
-         self.builder.setBB(bbdo)
-         self.genCode(code.statement)
-         self.builder.addIns(ir.Branch(bbtest))
-         self.builder.setBB(te)
+            bbdo = self.builder.newBB()
+            bbtest = self.builder.newBB()
+            te = self.builder.newBB()
+            self.builder.addIns(ir.Branch(bbtest))
+            self.builder.setBB(bbtest)
+            self.genCondCode(code.condition, bbdo, te)
+            self.builder.setBB(bbdo)
+            self.genCode(code.statement)
+            self.builder.addIns(ir.Branch(bbtest))
+            self.builder.setBB(te)
         else:
-         print('Unknown stmt:', code)
+            print('Unknown stmt:', code)
     def genCondCode(self, expr, bbtrue, bbfalse):
-      # Implement sequential logical operators
-      assert expr.typ == boolType
-      if type(expr) is astnodes.Binop:
-         if expr.op == 'or':
-            l2 = self.builder.newBB()
-            self.genCondCode(expr.a, bbtrue, l2)
-            self.builder.setBB(l2)
-            self.genCondCode(expr.b, bbtrue, bbfalse)
-         elif expr.op == 'and':
-            l2 = self.builder.newBB()
-            self.genCondCode(expr.a, l2, bbfalse)
-            self.builder.setBB(l2)
-            self.genCondCode(expr.b, bbtrue, bbfalse)
-         elif expr.op in ['==', '>', '<']:
-            ta = self.genExprCode(expr.a)
-            tb = self.genExprCode(expr.b)
-            i = ir.ConditionalBranch(ta, expr.op, tb, bbtrue, bbfalse)
-            self.builder.addIns(i)
-         else:
-            raise NotImlementedError('Unknown condition {0}'.format(expr))
-      elif type(expr) is astnodes.Literal:
-         if expr.val:
-            self.builder.addIns(ir.Branch(bbtrue))
-         else:
-            self.builder.addIns(ir.Branch(bbfalse))
-      else:
-         print('Unknown cond', expr)
+        # Implement sequential logical operators
+        assert expr.typ == boolType
+        if type(expr) is astnodes.Binop:
+             if expr.op == 'or':
+                l2 = self.builder.newBB()
+                self.genCondCode(expr.a, bbtrue, l2)
+                self.builder.setBB(l2)
+                self.genCondCode(expr.b, bbtrue, bbfalse)
+             elif expr.op == 'and':
+                l2 = self.builder.newBB()
+                self.genCondCode(expr.a, l2, bbfalse)
+                self.builder.setBB(l2)
+                self.genCondCode(expr.b, bbtrue, bbfalse)
+             elif expr.op in ['==', '>', '<']:
+                ta = self.genExprCode(expr.a)
+                tb = self.genExprCode(expr.b)
+                i = ir.ConditionalBranch(ta, expr.op, tb, bbtrue, bbfalse)
+                self.builder.addIns(i)
+             else:
+                raise NotImlementedError('Unknown condition {0}'.format(expr))
+        elif type(expr) is astnodes.Literal:
+             if expr.val:
+                self.builder.addIns(ir.Branch(bbtrue))
+             else:
+                self.builder.addIns(ir.Branch(bbfalse))
+        else:
+             print('Unknown cond', expr)
     def genExprCode(self, expr):
         if type(expr) is astnodes.Binop:
-         ra = self.genExprCode(expr.a)
-         rb = self.genExprCode(expr.b)
-         ops = ['+', '-', '*', '/', '|', '&']
-         if expr.op in ops:
-            tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', '&':'and'}
-            tmp = self.builder.newTmp(tmpnames[expr.op])
-            op = expr.op
-            ins = ir.BinaryOperator(tmp, op, ra, rb)
-            self.builder.addIns(ins)
-            return tmp
-         else:
-            print('Unknown {0}'.format(expr))
-            tmp = self.builder.newTmp()
-            # TODO
-            return tmp
+             ra = self.genExprCode(expr.a)
+             rb = self.genExprCode(expr.b)
+             ops = ['+', '-', '*', '/', '|', '&']
+             if expr.op in ops:
+                tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', '&':'and'}
+                tmp = self.builder.newTmp(tmpnames[expr.op])
+                op = expr.op
+                ins = ir.BinaryOperator(tmp, op, ra, rb)
+                self.builder.addIns(ins)
+                return tmp
+             else:
+                print('Unknown {0}'.format(expr))
+                tmp = self.builder.newTmp()
+                # TODO
+                return tmp
         elif type(expr) is astnodes.Unop:
             ra = self.genExprCode(expr.a)
             if expr.op == '&':
@@ -186,15 +185,15 @@
                 else:
                     raise Exception()
         elif type(expr) is astnodes.FunctionCall:
-         tmp = self.builder.newTmp("res")
-         args = []
-         for arg in expr.args:
-            ar = self.genExprCode(arg)
-            args.append(ar)
-         fn = self.funcMap[expr.proc]
-         ins = ir.Call(fn, args, tmp)
-         self.builder.addIns(ins)
-         return tmp
+             tmp = self.builder.newTmp("res")
+             args = []
+             for arg in expr.args:
+                ar = self.genExprCode(arg)
+                args.append(ar)
+             fn = self.funcMap[expr.proc]
+             ins = ir.Call(fn, args, tmp)
+             self.builder.addIns(ins)
+             return tmp
         else:
-         raise CompilerError('Unknown expr {}'.format(expr))
+             raise CompilerError('Unknown expr {}'.format(expr))
 
--- a/python/c3/parser.py	Fri Jul 12 17:42:39 2013 +0200
+++ b/python/c3/parser.py	Sat Jul 13 11:12:24 2013 +0200
@@ -28,6 +28,10 @@
     def Peak(self):
         return self.token.typ
 
+    @property
+    def CurLoc(self):
+        return self.token.loc
+
     def hasConsumed(self, typ):
         if self.Peak == typ:
             self.Consume(typ)
@@ -181,7 +185,7 @@
       if self.hasConsumed('else'):
          no = self.parseCompoundStatement()
       else:
-         no = astnodes.EmptyStatement()
+         no = None
       return astnodes.IfStatement(condition, yes, no, loc)
 
     def parseWhileStatement(self):
@@ -203,7 +207,7 @@
         statements = []
         while not self.hasConsumed('}'):
             s = self.Statement()
-            if type(s) is astnodes.EmptyStatement:
+            if s is None:
                 continue
             statements.append(s)
         return astnodes.CompoundStatement(statements)
@@ -217,10 +221,9 @@
         elif self.Peak == '{':
             return self.parseCompoundStatement()
         elif self.hasConsumed(';'):
-            return astnodes.EmptyStatement()
+            pass
         elif self.Peak == 'var':
             self.parseVarDef()
-            return astnodes.EmptyStatement()
         elif self.Peak == 'return':
             return self.parseReturnStatement()
         else:
@@ -301,7 +304,10 @@
     # Domain of unary expressions:
 
     def CastExpression(self):
-        # type cast conflicts with '(' expr ')', so introduce extra keyword 'cast'
+        """
+          the C-style type cast conflicts with '(' expr ')'
+          so introduce extra keyword 'cast'
+        """
         if self.Peak == 'cast':
             self.Consume('cast')
             self.Consume('<')
--- a/python/c3/typecheck.py	Fri Jul 12 17:42:39 2013 +0200
+++ b/python/c3/typecheck.py	Sat Jul 13 11:12:24 2013 +0200
@@ -3,7 +3,10 @@
 from .visitor import Visitor
 
 def equalTypes(a, b):
-    """ Compare types a and b for equality. Not equal until proven otherwise. """
+    """ 
+        Compare types a and b for equality.
+        Not equal until proven otherwise.
+    """
     # Recurse into named types:
     if type(a) is DefinedType:
         return equalTypes(a.typ, b)
@@ -38,7 +41,9 @@
         self.diag = diag
 
     def error(self, msg, loc):
-        """ Wrapper that registers the message and marks the result invalid """
+        """ 
+            Wrapper that registers the message and marks the result invalid 
+        """
         self.diag.error(msg, loc)
         self.ok = False
 
@@ -62,7 +67,6 @@
         elif type(sym) is ReturnStatement:
             pass
         elif type(sym) is FunctionCall:
-         if sym.proc:
             # Check arguments:
             ngiv = len(sym.args)
             ptypes = sym.proc.typ.parametertypes
@@ -75,8 +79,6 @@
                      self.error('Got {0}, expected {1}'.format(a.typ, at), a.loc)
             # determine return type:
             sym.typ = sym.proc.typ.returntype
-         else:
-            sym.typ = intType
         elif type(sym) is VariableUse:
             sym.lvalue = True
             if type(sym.target) is Variable:
@@ -171,7 +173,7 @@
         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, ExpressionStatement, DefinedType]:
+        elif type(sym) in [CompoundStatement, Package, Function, FunctionType, ExpressionStatement, DefinedType]:
          pass
         else:
             raise Exception('Unknown type check {0}'.format(sym))
--- a/python/c3/visitor.py	Fri Jul 12 17:42:39 2013 +0200
+++ b/python/c3/visitor.py	Sat Jul 13 11:12:24 2013 +0200
@@ -1,7 +1,7 @@
 from .astnodes import *
 
 class Visitor:
-    """ 
+    """
         Visitor that can visit all nodes in the AST
         and run pre and post functions.
     """
@@ -11,58 +11,59 @@
         self.do(node)
 
     def do(self, node):
-      # Run visitor:
-      if self.f_pre:
+        # Run visitor:
+        if self.f_pre:
             self.f_pre(node)
 
-      # Descent into subnodes:
-      if type(node) is Package:
+        # Descent into subnodes:
+        if type(node) is Package:
             for decl in node.declarations:
                 self.do(decl)
-      elif type(node) is Function:
+        elif type(node) is Function:
             for s in node.declarations:
                 self.do(s)
             self.do(node.body)
-      elif type(node) is CompoundStatement:
+        elif type(node) is CompoundStatement:
          for s in node.statements:
             self.do(s)
-      elif type(node) is IfStatement:
-         self.do(node.condition)
-         self.do(node.truestatement)
-         self.do(node.falsestatement)
-      elif type(node) is FunctionCall:
-         for arg in node.args:
-            self.do(arg)
-      elif type(node) is Assignment:
-         self.do(node.lval)
-         self.do(node.rval)
-      elif type(node) is ReturnStatement:
-         self.do(node.expr)
-      elif type(node) is Binop:
-         self.do(node.a)
-         self.do(node.b)
-      elif type(node) is Unop:
+        elif type(node) is IfStatement:
+            self.do(node.condition)
+            self.do(node.truestatement)
+            if node.falsestatement:
+                self.do(node.falsestatement)
+        elif type(node) is FunctionCall:
+            for arg in node.args:
+                self.do(arg)
+        elif type(node) is Assignment:
+            self.do(node.lval)
+            self.do(node.rval)
+        elif type(node) is ReturnStatement:
+            self.do(node.expr)
+        elif type(node) is Binop:
             self.do(node.a)
-      elif type(node) is ExpressionStatement:
+            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:
+        elif type(node) is TypeCast:
             self.do(node.a)
-      elif type(node) is FieldRef:
+        elif type(node) is FieldRef:
             self.do(node.base)
-      elif type(node) is Deref:
+        elif type(node) is Deref:
             self.do(node.ptr)
-      elif type(node) is Constant:
+        elif type(node) is Constant:
          self.do(node.value)
-      elif type(node) in [EmptyStatement, VariableUse, Variable, Literal, FunctionType, DefinedType]:
+        elif type(node) in [VariableUse, Variable, Literal, FunctionType, DefinedType]:
          # Those nodes do not have child nodes.
          pass
-      elif type(node) is WhileStatement:
+        elif type(node) is WhileStatement:
          self.do(node.condition)
          self.do(node.statement)
-      else:
+        else:
            raise Exception('Could not visit "{0}"'.format(node))
 
-      # run post function
-      if self.f_post:
+        # run post function
+        if self.f_post:
             self.f_post(node)
 
--- a/python/stm32f4/blink.c3	Fri Jul 12 17:42:39 2013 +0200
+++ b/python/stm32f4/blink.c3	Sat Jul 13 11:12:24 2013 +0200
@@ -2,9 +2,28 @@
 package blink;
 
 // import bla
-//type struct TIM2_s {
+type struct {
 //  uint32_t SR;
-//};
+} TIM_Type;
+
+type struct {
+    int MODER;
+    int OTYPER;
+    int OSPEEDR;
+    int PUPDR;
+    int IDR;
+    int ODR;
+} GPIO_Type;
+
+const GPIO_Type* GPIOD = cast<GPIO_Type*>(0x400000);
+
+function void delay(int count)
+{
+    while (count > 0)
+    {
+        count = count - 1;
+    }
+}
 
 // Globals:
 var int divider;
@@ -29,6 +48,8 @@
 {
     divider = 0;
 
+    // delay(100);
+
     var int* RCC_AHB1ENR;
     RCC_AHB1ENR = cast<int*>(0x40003022);
     *RCC_AHB1ENR = *RCC_AHB1ENR | 8943;
--- a/python/testc3.py	Fri Jul 12 17:42:39 2013 +0200
+++ b/python/testc3.py	Sat Jul 13 11:12:24 2013 +0200
@@ -256,12 +256,11 @@
             pa = 2; // type conflict
             pa = &a;
             pa = &2;
-            &a = 3; // no valid lvalue and incorrect types.
             &a = pa; // No valid lvalue
             **pa = 22; // Cannot deref int
          }
         """
-        self.expectErrors(snippet, [6, 9, 9, 10, 11])
+        self.expectErrors(snippet, [6, 9, 10])
 
     def testComplexType(self):
         snippet = """