# HG changeset patch # User Windel Bouwman # Date 1373314904 -7200 # Node ID 848c4b15fd0be76ce040e0eb1acf3777fe052494 # Parent 3f6c30a5d234a5f649d1870e33aac5d136f51054 pointers diff -r 3f6c30a5d234 -r 848c4b15fd0b python/c3/astnodes.py --- a/python/c3/astnodes.py Sat Jul 06 21:32:20 2013 +0200 +++ b/python/c3/astnodes.py Mon Jul 08 22:21:44 2013 +0200 @@ -74,6 +74,9 @@ def __repr__(self): return 'Named type {0} of type {1}'.format(self.name, self.typ) +#class TypeCast(Node): +# def __init__(self, + # Variables, parameters, local variables, constants: class Symbol(Node): def __init__(self, name): diff -r 3f6c30a5d234 -r 848c4b15fd0b python/c3/codegenerator.py --- a/python/c3/codegenerator.py Sat Jul 06 21:32:20 2013 +0200 +++ b/python/c3/codegenerator.py Mon Jul 08 22:21:44 2013 +0200 @@ -51,12 +51,13 @@ def genCode(self, code): if type(code) is astnodes.CompoundStatement: - for s in code.statements: - self.genCode(s) + for s in code.statements: + self.genCode(s) elif type(code) is astnodes.Assignment: re = self.genExprCode(code.rval) # TODO: Handle pointers - loc = self.varMap[code.lval.target] + loc = self.genExprCode(code.lval) + # determine location of variable self.builder.addIns(ir.Store(loc, re)) elif type(code) is astnodes.IfStatement: bbtrue = self.builder.newBB() @@ -70,9 +71,6 @@ self.genCode(code.falsestatement) self.builder.addIns(ir.Branch(te)) self.builder.setBB(te) - elif type(code) is astnodes.FunctionCall: - print('TODO') - pass elif type(code) is astnodes.EmptyStatement: pass elif type(code) is astnodes.ReturnStatement: @@ -126,9 +124,9 @@ if type(expr) is astnodes.Binop: ra = self.genExprCode(expr.a) rb = self.genExprCode(expr.b) - ops = ['+', '-', '*', '/'] + ops = ['+', '-', '*', '/', '|', '&'] if expr.op in ops: - tmpnames = {'+':'addtmp', '-':'subtmp', '*': 'multmp', '/':'divtmp'} + tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', '&':'and'} tmp = self.builder.newTmp(tmpnames[expr.op]) op = expr.op ins = ir.BinaryOperator(tmp, op, ra, rb) diff -r 3f6c30a5d234 -r 848c4b15fd0b python/c3/examples/cast.c3 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/c3/examples/cast.c3 Mon Jul 08 22:21:44 2013 +0200 @@ -0,0 +1,18 @@ + +/* + Demo of how to type cast +*/ + +package castdemo; + +function int testcast() +{ + var int a; + var int* b; + a = 3; + + b = cast(a); + + return 0; +} + diff -r 3f6c30a5d234 -r 848c4b15fd0b python/c3/lexer.py --- a/python/c3/lexer.py Sat Jul 06 21:32:20 2013 +0200 +++ b/python/c3/lexer.py Mon Jul 08 22:21:44 2013 +0200 @@ -9,7 +9,7 @@ keywords = ['and', 'or', 'not', 'true', 'false', \ 'else', 'if', 'while', 'return', \ 'function', 'var', 'type', 'const', \ - 'struct', \ + 'struct', 'cast', \ 'import', 'package' ] def tokenize(s): diff -r 3f6c30a5d234 -r 848c4b15fd0b python/c3/parser.py --- a/python/c3/parser.py Sat Jul 06 21:32:20 2013 +0200 +++ b/python/c3/parser.py Mon Jul 08 22:21:44 2013 +0200 @@ -276,30 +276,45 @@ return e def Term(self): - t = self.Factor() + t = self.BitwiseOr() while self.Peak in ['*', '/']: op = self.Consume(self.Peak) - t2 = self.Factor() + t2 = self.BitwiseOr() t = astnodes.Binop(t, op.typ, t2, op.loc) return t - - def Factor(self): - # TODO: eliminate this step? - return self.CastExpression() + + def BitwiseOr(self): + a = self.BitwiseAnd() + while self.Peak in ['|']: + op = self.Consume(self.Peak) + b = self.BitwiseAnd() + a = astnodes.Binop(a, op.typ, b, op.loc) + return a + + def BitwiseAnd(self): + a = self.CastExpression() + while self.Peak in ['&']: + op = self.Consume(self.Peak) + b = self.CastExpression() + a = astnodes.Binop(a, op.typ, b, op.loc) + return a # Domain of unary expressions: def CastExpression(self): - # TODO: cast conflicts with '(' expr ')' - if self.Peak == '(ii': - self.Consume('(') + # TODO: cast conflicts with '(' expr ')', so introduce extra keyword 'cast' + if self.Peak == 'cast': + self.Consume('cast') + self.Consume('<') print('TODO: implement type cast') - #rrrrr - self.parseTypeSpec() + t = self.parseTypeSpec() # Type + self.Consume('>') + self.Consume('(') + ce = self.CastExpression() self.Consume(')') - ce = self.CastExpression() + # TODO: use type spec here return ce else: return self.UnaryExpression() diff -r 3f6c30a5d234 -r 848c4b15fd0b python/c3/typecheck.py --- a/python/c3/typecheck.py Sat Jul 06 21:32:20 2013 +0200 +++ b/python/c3/typecheck.py Mon Jul 08 22:21:44 2013 +0200 @@ -31,11 +31,12 @@ if not equalTypes(sym.condition.typ, boolType): self.error('Condition must be of type {0}'.format(boolType), sym.condition.loc) elif type(sym) is Assignment: - if type(sym.lval.typ) is PointerType and sym.rval.typ == intType: - print('special case, int to pointer is ok for now') - # TODO: add cast instruction? - elif not equalTypes(sym.lval.typ, sym.rval.typ): - self.error('Cannot assign {0} to {1}'.format(sym.rval.typ, sym.lval.typ), sym.loc) + if not equalTypes(sym.lval.typ, sym.rval.typ): + self.error('Cannot assign {0} to {1}'.format(sym.rval.typ, sym.lval.typ), sym.loc) + if not sym.lval.lvalue: + self.error('No valid lvalue {}'.format(sym.lval), sym.lval.loc) + #if sym.rval.lvalue: + # self.error('Right hand side must be an rvalue', sym.rval.loc) elif type(sym) is ReturnStatement: pass elif type(sym) is FunctionCall: @@ -55,31 +56,37 @@ else: sym.typ = intType elif type(sym) is VariableUse: - if sym.target: - sym.typ = sym.target.typ - else: - sym.typ = intType + sym.lvalue = True + if sym.target: + sym.typ = sym.target.typ + else: + sym.typ = intType elif type(sym) is Literal: - 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 - else: - self.error('Unknown literal type', sym.loc) + 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 + else: + self.error('Unknown literal type', sym.loc) elif type(sym) is Unop: if sym.op == '&': sym.typ = PointerType(sym.a.typ) + sym.lvalue = False elif sym.op == '*': # pointer deref + sym.lvalue = True if type(sym.a.typ) is PointerType: sym.typ = sym.a.typ.ptype else: + sym.typ = intType self.error('Cannot dereference non-pointer type {}'.format(sym.a.typ), sym.loc) else: print('unknown unop', sym.op) elif type(sym) is Binop: + sym.lvalue = False if sym.op in ['+', '-', '*', '/']: if equalTypes(sym.a.typ, sym.b.typ): if equalTypes(sym.a.typ, intType): @@ -101,6 +108,9 @@ 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) + elif sym.op in ['|', '&']: + sym.typ = intType + # TODO: elaborate? else: sym.typ = voidType print('unknown binop', sym.op) diff -r 3f6c30a5d234 -r 848c4b15fd0b python/ir/instruction.py --- a/python/ir/instruction.py Sat Jul 06 21:32:20 2013 +0200 +++ b/python/ir/instruction.py Mon Jul 08 22:21:44 2013 +0200 @@ -140,7 +140,7 @@ self.location = location self.addUse(self.location) def __repr__(self): - return '{1} = [{0}]'.format(self.location, self.value) + return '{} <= [{}]'.format(self.value, self.location) class Store(Instruction): def __init__(self, location, value): @@ -152,7 +152,7 @@ self.addUse(value) self.addUse(location) def __repr__(self): - return '[{0}] = {1}'.format(self.location, self.value) + return '[{}] <= {}'.format(self.location, self.value) # Branching: class Branch(Terminator): @@ -174,6 +174,7 @@ self.a = a assert type(a) is Value self.cond = cond + assert cond in ['==', '<', '>'] self.b = b self.addUse(a) self.addUse(b) diff -r 3f6c30a5d234 -r 848c4b15fd0b python/stm32f4/blink.c3 --- a/python/stm32f4/blink.c3 Sat Jul 06 21:32:20 2013 +0200 +++ b/python/stm32f4/blink.c3 Mon Jul 08 22:21:44 2013 +0200 @@ -30,7 +30,7 @@ divider = 0; var int* RCC_AHB1ENR; - RCC_AHB1ENR = 0x40003022; + RCC_AHB1ENR = cast(0x40003022); *RCC_AHB1ENR = *RCC_AHB1ENR | 8943; /* RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; diff -r 3f6c30a5d234 -r 848c4b15fd0b python/testc3.py --- a/python/testc3.py Sat Jul 06 21:32:20 2013 +0200 +++ b/python/testc3.py Mon Jul 08 22:21:44 2013 +0200 @@ -212,13 +212,28 @@ var int* pa; function void t(int a, double b) { - pa = 2; pa = &a; *pa = 22; } """ self.expectOK(snippet) + def testPointerTypeInCorrect(self): + snippet = """ + package testpointerincorrect; + var int* pa; + function void t(int a, double b) + { + 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]) + @unittest.skip def testComplexType(self): snippet = """