Mercurial > lcfOS
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):