Mercurial > lcfOS
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 = """