changeset 306:b145f8e6050b

Start on c3 rewrite
author Windel Bouwman
date Mon, 09 Dec 2013 19:00:21 +0100
parents 0615b5308710
children e609d5296ee9
files doc/compiler.rst doc/index.rst examples/c3/burn2.c3 kernel/make.py kernel/process.c3 python/ide/astviewer.py python/ide/ide.py python/ppci/c3/analyse.py python/ppci/c3/astnodes.py python/ppci/c3/builder.py python/ppci/c3/codegenerator.py python/ppci/c3/lexer.py python/ppci/c3/parser.py python/ppci/c3/scope.py python/ppci/c3/visitor.py python/target/basetarget.py python/utils/hexfile.py python/zcc.py test/runtests.sh test/testc3.py
diffstat 20 files changed, 431 insertions(+), 340 deletions(-) [+]
line wrap: on
line diff
--- a/doc/compiler.rst	Fri Dec 06 13:50:38 2013 +0100
+++ b/doc/compiler.rst	Mon Dec 09 19:00:21 2013 +0100
@@ -64,12 +64,16 @@
 
 .. autoclass:: ppci.c3.Lexer
 
-.. autoclass:: ppci.c3.Builder
-
 .. autoclass:: ppci.c3.Parser
 
+.. autoclass:: ppci.c3.Analyzer
+
+.. autoclass:: ppci.c3.TypeChecker
+
 .. autoclass:: ppci.c3.CodeGenerator
 
+.. autoclass:: ppci.c3.Builder
+
 Back-end
 --------
 
@@ -80,7 +84,7 @@
 3. Peep hole optimization?
 4. real code generation
 
-.. automodule:: codegen
+.. automodule:: ppci.codegen
    :members:
 
 Instruction selection
--- a/doc/index.rst	Fri Dec 06 13:50:38 2013 +0100
+++ b/doc/index.rst	Mon Dec 09 19:00:21 2013 +0100
@@ -17,6 +17,9 @@
    ir
 
 
+>>> from utils import HexFile
+>>> h = HexFile()
+
 
 Indices and tables
 ==================
--- a/examples/c3/burn2.c3	Fri Dec 06 13:50:38 2013 +0100
+++ b/examples/c3/burn2.c3	Mon Dec 09 19:00:21 2013 +0100
@@ -27,14 +27,14 @@
         return;
     }
 
-    var stm32f4xx:RCC_Type RCC;
-    RCC = cast<stm32f4xx:RCC_Type>(0x40023800);
+    var stm32f4xx.RCC_Type RCC;
+    RCC = cast<stm32f4xx.RCC_Type>(0x40023800);
 
     // Enable the clock to port D:
     RCC->AHB1ENR = RCC->AHB1ENR | (1 << 3);
     // Memory mapped control registers:
-    var stm32f4xx:GPIO_Type GPIOD;
-    GPIOD = cast<stm32f4xx:GPIO_Type>(0x40020C00);
+    var stm32f4xx.GPIO_Type GPIOD;
+    GPIOD = cast<stm32f4xx.GPIO_Type>(0x40020C00);
 
     // PD13 == output (01)
     GPIOD->MODER = (1 << (pin << 1));
@@ -48,7 +48,7 @@
     init(13);
 
     var int a;
-    a = 0
+    a = 0;
     while (a < 1000)
     {
         a = add(a, 1);
--- a/kernel/make.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/kernel/make.py	Mon Dec 09 19:00:21 2013 +0100
@@ -5,10 +5,15 @@
 sys.path.insert(0, os.path.join('..', 'python'))
 import zcc
 
-arglist = ['memory.c3', 'kernel.c3', 'syscall.c3', 'process.c3', 'schedule.c3', 'arch_arm.c3']
-arglist += ['--target', 'arm']
-arglist += ['--dumpasm', '--dumpir']
-arglist += ['--log', 'debug']
+def make():
+    arglist = ['memory.c3', 'kernel.c3', 'syscall.c3', 'process.c3']
+    arglist += ['schedule.c3', 'arch_arm.c3']
+    arglist += ['--target', 'arm']
+    arglist += ['--dumpasm', '--dumpir']
+    arglist += ['--log', 'debug']
 
-args = zcc.parser.parse_args(arglist)
-zcc.main(args)
+    args = zcc.parser.parse_args(arglist)
+    zcc.main(args)
+
+if __name__ == '__main__':
+    make()
--- a/kernel/process.c3	Fri Dec 06 13:50:38 2013 +0100
+++ b/kernel/process.c3	Mon Dec 09 19:00:21 2013 +0100
@@ -13,8 +13,8 @@
 // List<process_t> procs;
 
 // init is the root of all processes:
-var process_t* init_pid = 0;
-var int next_pid = 0;
+var process_t* init_pid;
+var int next_pid;
 
 function void init()
 {
--- a/python/ide/astviewer.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ide/astviewer.py	Mon Dec 09 19:00:21 2013 +0100
@@ -1,6 +1,6 @@
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
-from c3 import Visitor, astnodes
+from ppci.c3 import Visitor, astnodes
 
 class AstModelBuilder:
     def __init__(self):
--- a/python/ide/ide.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ide/ide.py	Mon Dec 09 19:00:21 2013 +0100
@@ -20,7 +20,6 @@
 from logview import LogView as BuildOutput
 from disasm import Disassembly
 stutil = __import__('st-util')
-import c3
 import zcc
 import outstream
 from target import armtarget
@@ -172,7 +171,6 @@
         self.settings = QSettings('windelsoft', 'lcfoside')
         self.loadSettings()
         self.diag = ppci.DiagnosticsManager()
-        self.c3front = c3.Builder(self.diag)
 
     # File handling:
     def newFile(self):
--- a/python/ppci/c3/analyse.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ppci/c3/analyse.py	Mon Dec 09 19:00:21 2013 +0100
@@ -1,35 +1,40 @@
 import logging
-from .visitor import Visitor
+from .visitor import Visitor, AstPrinter
 from .astnodes import *
-from .scope import *
+from .scope import Scope
 
 
 class C3Pass:
     def __init__(self, diag):
         self.diag = diag
         self.logger = logging.getLogger('c3')
-        self.ok = True
         self.visitor = Visitor()
 
     def error(self, msg, loc=None):
-        self.ok = False
+        self.pkg.ok = False
         self.diag.error(msg, loc)
 
     def visit(self, pkg, pre, post):
+        self.pkg = pkg
         self.visitor.visit(pkg, pre, post)
+        self.pkg = None
 
 
 class AddScope(C3Pass):
+    scoped_types = [Package, Function]
+    def __init__(self, diag, topScope):
+        super().__init__(diag)
+        self.topScope = topScope
+
     """ Scope is attached to the correct modules. """
     def addScope(self, pkg):
         self.logger.info('Adding scoping to package {}'.format(pkg.name))
         # Prepare top level scope and set scope to all objects:
-        self.scopeStack = [topScope]
+        self.scopeStack = [self.topScope]
         modScope = Scope(self.CurrentScope)
         self.scopeStack.append(modScope)
         self.visit(pkg, self.enterScope, self.quitScope)
         assert len(self.scopeStack) == 2
-        return self.ok
 
     @property
     def CurrentScope(self):
@@ -46,18 +51,18 @@
         sym.scope = self.CurrentScope
 
         # Add symbols to current scope:
-        if isinstance(sym, Symbol) or isinstance(sym, DefinedType):
+        if isinstance(sym, Symbol):
             self.addSymbol(sym)
 
         # Create subscope:
-        if type(sym) in [Package, Function]:
+        if type(sym) in self.scoped_types:
             newScope = Scope(self.CurrentScope)
             self.scopeStack.append(newScope)
             sym.innerScope = self.CurrentScope
 
     def quitScope(self, sym):
         # Pop out of scope:
-        if type(sym) in [Package, Function]:
+        if type(sym) in self.scoped_types:
             self.scopeStack.pop(-1)
 
 
@@ -69,8 +74,8 @@
     """
 
     def analyzePackage(self, pkg, packageDict):
-        self.ok = True
         # Prepare top level scope and set scope to all objects:
+        self.pkg = pkg
 
         self.logger.info('Resolving imports for package {}'.format(pkg.name))
         # Handle imports:
@@ -82,74 +87,12 @@
             pkg.scope.addSymbol(ip)
         fr = FixRefs(self.diag)
         fr.fixRefs(pkg)
-        return self.ok and fr.ok
 
 
 class FixRefs(C3Pass):
     def fixRefs(self, pkg):
-        self.ok = True
         self.logger.info('Resolving references for {}'.format(pkg.name))
-        self.visitor.visit(pkg, self.findRefs)
-
-    # Reference fixups:
-    def resolveDesignator(self, d, scope):
-        assert isinstance(d, Designator), type(d)
-        assert type(scope) is Scope
-        if scope.hasSymbol(d.tname):
-            s = scope.getSymbol(d.tname)
-            if isinstance(d, ImportDesignator):
-                if s.innerScope.hasSymbol(d.vname):
-                    return s.innerScope.getSymbol(d.vname)
-            else:
-                s.addRef(None)  # TODO: fix this?
-                return s
-        self.error('Cannot resolve name {0}'.format(d.tname), d.loc)
-
-    def resolveType(self, t, scope):
-        if type(t) is PointerType:
-            t.ptype = self.resolveType(t.ptype, scope)
-            return t
-        elif type(t) is StructureType:
-            offset = 0
-            for mem in t.mems:
-                mem.offset = offset
-                mem.typ = self.resolveType(mem.typ, scope)
-                offset += theType(mem.typ).bytesize
-            t.bytesize = offset
-            return t
-        elif isinstance(t, Designator):
-            t = self.resolveDesignator(t, scope)
-            if t:
-                return self.resolveType(t, scope)
-        elif isinstance(t, Type):
-            # Already resolved??
-            return t
-        else:
-            raise Exception('Error resolving type {} {}'.format(t, type(t)))
-
-    def findRefs(self, sym):
-        if type(sym) is Constant or isinstance(sym, Variable):
-            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:
-            varuse = sym.proc
-            if type(varuse) is VariableUse:
-                sym.proc = self.resolveDesignator(varuse.target, sym.scope)
-        elif type(sym) is Function:
-            # Checkup function type:
-            ft = sym.typ
-            ft.returntype = self.resolveType(ft.returntype, sym.scope)
-            ft.parametertypes = [self.resolveType(pt, sym.scope) for pt in
-                                 ft.parametertypes]
-            # Mark local variables:
-            for d in sym.declarations:
-                if isinstance(d, Variable):
-                    d.isLocal = True
-        elif type(sym) is DefinedType:
-            sym.typ = self.resolveType(sym.typ, sym.scope)
+        self.pkg = pkg
 
 
 # Type checking:
@@ -158,13 +101,18 @@
     """ Recurse until a 'real' type is found """
     if type(t) is DefinedType:
         return theType(t.typ)
+    elif type(t) is Identifier:
+        return theType(resolveSymbol(t))
     return t
 
 
 def equalTypes(a, b):
     """ Compare types a and b for structural equavalence. """
     # Recurse into named types:
-    a, b = theType(a), theType(b)
+    a = theType(a)
+    b = theType(b)
+    assert isinstance(a, Type)
+    assert isinstance(b, Type)
 
     if type(a) is type(b):
         if type(a) is BaseType:
@@ -177,8 +125,7 @@
             return all(equalTypes(am.typ, bm.typ) for am, bm in
                        zip(a.mems, b.mems))
         else:
-            raise NotImplementedError('Type compare for {} not implemented'
-                                      .format(type(a)))
+            raise NotImplementedError('{} not implemented'.format(type(a)))
     return False
 
 
@@ -187,7 +134,8 @@
     toT = theType(toT)
     if isinstance(fromT, PointerType) and isinstance(toT, PointerType):
         return True
-    elif fromT is intType and isinstance(toT, PointerType):
+    elif type(fromT) is BaseType and fromT.name == 'int' and \
+            isinstance(toT, PointerType):
         return True
     return False
 
@@ -196,20 +144,121 @@
     # TODO: solve this better
     s.expect_rvalue = True
 
+# Reference fixups:
+def resolveDesignator(self, d, scope):
+    assert isinstance(d, Designator), type(d)
+    assert type(scope) is Scope
+    if d.tname in scope:
+        s = scope[d.tname]
+        if isinstance(d, ImportDesignator):
+            if s.innerScope.hasSymbol(d.vname):
+                return s.innerScope.getSymbol(d.vname)
+        else:
+            s.addRef(None)  # TODO: fix this?
+            return s
+    self.error('Cannot resolve name {0}'.format(d.tname), d.loc)
+
+
+def findRefs(self, sym):
+    if type(sym) is Constant or isinstance(sym, Variable):
+        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:
+        varuse = sym.proc
+        if type(varuse) is VariableUse:
+            sym.proc = self.resolveDesignator(varuse.target, sym.scope)
+    elif type(sym) is Function:
+        # Checkup function type:
+        ft = sym.typ
+        ft.returntype = self.resolveType(ft.returntype, sym.scope)
+        ft.parametertypes = [self.resolveType(pt, sym.scope) for pt in
+                             ft.parametertypes]
+        # Mark local variables:
+        for d in sym.declarations:
+            if isinstance(d, Variable):
+                d.isLocal = True
+    elif type(sym) is DefinedType:
+        sym.typ = self.resolveType(sym.typ, sym.scope)
+
+
+def resolveSymbol(sym):
+    name = sym.target
+    scope = sym.scope
+    return scope[name]
+
 
 class TypeChecker(C3Pass):
+    """ Checks if all types are correctly used """
     def checkPackage(self, pkg):
         self.logger.info('Type checking {}'.format(pkg.name))
-        self.ok = True
-        self.visit(pkg, None, self.check2)
-        return self.ok
+        self.pkg = pkg
+        AstPrinter().printAst(pkg)
+        # Prepare some standard types:
+        self.intType = pkg.scope['int']
+        self.boolType = pkg.scope['bool']
+        for decl in pkg.declarations:
+            self.checkDecl(decl)
+        self.pkg.ok = False
+
+    def checkDecl(self, decl):
+        if type(decl) is Function:
+            self.checkFunction(decl)
+        elif isinstance(decl, Variable):
+            pass
+        elif isinstance(decl, Type):
+            self.checkType(decl)
+        else:
+            raise Exception(str(decl))
 
-    def check2(self, sym):
-        if type(sym) in [IfStatement, WhileStatement]:
-            if not equalTypes(sym.condition.typ, boolType):
-                msg = 'Condition must be of type {}'.format(boolType)
+    def checkType(self, t):
+        if type(t) is PointerType:
+            self.checkType(t.ptype)
+        elif type(t) is StructureType:
+            offset = 0
+            for mem in t.mems:
+                mem.offset = offset
+                self.checkType(mem.typ)
+                offset += theType(mem.typ).bytesize
+            t.bytesize = offset
+        elif type(t) is DefinedType:
+            self.checkType(t.typ)
+        elif isinstance(t, Identifier):
+            pass
+        elif isinstance(t, Member):
+            pass
+        else:
+            raise Exception('Error resolving type {} {}'.format(t, type(t)))
+
+    def checkVariable(self, v):
+        self.checkType(v.typ)
+
+    def checkFunction(self, f):
+        for decl in f.declarations:
+            self.checkDecl(decl)
+        self.checkStmt(f.body)
+
+
+    def checkStmt(self, sym):
+        assert isinstance(sym, Statement)
+        if type(sym) is IfStatement:
+            self.checkExpr(sym.condition)
+            if not equalTypes(sym.condition.typ, self.boolType):
+                msg = 'Condition must be boolean'
                 self.error(msg, sym.condition.loc)
+            self.checkStmt(sym.truestatement)
+            self.checkStmt(sym.falsestatement)
+        elif type(sym) is WhileStatement:
+            self.checkExpr(sym.condition)
+            if not equalTypes(sym.condition.typ, self.boolType):
+                msg = 'Condition must be boolean'
+                self.error(msg, sym.condition.loc)
+            self.checkStmt(sym.statement)
         elif type(sym) is Assignment:
+            self.checkExpr(sym.lval)
+            self.checkExpr(sym.rval)
             l, r = sym.lval, sym.rval
             if not equalTypes(l.typ, r.typ):
                 msg = 'Cannot assign {} to {}'.format(r.typ, l.typ)
@@ -221,9 +270,25 @@
             expectRval(sym.rval)
         elif type(sym) is ReturnStatement:
             pass
-        elif type(sym) is FunctionCall:
+        elif type(sym) is EmptyStatement:
+            pass
+        elif type(sym) is ExpressionStatement:
+            self.checkExpr(sym.ex)
+        elif type(sym) is CompoundStatement:
+            for s in sym.statements:
+                self.checkStmt(s)
+        else:
+            raise Exception(str(sym))
+
+    def checkExpr(self, sym):
+        assert isinstance(sym, Expression)
+        if type(sym) is FunctionCall:
             # Check arguments:
+            for arg in sym.args:
+                self.checkExpr(arg)
+            self.checkExpr(sym.proc)
             ngiv = len(sym.args)
+            # tg = 
             ptypes = sym.proc.typ.parametertypes
             nreq = len(ptypes)
             if ngiv != nreq:
@@ -237,18 +302,16 @@
                                    .format(a.typ, at), a.loc)
             # determine return type:
             sym.typ = sym.proc.typ.returntype
-        elif type(sym) is VariableUse:
+        elif type(sym) is Identifier:
             sym.lvalue = True
-            assert isinstance(sym.target, Variable), sym.target
-            sym.typ = sym.target.typ
+            tg = resolveSymbol(sym)
+            sym.kind = type(tg)
+            sym.typ = tg.typ
         elif type(sym) is Literal:
             sym.lvalue = False
-            if type(sym.val) is int:
-                sym.typ = intType
-            elif type(sym.val) is float:
-                sym.typ = doubleType
-            elif type(sym.val) is bool:
-                sym.typ = boolType
+            typemap = {int: 'int', float: 'double', bool: 'bool'}
+            if type(sym.val) in typemap:
+                sym.typ = self.pkg.scope[typemap[type(sym.val)]]
             else:
                 raise Exception('Unknown literal type'.format(sym.val))
         elif type(sym) is Unop:
@@ -261,14 +324,16 @@
             # pointer deref
             sym.lvalue = True
             # check if the to be dereferenced variable is a pointer type:
+            self.checkExpr(sym.ptr)
             ptype = theType(sym.ptr.typ)
             if type(ptype) is PointerType:
                 sym.typ = ptype.ptype
             else:
                 self.error('Cannot dereference non-pointer type {}'
                            .format(ptype), sym.loc)
-                sym.typ = intType
-        elif type(sym) is FieldRef:
+                sym.typ = self.intType
+        elif type(sym) is Member:
+            self.checkExpr(sym.base)
             basetype = sym.base.typ
             sym.lvalue = sym.base.lvalue
             basetype = theType(basetype)
@@ -278,59 +343,61 @@
                 else:
                     self.error('{} does not contain field {}'
                                .format(basetype, sym.field), sym.loc)
-                    sym.typ = intType
+                    sym.typ = self.intType
             else:
                 self.error('Cannot select field {} of non-structure type {}'
                            .format(sym.field, basetype), sym.loc)
-                sym.typ = intType
+                sym.typ = self.intType
         elif type(sym) is Binop:
+            self.checkExpr(sym.a)
+            self.checkExpr(sym.b)
             sym.lvalue = False
             if sym.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']:
                 expectRval(sym.a)
                 expectRval(sym.b)
                 if equalTypes(sym.a.typ, sym.b.typ):
-                    if equalTypes(sym.a.typ, intType):
+                    if equalTypes(sym.a.typ, self.intType):
                         sym.typ = sym.a.typ
                     else:
                         self.error('Can only add integers', sym.loc)
-                        sym.typ = intType
+                        sym.typ = self.intType
                 else:
                     # assume void here? TODO: throw exception!
-                    sym.typ = intType
+                    sym.typ = self.intType
                     self.error('Types unequal {} != {}'
                                .format(sym.a.typ, sym.b.typ), sym.loc)
             elif sym.op in ['>', '<', '==', '<=', '>=', '!=']:
                 expectRval(sym.a)
                 expectRval(sym.b)
-                sym.typ = boolType
+                sym.typ = self.boolType
                 if not equalTypes(sym.a.typ, sym.b.typ):
                     self.error('Types unequal {} != {}'
                                .format(sym.a.typ, sym.b.typ), sym.loc)
             elif sym.op in ['or', 'and']:
-                sym.typ = boolType
-                if not equalTypes(sym.a.typ, boolType):
-                    self.error('Must be {0}'.format(boolType), sym.a.loc)
-                if not equalTypes(sym.b.typ, boolType):
-                    self.error('Must be {0}'.format(boolType), sym.b.loc)
+                sym.typ = self.boolType
+                if not equalTypes(sym.a.typ, self.boolType):
+                    self.error('Must be boolean', sym.a.loc)
+                if not equalTypes(sym.b.typ, self.boolType):
+                    self.error('Must be boolean', sym.b.loc)
             else:
                 raise Exception('Unknown binop {0}'.format(sym.op))
         elif isinstance(sym, Variable):
-            # check initial value type:
-            # TODO
             pass
         elif type(sym) is TypeCast:
+            self.checkExpr(sym.a)
+            self.checkType(sym.to_type)
             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), sym.loc)
-                sym.typ = intType
+                sym.typ = self.intType
         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 [CompoundStatement, Package, Function, FunctionType,
-                           ExpressionStatement, DefinedType]:
+                           ExpressionStatement, DefinedType, EmptyStatement]:
             pass
         else:
             raise NotImplementedError('Unknown type check {0}'.format(sym))
--- a/python/ppci/c3/astnodes.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ppci/c3/astnodes.py	Mon Dec 09 19:00:21 2013 +0100
@@ -9,11 +9,14 @@
 
 
 class Node:
+    """ Base class of all nodes in a AST """
     pass
 
 
 # Variables, parameters, local variables, constants and named types:
 class Symbol(Node):
+    """ Symbol is the base class for all named things like variables, 
+        functions, constants and types and modules """
     def __init__(self, name):
         self.name = name
         self.refs = []
@@ -38,47 +41,21 @@
         return 'MODULE {}'.format(self.name)
 
 
-class Designator(Node):
-    def __init__(self, tname, loc):
-        self.tname = tname
-        self.loc = loc
-
-    def __repr__(self):
-        return 'DESIGNATOR {}'.format(self.tname)
-
-
-class ImportDesignator(Designator):
-    def __init__(self, tname, vname, loc):
-        super().__init__(tname, loc)
-        self.vname = vname
-
-    def __repr__(self):
-        return 'IMPORT DESIGNATOR {}:{}'.format(self.tname, self.vname)
-
-
-"""
-Type classes
-
-types must be comparable.
-
-There are the following types:
-- base type -> basic type (built in)
-- struct type -> a composite type that contains a list of named fields
-            of other types
-- function type
-"""
-
-
 class Type(Node):
+    """ Base class of all types """
     pass
 
 
 class NamedType(Type, Symbol):
+    """ Some types are named, for example a user defined type (typedef) 
+        and built in types. That is why this class derives from both Type
+        and Symbol. """
     def __init__(self, name):
         Symbol.__init__(self, name)
 
 
 class BaseType(NamedType):
+    """ Built in type """
     def __init__(self, name):
         super().__init__(name)
 
@@ -87,6 +64,7 @@
 
 
 class FunctionType(Type):
+    """ Function blueprint, defines argument types and return type """
     def __init__(self, parametertypes, returntype):
         self.parametertypes = parametertypes
         self.returntype = returntype
@@ -99,7 +77,7 @@
 class PointerType(Type):
     """ A type that points to data of some other type """
     def __init__(self, ptype):
-        assert isinstance(ptype, Type) or isinstance(ptype, Designator)
+        assert isinstance(ptype, Type) or isinstance(ptype, Expression)
         self.ptype = ptype
 
     def __repr__(self):
@@ -108,17 +86,17 @@
 
 class StructField:
     def __init__(self, name, typ):
+        assert type(name) is str
         self.name = name
         self.typ = typ
         self.offset = 0
 
 
 class StructureType(Type):
+    """ Struct type consisting of several named members """
     def __init__(self, mems):
         self.mems = mems
-        for mem in mems:
-            assert type(mem) is StructField
-            assert type(mem.name) is str
+        assert all(type(mem) is StructField for mem in mems)
 
     def hasField(self, name):
         for mem in self.mems:
@@ -168,7 +146,6 @@
     def __init__(self, name, typ):
         super().__init__(name)
         self.typ = typ
-        self.ival = None
         self.isLocal = False
         self.isReadOnly = False
         self.isParameter = False
@@ -227,7 +204,8 @@
         return 'TYPECAST {}'.format(self.to_type)
 
 
-class FieldRef(Expression):
+class Member(Expression):
+    """ Field reference of some object, can also be package selection """
     def __init__(self, base, field, loc):
         super().__init__(loc)
         assert isinstance(base, Expression)
@@ -236,10 +214,11 @@
         self.field = field
 
     def __repr__(self):
-        return 'FIELD {}.{}'.format(self.base, self.field)
+        return 'MEMBER {}.{}'.format(self.base, self.field)
 
 
 class Unop(Expression):
+    """ Operation on one operand """
     def __init__(self, op, a, loc):
         super().__init__(loc)
         assert isinstance(a, Expression)
@@ -252,6 +231,7 @@
 
 
 class Binop(Expression):
+    """ Expression taking two operands and one operator """
     def __init__(self, a, op, b, loc):
         super().__init__(loc)
         assert isinstance(a, Expression), type(a)
@@ -265,16 +245,19 @@
         return 'BINOP {}'.format(self.op)
 
 
-class VariableUse(Expression):
+class Identifier(Expression):
+    """ Reference to some identifier, can be anything from package, variable
+        function or type, any named thing! """
     def __init__(self, target, loc):
         super().__init__(loc)
         self.target = target
 
     def __repr__(self):
-        return 'VAR USE {}'.format(self.target)
+        return 'ID {}'.format(self.target)
 
 
 class Literal(Expression):
+    """ Constant value or string """
     def __init__(self, val, loc):
         super().__init__(loc)
         self.val = val
@@ -284,6 +267,7 @@
 
 
 class FunctionCall(Expression):
+    """ Call to a some function """
     def __init__(self, proc, args, loc):
         super().__init__(loc)
         self.proc = proc
@@ -295,11 +279,22 @@
 
 # Statements
 class Statement(Node):
+    """ Base class of all statements """
     def __init__(self, loc):
         self.loc = loc
 
 
+class EmptyStatement(Statement):
+    """ Empty statement which does nothing! """
+    def __init__(self):
+        super().__init__(None)
+
+    def __repr__(self):
+        return 'NOP'
+
+
 class CompoundStatement(Statement):
+    """ Statement consisting of a sequence of other statements """
     def __init__(self, statements):
         super().__init__(None)
         self.statements = statements
@@ -322,8 +317,8 @@
 class Assignment(Statement):
     def __init__(self, lval, rval, loc):
         super().__init__(loc)
-        assert isinstance(lval, Node)
-        assert isinstance(rval, Node)
+        assert isinstance(lval, Expression)
+        assert isinstance(rval, Expression)
         self.lval = lval
         self.rval = rval
 
--- a/python/ppci/c3/builder.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ppci/c3/builder.py	Mon Dec 09 19:00:21 2013 +0100
@@ -1,8 +1,11 @@
 import logging
+from .lexer import Lexer
 from .parser import Parser
 from .analyse import TypeChecker, Analyzer
 from .codegenerator import CodeGenerator
 from .analyse import AddScope
+from .scope import createTopScope
+from .visitor import AstPrinter
 
 
 class Builder:
@@ -13,53 +16,55 @@
     def __init__(self, diag, target):
         self.logger = logging.getLogger('c3')
         self.diag = diag
+        self.lexer = Lexer(diag)
         self.parser = Parser(diag)
         self.tc = TypeChecker(diag)
         self.al = Analyzer(diag)
         self.cg = CodeGenerator()
-
-    def checkSource(self, srcs, imps=[]):
-        """ Performs syntax and type check. """
-        iter(srcs)
-        iter(imps)
-
-        def doParse(srcs):
-            for src in srcs:
-                pkg = self.parser.parseSource(src)
-                if pkg:
-                    yield pkg
-                else:
-                    self.ok = False
-        s_pkgs = set(doParse(srcs))
-        i_pkgs = set(doParse(imps))
-        all_pkgs = s_pkgs | i_pkgs
-        # Fix scopes:
-
-        def doF(f, pkgs):
-            for pkg in pkgs:
-                if f(pkg):
-                    yield pkg
-                else:
-                    self.ok = False
-        all_pkgs = set(doF(AddScope(self.diag).addScope, all_pkgs))
-        # TODO: fix error handling better
-
-        def doA(pkgs):
-            packages = {pkg.name: pkg for pkg in pkgs}
-            for pkg in pkgs:
-                if self.al.analyzePackage(pkg, packages):
-                    yield pkg
-                else:
-                    self.ok = False
-        all_pkgs = set(doA(all_pkgs))
-        all_pkgs = set(doF(self.tc.checkPackage, all_pkgs))
-        return all_pkgs & s_pkgs
+        self.topScope = createTopScope(target)  # Scope with built in types
 
     def build(self, srcs, imps=[]):
         """ Create IR-code from sources """
         self.logger.info('Building {} source files'.format(len(srcs)))
+        iter(srcs)  # Check if srcs are iterable
+        iter(imps)
         self.ok = True
-        for pkg in self.checkSource(srcs, imps):
-            # Only return ircode when everything is OK
-            if self.ok:
-                yield self.cg.gencode(pkg)
+        self.pkgs = {}
+
+        def doParse(src):
+            tokens = self.lexer.lex(src)
+            return self.parser.parseSource(tokens)
+        s_pkgs = set(map(doParse, srcs))
+        i_pkgs = set(map(doParse, imps))
+        all_pkgs = s_pkgs | i_pkgs
+        if not all(all_pkgs):
+            self.ok = False
+            return
+
+        #for pkg in all_pkgs:
+        #    AstPrinter().printAst(pkg)
+            
+        packages = {pkg.name: pkg for pkg in all_pkgs}
+        self.pkgs = packages
+        # Fix scopes:
+        for pkg in all_pkgs:
+            AddScope(self.diag, self.topScope).addScope(pkg)
+        if not all(pkg.ok for pkg in all_pkgs):
+            self.ok = False
+            return
+
+        for pkg in all_pkgs:
+            self.al.analyzePackage(pkg, packages)
+        if not all(pkg.ok for pkg in all_pkgs):
+            self.ok = False
+            return
+
+        for pkg in all_pkgs:
+            self.tc.checkPackage(pkg)
+        if not all(pkg.ok for pkg in all_pkgs):
+            self.ok = False
+            return
+
+        # Only return ircode when everything is OK
+        for pkg in all_pkgs & s_pkgs:
+            yield self.cg.gencode(pkg)
--- a/python/ppci/c3/codegenerator.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ppci/c3/codegenerator.py	Mon Dec 09 19:00:21 2013 +0100
@@ -1,7 +1,6 @@
 import logging
 from .. import ir
 from . import astnodes
-from .scope import boolType, intType
 from ppci import CompilerError
 from .analyse import theType
 
@@ -43,7 +42,6 @@
         # TODO: handle arguments
         f = self.funcMap[fn]
         f.return_value = self.newTemp()
-        # TODO reserve room for stack, this can be done at later point?
         self.setFunction(f)
         l2 = self.newBlock()
         self.emit(ir.Jump(l2))
@@ -77,6 +75,8 @@
         if type(code) is astnodes.CompoundStatement:
             for s in code.statements:
                 self.genCode(s)
+        elif type(code) is astnodes.EmptyStatement:
+            pass
         elif type(code) is astnodes.Assignment:
             rval = self.genExprCode(code.rval)
             lval = self.genExprCode(code.lval)
@@ -92,12 +92,10 @@
             self.genCode(code.truestatement)
             self.emit(ir.Jump(te))
             self.setBlock(bbfalse)
-            if code.falsestatement:
-                self.genCode(code.falsestatement)
+            self.genCode(code.falsestatement)
             self.emit(ir.Jump(te))
             self.setBlock(te)
         elif type(code) is astnodes.ReturnStatement:
-            assert code.expr
             re = self.genExprCode(code.expr)
             self.emit(ir.Move(self.fn.return_value, re))
             self.emit(ir.Jump(self.fn.epiloog))
@@ -119,7 +117,6 @@
 
     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.newBlock()
@@ -180,7 +177,7 @@
             ar = self.genExprCode(expr.a)
             tt = theType(expr.to_type)
             if isinstance(tt, astnodes.PointerType):
-                if expr.a.typ is intType:
+                if expr.a.typ is expr.scope['int']:
                     return ar
                 elif isinstance(expr.a.typ, astnodes.PointerType):
                     return ar
--- a/python/ppci/c3/lexer.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ppci/c3/lexer.py	Mon Dec 09 19:00:21 2013 +0100
@@ -19,6 +19,9 @@
     def __init__(self, diag):
         self.diag = diag
 
+    def lex(self, source):
+        return self.tokenize(source)
+
     def tokenize(self, input_file):
         """
            Tokenizer, generates an iterator that
--- a/python/ppci/c3/parser.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ppci/c3/parser.py	Mon Dec 09 19:00:21 2013 +0100
@@ -1,15 +1,16 @@
 import logging
 from ppci import CompilerError
-from .lexer import Lexer
-from .astnodes import FieldRef, Literal, TypeCast, Unop, Binop
+from .astnodes import Member, Literal, TypeCast, Unop, Binop
 from .astnodes import Assignment, ExpressionStatement, CompoundStatement
 from .astnodes import ReturnStatement, WhileStatement, IfStatement
 from .astnodes import FunctionType, Function, FormalParameter
 from .astnodes import StructureType, DefinedType, PointerType
 from .astnodes import Constant, Variable
 from .astnodes import StructField, Deref
-from .astnodes import Package, ImportDesignator
-from .astnodes import Designator, VariableUse, FunctionCall
+from .astnodes import Package
+from .astnodes import Identifier
+from .astnodes import FunctionCall
+from .astnodes import EmptyStatement
 
 
 class Parser:
@@ -17,13 +18,14 @@
     def __init__(self, diag):
         self.logger = logging.getLogger('c3')
         self.diag = diag
-        self.lexer = Lexer(diag)
 
-    def parseSource(self, source):
+    def parseSource(self, tokens):
         self.logger.info('Parsing source')
-        self.initLex(source)
+        self.tokens = tokens
+        self.token = self.tokens.__next__()
         try:
             self.parsePackage()
+            self.mod.ok = True  # Valid until proven wrong :)
             return self.mod
         except CompilerError as e:
             self.diag.addDiag(e)
@@ -58,10 +60,6 @@
             self.token = self.tokens.__next__()
         return t
 
-    def initLex(self, source):
-        self.tokens = self.lexer.tokenize(source)
-        self.token = self.tokens.__next__()
-
     def addDeclaration(self, decl):
         self.currentPart.declarations.append(decl)
 
@@ -86,6 +84,7 @@
             self.parseFunctionDef()
         elif self.Peak == 'var':
             self.parseVarDef()
+            # TODO handle variable initialization
         elif self.Peak == 'const':
             self.parseConstDef()
         elif self.Peak == 'type':
@@ -98,11 +97,13 @@
     def parseDesignator(self):
         """ A designator designates an object with a name. """
         name = self.Consume('ID')
-        if self.hasConsumed(':'):
-            name2 = self.Consume('ID')
-            return ImportDesignator(name.val, name2.val, name.loc)
-        else:
-            return Designator(name.val, name.loc)
+        return Identifier(name.val, name.loc)
+
+    def parseIdSequence(self):
+        ids = [self.Consume('ID')]
+        while self.hasConsumed(','):
+            ids.append(self.Consume('ID'))
+        return ids
 
     # Type system
     def parseTypeSpec(self):
@@ -113,16 +114,16 @@
             mems = []
             while self.Peak != '}':
                 mem_t = self.parseTypeSpec()
-                mem_n = self.Consume('ID').val
-                mems.append(StructField(mem_n, mem_t))
-                while self.hasConsumed(','):
-                    mem_n = self.Consume('ID').val
-                    mems.append(StructField(mem_n, mem_t))
+                for i in self.parseIdSequence():
+                    mems.append(StructField(i.val, mem_t))
                 self.Consume(';')
             self.Consume('}')
             theT = StructureType(mems)
+        elif self.Peak == 'enum':
+            # TODO)
+            raise NotImplementedError()
         else:
-            theT = self.parseDesignator()
+            theT = self.PostFixExpression()
         # Check for pointer suffix:
         while self.hasConsumed('*'):
             theT = PointerType(theT)
@@ -140,35 +141,26 @@
     def parseVarDef(self):
         self.Consume('var')
         t = self.parseTypeSpec()
-
-        def parseVar():
-            name = self.Consume('ID')
+        for name in self.parseIdSequence():
             v = Variable(name.val, t)
             v.loc = name.loc
-            if self.hasConsumed('='):
-                v.ival = self.Expression()
             self.addDeclaration(v)
-        parseVar()
-        while self.hasConsumed(','):
-            parseVar()
         self.Consume(';')
+        return EmptyStatement()
 
     def parseConstDef(self):
         self.Consume('const')
         t = self.parseTypeSpec()
-
-        def parseConst():
+        while True:
             name = self.Consume('ID')
             self.Consume('=')
             val = self.Expression()
             c = Constant(name.val, t, val)
             c.loc = name.loc
-        parseConst()
-        while self.hasConsumed(','):
-            parseConst()
+            if not self.hasConsumed(','):
+                break
         self.Consume(';')
 
-    # Procedures
     def parseFunctionDef(self):
         loc = self.Consume('function').loc
         returntype = self.parseTypeSpec()
@@ -180,34 +172,28 @@
         self.Consume('(')
         parameters = []
         if not self.hasConsumed(')'):
-            def parseParameter():
+            while True:
                 typ = self.parseTypeSpec()
                 name = self.Consume('ID')
                 param = FormalParameter(name.val, typ)
                 param.loc = name.loc
                 self.addDeclaration(param)
                 parameters.append(param)
-            parseParameter()
-            while self.hasConsumed(','):
-                parseParameter()
+                if not self.hasConsumed(','):
+                    break
             self.Consume(')')
         paramtypes = [p.typ for p in parameters]
         f.typ = FunctionType(paramtypes, returntype)
         f.body = self.parseCompoundStatement()
         self.currentPart = savePart
 
-    # Statements:
-
     def parseIfStatement(self):
         loc = self.Consume('if').loc
         self.Consume('(')
         condition = self.Expression()
         self.Consume(')')
-        yes = self.parseCompoundStatement()
-        if self.hasConsumed('else'):
-            no = self.parseCompoundStatement()
-        else:
-            no = None
+        yes = self.Statement()
+        no = self.Statement() if self.hasConsumed('else') else EmptyStatement()
         return IfStatement(condition, yes, no, loc)
 
     def parseWhileStatement(self):
@@ -215,7 +201,7 @@
         self.Consume('(')
         condition = self.Expression()
         self.Consume(')')
-        statements = self.parseCompoundStatement()
+        statements = self.Statement()
         return WhileStatement(condition, statements, loc)
 
     def parseReturnStatement(self):
@@ -231,10 +217,7 @@
         self.Consume('{')
         statements = []
         while not self.hasConsumed('}'):
-            s = self.Statement()
-            if s is None:
-                continue
-            statements.append(s)
+            statements.append(self.Statement())
         return CompoundStatement(statements)
 
     def Statement(self):
@@ -246,23 +229,20 @@
         elif self.Peak == '{':
             return self.parseCompoundStatement()
         elif self.hasConsumed(';'):
-            pass
+            return EmptyStatement()
         elif self.Peak == 'var':
-            self.parseVarDef()
+            return self.parseVarDef()
         elif self.Peak == 'return':
             return self.parseReturnStatement()
         else:
-            return self.AssignmentOrCall()
-
-    def AssignmentOrCall(self):
-        x = self.UnaryExpression()
-        if self.Peak == '=':
-            # We enter assignment mode here.
-            loc = self.Consume('=').loc
-            rhs = self.Expression()
-            return Assignment(x, rhs, loc)
-        else:
-            return ExpressionStatement(x, x.loc)
+            x = self.UnaryExpression()
+            if self.Peak == '=':
+                # We enter assignment mode here.
+                loc = self.Consume('=').loc
+                rhs = self.Expression()
+                return Assignment(x, rhs, loc)
+            else:
+                return ExpressionStatement(x, x.loc)
 
     # Expression section:
     # We not implement these C constructs:
@@ -321,7 +301,7 @@
 
     def BitwiseOr(self):
         a = self.BitwiseAnd()
-        while self.Peak in ['|']:
+        while self.Peak == '|':
             op = self.Consume(self.Peak)
             b = self.BitwiseAnd()
             a = Binop(a, op.typ, b, op.loc)
@@ -329,7 +309,7 @@
 
     def BitwiseAnd(self):
         a = self.CastExpression()
-        while self.Peak in ['&']:
+        while self.Peak == '&':
             op = self.Consume(self.Peak)
             b = self.CastExpression()
             a = Binop(a, op.typ, b, op.loc)
@@ -383,12 +363,10 @@
                 elif self.hasConsumed('->'):
                     field = self.Consume('ID')
                     pfe = Deref(pfe, pfe.loc)
-                    pfe = FieldRef(pfe, field.val, field.loc)
+                    pfe = Member(pfe, field.val, field.loc)
                 elif self.hasConsumed('.'):
                     field = self.Consume('ID')
-                    pfe = FieldRef(pfe, field.val, field.loc)
-                else:
-                    raise Exception()
+                    pfe = Member(pfe, field.val, field.loc)
         return pfe
 
     def PrimaryExpression(self):
@@ -409,6 +387,5 @@
             val = self.Consume('false')
             return Literal(False, val.loc)
         elif self.Peak == 'ID':
-            d = self.parseDesignator()
-            return VariableUse(d, d.loc)
+            return self.parseDesignator()
         self.Error('Expected NUM, ID or (expr), got {0}'.format(self.Peak))
--- a/python/ppci/c3/scope.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ppci/c3/scope.py	Mon Dec 09 19:00:21 2013 +0100
@@ -1,8 +1,9 @@
-from . import astnodes
+from .astnodes import Constant, Variable, Function, BaseType
 
 
 class Scope:
-    """ A scope contains all symbols in a scope """
+    """ A scope contains all symbols in a scope. It also has a parent scope,
+        when looking for a symbol, also the parent scopes are checked. """
     def __init__(self, parent=None):
         self.symbols = {}
         self.parent = parent
@@ -18,53 +19,58 @@
 
     @property
     def Constants(self):
-        return [s for s in self.Syms if type(s) is astnodes.Constant]
+        return [s for s in self.Syms if type(s) is Constant]
 
     @property
     def Variables(self):
-        return [s for s in self.Syms if isinstance(s, astnodes.Variable)]
+        return [s for s in self.Syms if isinstance(s, Variable)]
 
     @property
     def Functions(self):
-        return [s for s in self.Syms if type(s) is astnodes.Function]
+        return [s for s in self.Syms if type(s) is Function]
 
     def getSymbol(self, name):
         if name in self.symbols:
             return self.symbols[name]
         # Look for symbol:
-        if self.parent:
+        elif self.parent:
             return self.parent.getSymbol(name)
-        raise CompilerException("Symbol {0} not found".format(name), name.loc)
+        else:
+            raise KeyError(name)
+
+    def __getitem__(self, key):
+        return self.getSymbol(key)
 
     def hasSymbol(self, name):
         if name in self.symbols:
             return True
-        if self.parent:
+        elif self.parent:
             return self.parent.hasSymbol(name)
-        return False
+        else:
+            return False
+
+    def __contains__(self, name):
+        return self.hasSymbol(name)
 
     def addSymbol(self, sym):
+        assert sym.name not in self.symbols
         self.symbols[sym.name] = sym
 
     def __repr__(self):
         return 'Scope with {} symbols'.format(len(self.symbols))
 
 
-def createBuiltins(scope):
+def createTopScope(target):
+    scope = Scope()
     for tn in ['u64', 'u32', 'u16', 'u8']:
-        scope.addSymbol(astnodes.BaseType(tn))
-    for t in [intType, doubleType, voidType, boolType, stringType, byteType]:
-        scope.addSymbol(t)
-
-# buildin types:
-intType = astnodes.BaseType('int')
-intType.bytesize = 4
-doubleType = astnodes.BaseType('double')
-voidType = astnodes.BaseType('void')
-boolType = astnodes.BaseType('bool')
-stringType = astnodes.BaseType('string')
-byteType = astnodes.BaseType('byte')
-
-# Create top level scope:
-topScope = Scope()
-createBuiltins(topScope)
+        scope.addSymbol(BaseType(tn))
+    # buildin types:
+    intType = BaseType('int')
+    intType.bytesize = target.byte_sizes['int']
+    scope.addSymbol(intType)
+    scope.addSymbol(BaseType('double'))
+    scope.addSymbol(BaseType('void'))
+    scope.addSymbol(BaseType('bool'))
+    scope.addSymbol(BaseType('string'))
+    scope.addSymbol(BaseType('byte'))
+    return scope
--- a/python/ppci/c3/visitor.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/ppci/c3/visitor.py	Mon Dec 09 19:00:21 2013 +0100
@@ -12,7 +12,7 @@
         self.do(node)
 
     def do(self, node):
-        # Run visitor:
+        # Run pre function:
         if self.f_pre:
             self.f_pre(node)
 
@@ -23,6 +23,7 @@
         elif type(node) is Function:
             for s in node.declarations:
                 self.do(s)
+            self.do(node.typ)
             self.do(node.body)
         elif type(node) is CompoundStatement:
             for s in node.statements:
@@ -30,11 +31,11 @@
         elif type(node) is IfStatement:
             self.do(node.condition)
             self.do(node.truestatement)
-            if node.falsestatement:
-                self.do(node.falsestatement)
+            self.do(node.falsestatement)
         elif type(node) is FunctionCall:
             for arg in node.args:
                 self.do(arg)
+            self.do(node.proc)
         elif type(node) is Assignment:
             self.do(node.lval)
             self.do(node.rval)
@@ -49,14 +50,26 @@
             self.do(node.ex)
         elif type(node) is TypeCast:
             self.do(node.a)
-        elif type(node) is FieldRef:
+        elif type(node) is Member:
             self.do(node.base)
         elif type(node) is Deref:
             self.do(node.ptr)
         elif type(node) is Constant:
             self.do(node.value)
-        elif type(node) in [VariableUse, Variable, Literal, FunctionType,
-                            DefinedType, FormalParameter, LocalVariable]:
+        elif type(node) is DefinedType:
+            self.do(node.typ)
+        elif isinstance(node, Variable):
+            self.do(node.typ)
+        elif type(node) is PointerType:
+            self.do(node.ptype)
+        elif type(node) is StructureType:
+            for m in node.mems:
+                self.do(m.typ)
+        elif type(node) is FunctionType:
+            for pt in node.parametertypes:
+                self.do(pt)
+            self.do(node.returntype)
+        elif type(node) in [Identifier, Literal, EmptyStatement]:
             # Those nodes do not have child nodes.
             pass
         elif type(node) is WhileStatement:
--- a/python/target/basetarget.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/target/basetarget.py	Mon Dec 09 19:00:21 2013 +0100
@@ -141,6 +141,7 @@
         self.desc = desc
         self.registers = []
         self.instructions = []
+        self.byte_sizes = {'int':4}  # For front end!
 
     def instruction(self, cls):
         """ Decorator function that registers an instruction to this target """
--- a/python/utils/hexfile.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/utils/hexfile.py	Mon Dec 09 19:00:21 2013 +0100
@@ -81,7 +81,7 @@
                 raise HexFileException('record type {0} not implemented'.format(typ))
 
     def __repr__(self):
-        size = sum(len(r.data) for r in self.regions)
+        size = sum(r.Size for r in self.regions)
         return 'Hexfile containing {} bytes'.format(size)
 
     def dump(self):
@@ -150,5 +150,9 @@
         self.data = self.data + d
 
     @property
+    def Size(self):
+        return len(self.data)
+
+    @property
     def EndAddress(self):
         return self.address + len(self.data)
--- a/python/zcc.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/python/zcc.py	Mon Dec 09 19:00:21 2013 +0100
@@ -64,7 +64,6 @@
     for ircode in c3b.build(srcs, imps):
         if not ircode:
             return
-
         # Optimization passes, TODO
 
         if dumpir:
--- a/test/runtests.sh	Fri Dec 06 13:50:38 2013 +0100
+++ b/test/runtests.sh	Mon Dec 09 19:00:21 2013 +0100
@@ -2,7 +2,8 @@
 
 export PYTHONPATH=$PYTHONPATH:`pwd`/../python
 
-if [ $1 == "loop" ]; then
+if [ "$1" == "loop" ]
+then
   DIR=..
   while :; do
     python -m unittest
--- a/test/testc3.py	Fri Dec 06 13:50:38 2013 +0100
+++ b/test/testc3.py	Mon Dec 09 19:00:21 2013 +0100
@@ -45,23 +45,35 @@
         self.builder = Builder(self.diag, SimpleTarget())
         self.diag.clear()
 
+    def makeFileList(self, snippet):
+        """ Try to make a list with opened files """
+        if type(snippet) is list:
+            l2 = []
+            for s in snippet:
+                if type(s) is str:
+                    l2.append(io.StringIO(s))
+                else:
+                    l2.append(s)
+            return l2
+        else:
+            return [io.StringIO(snippet)]
+
     def expectErrors(self, snippet, rows):
         """ Helper to test for expected errors on rows """
         ircode = list(self.builder.build([io.StringIO(snippet)]))
         actualErrors = [err.row for err in self.diag.diags]
         if rows != actualErrors:
-            self.diag.printErrors(snippet)
+            self.diag.printErrors()
         self.assertSequenceEqual(rows, actualErrors)
         # self.assertFalse(all(ircode))
 
     def expectOK(self, snippet):
-        if type(snippet) is list:
-            ircode = self.builder.build(snippet)
-        else:
-            ircode = self.builder.build([io.StringIO(snippet)])
-        if not ircode:
-            self.diag.printErrors(snippet)
+        """ Expect a snippet to be OK """
+        ircode = list(self.builder.build(self.makeFileList(snippet)))
+        if len(self.diag.diags) > 0:
+            self.diag.printErrors()
         self.assertTrue(all(ircode))
+        self.assertEqual(0, len(self.diag.diags))
         return ircode
 
     def testPackage(self):
@@ -70,9 +82,9 @@
         """
         p2 = """module p2;
         import p1;
-        var A b;
+        var p1.A b;
         """
-        self.expectOK([io.StringIO(s) for s in (p1, p2)])
+        self.expectOK([p1, p2])
 
     def testPackageMutual(self):
         p1 = """module p1;
@@ -84,13 +96,13 @@
         import p1;
         var p1.A a;
         """
-        self.expectOK([io.StringIO(s) for s in (p1, p2)])
+        self.expectOK([p1, p2])
 
     def testPackageNotExists(self):
         p1 = """module p1;
         import p23;
         """
-        self.expectOK([io.StringIO(p1)])
+        self.expectErrors(p1, [0])
 
     def testFunctArgs(self):
         snippet = """
@@ -177,7 +189,8 @@
         var int a;
         function void t()
          {
-         var int i = 0;
+         var int i;
+         i = 0;
          while (i < 1054)
          {
             i = i + 3;