Mercurial > lcfOS
comparison python/ppci/c3/codegenerator.py @ 308:2e7f55319858
Merged analyse into codegenerator
author | Windel Bouwman |
---|---|
date | Fri, 13 Dec 2013 11:53:29 +0100 |
parents | e609d5296ee9 |
children | ff665880a6b0 |
comparison
equal
deleted
inserted
replaced
307:e609d5296ee9 | 308:2e7f55319858 |
---|---|
1 import logging | 1 import logging |
2 from .. import ir | 2 from .. import ir |
3 from .. import irutils | 3 from .. import irutils |
4 from .astnodes import Symbol, Package, Variable, Function | 4 from . import astnodes as ast |
5 from .astnodes import Statement, Empty, Compound, If, While, Assignment | |
6 from .astnodes import ExpressionStatement, Return | |
7 from .astnodes import Expression, Binop, Unop, Identifier, Deref, Member | |
8 from .astnodes import Expression, FunctionCall, Literal, TypeCast | |
9 from .astnodes import Type, DefinedType, BaseType, PointerType, StructureType | |
10 | |
11 from ppci import CompilerError | |
12 | 5 |
13 | 6 |
14 class SemanticError(Exception): | 7 class SemanticError(Exception): |
8 """ Error thrown when a semantic issue is observed """ | |
15 def __init__(self, msg, loc): | 9 def __init__(self, msg, loc): |
10 super().__init__() | |
16 self.msg = msg | 11 self.msg = msg |
17 self.loc = loc | 12 self.loc = loc |
18 | 13 |
19 | 14 |
20 class CodeGenerator(irutils.Builder): | 15 class CodeGenerator(irutils.Builder): |
31 def __init__(self, diag): | 26 def __init__(self, diag): |
32 self.logger = logging.getLogger('c3cgen') | 27 self.logger = logging.getLogger('c3cgen') |
33 self.diag = diag | 28 self.diag = diag |
34 | 29 |
35 def gencode(self, pkg): | 30 def gencode(self, pkg): |
31 """ Generate code for a single module """ | |
36 self.prepare() | 32 self.prepare() |
37 assert type(pkg) is Package | 33 assert type(pkg) is ast.Package |
38 self.pkg = pkg | 34 self.pkg = pkg |
39 self.intType = pkg.scope['int'] | 35 self.intType = pkg.scope['int'] |
40 self.boolType = pkg.scope['bool'] | 36 self.boolType = pkg.scope['bool'] |
41 self.logger.info('Generating ir-code for {}'.format(pkg.name)) | 37 self.logger.info('Generating ir-code for {}'.format(pkg.name)) |
42 self.varMap = {} # Maps variables to storage locations. | 38 self.varMap = {} # Maps variables to storage locations. |
43 self.funcMap = {} | 39 self.funcMap = {} |
44 self.m = ir.Module(pkg.name) | 40 self.m = ir.Module(pkg.name) |
45 self.genModule(pkg) | |
46 return self.m | |
47 | |
48 def error(self, msg, loc=None): | |
49 self.pkg.ok = False | |
50 self.diag.error(msg, loc) | |
51 | |
52 # inner helpers: | |
53 def genModule(self, pkg): | |
54 # Take care of forward declarations: | |
55 try: | 41 try: |
56 for s in pkg.innerScope.Functions: | 42 for s in pkg.innerScope.Functions: |
57 f = self.newFunction(s.name) | 43 f = self.newFunction(s.name) |
58 self.funcMap[s] = f | 44 self.funcMap[s] = f |
59 for v in pkg.innerScope.Variables: | 45 for v in pkg.innerScope.Variables: |
60 self.varMap[v] = self.newTemp() | 46 self.varMap[v] = self.newTemp() |
61 for s in pkg.innerScope.Functions: | 47 for s in pkg.innerScope.Functions: |
62 self.genFunction(s) | 48 self.gen_function(s) |
63 except SemanticError as e: | 49 except SemanticError as e: |
64 self.error(e.msg, e.loc) | 50 self.error(e.msg, e.loc) |
51 return self.m | |
52 | |
53 def error(self, msg, loc=None): | |
54 self.pkg.ok = False | |
55 self.diag.error(msg, loc) | |
65 | 56 |
66 def checkType(self, t): | 57 def checkType(self, t): |
67 """ Verify the type is correct """ | 58 """ Verify the type is correct """ |
68 t = self.theType(t) | 59 t = self.theType(t) |
69 | 60 |
70 def genFunction(self, fn): | 61 def gen_function(self, fn): |
71 # TODO: handle arguments | 62 # TODO: handle arguments |
72 f = self.funcMap[fn] | 63 f = self.funcMap[fn] |
73 f.return_value = self.newTemp() | 64 f.return_value = self.newTemp() |
74 self.setFunction(f) | 65 self.setFunction(f) |
75 l2 = self.newBlock() | 66 l2 = self.newBlock() |
79 | 70 |
80 for sym in fn.innerScope: | 71 for sym in fn.innerScope: |
81 # TODO: handle parameters different | 72 # TODO: handle parameters different |
82 if sym.isParameter: | 73 if sym.isParameter: |
83 self.checkType(sym.typ) | 74 self.checkType(sym.typ) |
84 v = ir.Parameter(sym.name) | 75 variable = ir.Parameter(sym.name) |
85 f.addParameter(v) | 76 f.addParameter(variable) |
86 elif sym.isLocal: | 77 elif sym.isLocal: |
87 self.checkType(sym.typ) | 78 self.checkType(sym.typ) |
88 v = ir.LocalVariable(sym.name) | 79 variable = ir.LocalVariable(sym.name) |
89 f.addLocal(v) | 80 f.addLocal(variable) |
90 elif isinstance(sym, Variable): | 81 elif isinstance(sym, ast.Variable): |
91 self.checkType(sym.typ) | 82 self.checkType(sym.typ) |
92 v = ir.LocalVariable(sym.name) | 83 variable = ir.LocalVariable(sym.name) |
93 f.addLocal(v) | 84 f.addLocal(variable) |
94 else: | 85 else: |
95 #v = self.newTemp() | |
96 raise NotImplementedError('{}'.format(sym)) | 86 raise NotImplementedError('{}'.format(sym)) |
97 self.varMap[sym] = v | 87 self.varMap[sym] = variable |
98 | 88 |
99 self.genCode(fn.body) | 89 self.genCode(fn.body) |
100 # Set the default return value to zero: | |
101 # TBD: this may not be required? | |
102 self.emit(ir.Move(f.return_value, ir.Const(0))) | 90 self.emit(ir.Move(f.return_value, ir.Const(0))) |
103 self.emit(ir.Jump(f.epiloog)) | 91 self.emit(ir.Jump(f.epiloog)) |
104 self.setFunction(None) | 92 self.setFunction(None) |
105 | 93 |
106 def genCode(self, code): | 94 def genCode(self, code): |
95 """ Wrapper around gen_stmt to catch errors """ | |
107 try: | 96 try: |
108 self.genStmt(code) | 97 self.gen_stmt(code) |
109 except SemanticError as e: | 98 except SemanticError as e: |
110 self.error(e.msg, e.loc) | 99 self.error(e.msg, e.loc) |
111 | 100 |
112 def genStmt(self, code): | 101 def gen_stmt(self, code): |
113 assert isinstance(code, Statement) | 102 """ Generate code for a statement """ |
103 assert isinstance(code, ast.Statement) | |
114 self.setLoc(code.loc) | 104 self.setLoc(code.loc) |
115 if type(code) is Compound: | 105 if type(code) is ast.Compound: |
116 for s in code.statements: | 106 for s in code.statements: |
117 self.genCode(s) | 107 self.genCode(s) |
118 elif type(code) is Empty: | 108 elif type(code) is ast.Empty: |
119 pass | 109 pass |
120 elif type(code) is Assignment: | 110 elif type(code) is ast.Assignment: |
121 lval = self.genExprCode(code.lval) | 111 lval = self.genExprCode(code.lval) |
122 rval = self.genExprCode(code.rval) | 112 rval = self.genExprCode(code.rval) |
123 if not self.equalTypes(code.lval.typ, code.rval.typ): | 113 if not self.equalTypes(code.lval.typ, code.rval.typ): |
124 msg = 'Cannot assign {} to {}'.format(code.lval.typ, code.rval.typ) | 114 msg = 'Cannot assign {} to {}'.format(code.lval.typ, code.rval.typ) |
125 raise SemanticError(msg, code.loc) | 115 raise SemanticError(msg, code.loc) |
126 if not code.lval.lvalue: | 116 if not code.lval.lvalue: |
127 raise SemanticError('No valid lvalue {}'.format(code.lval), code.lval.loc) | 117 raise SemanticError('No valid lvalue {}'.format(code.lval), code.lval.loc) |
128 self.emit(ir.Move(lval, rval)) | 118 self.emit(ir.Move(lval, rval)) |
129 elif type(code) is ExpressionStatement: | 119 elif type(code) is ast.ExpressionStatement: |
130 self.emit(ir.Exp(self.genExprCode(code.ex))) | 120 self.emit(ir.Exp(self.genExprCode(code.ex))) |
131 elif type(code) is If: | 121 elif type(code) is ast.If: |
132 bbtrue = self.newBlock() | 122 bbtrue = self.newBlock() |
133 bbfalse = self.newBlock() | 123 bbfalse = self.newBlock() |
134 te = self.newBlock() | 124 te = self.newBlock() |
135 self.genCondCode(code.condition, bbtrue, bbfalse) | 125 self.gen_cond_code(code.condition, bbtrue, bbfalse) |
136 self.setBlock(bbtrue) | 126 self.setBlock(bbtrue) |
137 self.genCode(code.truestatement) | 127 self.genCode(code.truestatement) |
138 self.emit(ir.Jump(te)) | 128 self.emit(ir.Jump(te)) |
139 self.setBlock(bbfalse) | 129 self.setBlock(bbfalse) |
140 self.genCode(code.falsestatement) | 130 self.genCode(code.falsestatement) |
141 self.emit(ir.Jump(te)) | 131 self.emit(ir.Jump(te)) |
142 self.setBlock(te) | 132 self.setBlock(te) |
143 elif type(code) is Return: | 133 elif type(code) is ast.Return: |
144 re = self.genExprCode(code.expr) | 134 re = self.genExprCode(code.expr) |
145 self.emit(ir.Move(self.fn.return_value, re)) | 135 self.emit(ir.Move(self.fn.return_value, re)) |
146 self.emit(ir.Jump(self.fn.epiloog)) | 136 self.emit(ir.Jump(self.fn.epiloog)) |
147 b = self.newBlock() | 137 b = self.newBlock() |
148 self.setBlock(b) | 138 self.setBlock(b) |
149 elif type(code) is While: | 139 elif type(code) is ast.While: |
150 bbdo = self.newBlock() | 140 bbdo = self.newBlock() |
151 bbtest = self.newBlock() | 141 bbtest = self.newBlock() |
152 te = self.newBlock() | 142 te = self.newBlock() |
153 self.emit(ir.Jump(bbtest)) | 143 self.emit(ir.Jump(bbtest)) |
154 self.setBlock(bbtest) | 144 self.setBlock(bbtest) |
155 self.genCondCode(code.condition, bbdo, te) | 145 self.gen_cond_code(code.condition, bbdo, te) |
156 self.setBlock(bbdo) | 146 self.setBlock(bbdo) |
157 self.genCode(code.statement) | 147 self.genCode(code.statement) |
158 self.emit(ir.Jump(bbtest)) | 148 self.emit(ir.Jump(bbtest)) |
159 self.setBlock(te) | 149 self.setBlock(te) |
160 else: | 150 else: |
161 raise NotImplementedError('Unknown stmt {}'.format(code)) | 151 raise NotImplementedError('Unknown stmt {}'.format(code)) |
162 | 152 |
163 def genCondCode(self, expr, bbtrue, bbfalse): | 153 def gen_cond_code(self, expr, bbtrue, bbfalse): |
164 # Implement sequential logical operators | 154 """ Generate conditional logic. |
165 if type(expr) is Binop: | 155 Implement sequential logical operators. """ |
156 if type(expr) is ast.Binop: | |
166 if expr.op == 'or': | 157 if expr.op == 'or': |
167 l2 = self.newBlock() | 158 l2 = self.newBlock() |
168 self.genCondCode(expr.a, bbtrue, l2) | 159 self.gen_cond_code(expr.a, bbtrue, l2) |
169 if not equalTypes(expr.a.typ, self.boolType): | 160 if not self.equalTypes(expr.a.typ, self.boolType): |
170 raise SemanticError('Must be boolean', expr.a.loc) | 161 raise SemanticError('Must be boolean', expr.a.loc) |
171 self.setBlock(l2) | 162 self.setBlock(l2) |
172 self.genCondCode(expr.b, bbtrue, bbfalse) | 163 self.gen_cond_code(expr.b, bbtrue, bbfalse) |
173 if not equalTypes(expr.b.typ, self.boolType): | 164 if not self.equalTypes(expr.b.typ, self.boolType): |
174 raise SemanticError('Must be boolean', expr.b.loc) | 165 raise SemanticError('Must be boolean', expr.b.loc) |
175 elif expr.op == 'and': | 166 elif expr.op == 'and': |
176 l2 = self.newBlock() | 167 l2 = self.newBlock() |
177 self.genCondCode(expr.a, l2, bbfalse) | 168 self.gen_cond_code(expr.a, l2, bbfalse) |
178 if not equalTypes(expr.a.typ, self.boolType): | 169 if not self.equalTypes(expr.a.typ, self.boolType): |
179 self.error('Must be boolean', expr.a.loc) | 170 self.error('Must be boolean', expr.a.loc) |
180 self.setBlock(l2) | 171 self.setBlock(l2) |
181 self.genCondCode(expr.b, bbtrue, bbfalse) | 172 self.gen_cond_code(expr.b, bbtrue, bbfalse) |
182 if not equalTypes(expr.b.typ, self.boolType): | 173 if not self.equalTypes(expr.b.typ, self.boolType): |
183 raise SemanticError('Must be boolean', expr.b.loc) | 174 raise SemanticError('Must be boolean', expr.b.loc) |
184 elif expr.op in ['==', '>', '<', '!=', '<=', '>=']: | 175 elif expr.op in ['==', '>', '<', '!=', '<=', '>=']: |
185 ta = self.genExprCode(expr.a) | 176 ta = self.genExprCode(expr.a) |
186 tb = self.genExprCode(expr.b) | 177 tb = self.genExprCode(expr.b) |
187 if not self.equalTypes(expr.a.typ, expr.b.typ): | 178 if not self.equalTypes(expr.a.typ, expr.b.typ): |
189 .format(expr.a.typ, expr.b.typ), expr.loc) | 180 .format(expr.a.typ, expr.b.typ), expr.loc) |
190 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse)) | 181 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse)) |
191 else: | 182 else: |
192 raise NotImplementedError('Unknown condition {}'.format(expr)) | 183 raise NotImplementedError('Unknown condition {}'.format(expr)) |
193 expr.typ = self.boolType | 184 expr.typ = self.boolType |
194 elif type(expr) is Literal: | 185 elif type(expr) is ast.Literal: |
186 self.genExprCode(expr) | |
195 if expr.val: | 187 if expr.val: |
196 self.emit(ir.Jump(bbtrue)) | 188 self.emit(ir.Jump(bbtrue)) |
197 else: | 189 else: |
198 self.emit(ir.Jump(bbfalse)) | 190 self.emit(ir.Jump(bbfalse)) |
199 expr.typ = self.boolType | |
200 else: | 191 else: |
201 raise NotImplementedError('Unknown cond {}'.format(expr)) | 192 raise NotImplementedError('Unknown cond {}'.format(expr)) |
202 if not self.equalTypes(expr.typ, self.boolType): | 193 if not self.equalTypes(expr.typ, self.boolType): |
203 self.error('Condition must be boolean', expr.loc) | 194 self.error('Condition must be boolean', expr.loc) |
204 | 195 |
205 def genExprCode(self, expr): | 196 def genExprCode(self, expr): |
206 assert isinstance(expr, Expression) | 197 """ Generate code for an expression. Return the generated ir-value """ |
207 if type(expr) is Binop: | 198 assert isinstance(expr, ast.Expression) |
199 if type(expr) is ast.Binop: | |
208 expr.lvalue = False | 200 expr.lvalue = False |
209 if expr.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']: | 201 if expr.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']: |
210 ra = self.genExprCode(expr.a) | 202 ra = self.genExprCode(expr.a) |
211 rb = self.genExprCode(expr.b) | 203 rb = self.genExprCode(expr.b) |
212 if self.equalTypes(expr.a.typ, self.intType) and \ | 204 if self.equalTypes(expr.a.typ, self.intType) and \ |
213 self.equalTypes(expr.b.typ, self.intType): | 205 self.equalTypes(expr.b.typ, self.intType): |
214 expr.typ = expr.a.typ | 206 expr.typ = expr.a.typ |
215 else: | 207 else: |
216 # assume void here? TODO: throw exception! | |
217 raise SemanticError('Can only add integers', expr.loc) | 208 raise SemanticError('Can only add integers', expr.loc) |
218 else: | 209 else: |
219 raise NotImplementedError("Cannot use equality as expressions") | 210 raise NotImplementedError("Cannot use equality as expressions") |
220 return ir.Binop(ra, expr.op, rb) | 211 return ir.Binop(ra, expr.op, rb) |
221 elif type(expr) is Unop: | 212 elif type(expr) is ast.Unop: |
222 if expr.op == '&': | 213 if expr.op == '&': |
223 ra = self.genExprCode(expr.a) | 214 ra = self.genExprCode(expr.a) |
224 expr.typ = PointerType(expr.a.typ) | 215 expr.typ = ast.PointerType(expr.a.typ) |
225 if not expr.a.lvalue: | 216 if not expr.a.lvalue: |
226 raise SemanticError('No valid lvalue', expr.a.loc) | 217 raise SemanticError('No valid lvalue', expr.a.loc) |
227 expr.lvalue = False | 218 expr.lvalue = False |
228 assert type(ra) is ir.Mem | 219 assert type(ra) is ir.Mem |
229 return ra.e | 220 return ra.e |
230 else: | 221 else: |
231 raise NotImplementedError('Unknown unop {0}'.format(expr.op)) | 222 raise NotImplementedError('Unknown unop {0}'.format(expr.op)) |
232 elif type(expr) is Identifier: | 223 elif type(expr) is ast.Identifier: |
233 # Generate code for this identifier. | 224 # Generate code for this identifier. |
234 expr.lvalue = True | 225 expr.lvalue = True |
235 tg = self.resolveSymbol(expr) | 226 tg = self.resolveSymbol(expr) |
236 expr.kind = type(tg) | 227 expr.kind = type(tg) |
237 expr.typ = tg.typ | 228 expr.typ = tg.typ |
238 # This returns the dereferenced variable. | 229 # This returns the dereferenced variable. |
239 if type(tg) is Variable: | 230 if isinstance(tg, ast.Variable): |
240 # TODO: now parameters are handled different. Not nice? | |
241 return ir.Mem(self.varMap[tg]) | 231 return ir.Mem(self.varMap[tg]) |
242 else: | 232 else: |
243 return ir.Mem(self.varMap[tg]) | 233 raise NotImplementedError(str(tg)) |
244 elif type(expr) is Deref: | 234 elif type(expr) is ast.Deref: |
245 # dereference pointer type: | 235 # dereference pointer type: |
246 addr = self.genExprCode(expr.ptr) | 236 addr = self.genExprCode(expr.ptr) |
247 ptr_typ = self.theType(expr.ptr.typ) | 237 ptr_typ = self.theType(expr.ptr.typ) |
248 expr.lvalue = True | 238 expr.lvalue = True |
249 if type(ptr_typ) is PointerType: | 239 if type(ptr_typ) is ast.PointerType: |
250 expr.typ = ptr_typ.ptype | 240 expr.typ = ptr_typ.ptype |
251 return ir.Mem(addr) | 241 return ir.Mem(addr) |
252 else: | 242 else: |
253 raise SemanticError('Cannot deref non-pointer', expr.loc) | 243 raise SemanticError('Cannot deref non-pointer', expr.loc) |
254 expr.typ = self.intType | 244 elif type(expr) is ast.Member: |
255 return ir.Mem(ir.Const(0)) | |
256 elif type(expr) is Member: | |
257 base = self.genExprCode(expr.base) | 245 base = self.genExprCode(expr.base) |
258 expr.lvalue = expr.base.lvalue | 246 expr.lvalue = expr.base.lvalue |
259 basetype = self.theType(expr.base.typ) | 247 basetype = self.theType(expr.base.typ) |
260 if type(basetype) is StructureType: | 248 if type(basetype) is ast.StructureType: |
261 if basetype.hasField(expr.field): | 249 if basetype.hasField(expr.field): |
262 expr.typ = basetype.fieldType(expr.field) | 250 expr.typ = basetype.fieldType(expr.field) |
263 else: | 251 else: |
264 raise SemanticError('{} does not contain field {}' | 252 raise SemanticError('{} does not contain field {}' |
265 .format(basetype, expr.field), expr.loc) | 253 .format(basetype, expr.field), expr.loc) |
266 else: | 254 else: |
267 raise SemanticError('Cannot select field {} of non-structure type {}' | 255 raise SemanticError('Cannot select {} of non-structure type {}' |
268 .format(sym.field, basetype), sym.loc) | 256 .format(expr.field, basetype), expr.loc) |
269 | 257 |
270 assert type(base) is ir.Mem, type(base) | 258 assert type(base) is ir.Mem, type(base) |
271 base = base.e | |
272 bt = self.theType(expr.base.typ) | 259 bt = self.theType(expr.base.typ) |
273 offset = ir.Const(bt.fieldOffset(expr.field)) | 260 offset = ir.Const(bt.fieldOffset(expr.field)) |
274 return ir.Mem(ir.Add(base, offset)) | 261 return ir.Mem(ir.Add(base.e, offset)) |
275 elif type(expr) is Literal: | 262 elif type(expr) is ast.Literal: |
276 expr.lvalue = False | 263 expr.lvalue = False |
277 typemap = {int: 'int', float: 'double', bool: 'bool'} | 264 typemap = {int: 'int', float: 'double', bool: 'bool'} |
278 if type(expr.val) in typemap: | 265 if type(expr.val) in typemap: |
279 expr.typ = self.pkg.scope[typemap[type(expr.val)]] | 266 expr.typ = self.pkg.scope[typemap[type(expr.val)]] |
280 else: | 267 else: |
281 raise SemanticError('Unknown literal type {}'.format(expr.val)) | 268 raise SemanticError('Unknown literal type {}'.format(expr.val)) |
282 return ir.Const(expr.val) | 269 return ir.Const(expr.val) |
283 elif type(expr) is TypeCast: | 270 elif type(expr) is ast.TypeCast: |
284 # TODO: improve this mess: | 271 return self.gen_type_cast(expr) |
285 ar = self.genExprCode(expr.a) | 272 elif type(expr) is ast.FunctionCall: |
286 ft = self.theType(expr.a.typ) | 273 return self.gen_function_call(expr) |
287 tt = self.theType(expr.to_type) | |
288 if isinstance(ft, PointerType) and isinstance(tt, PointerType): | |
289 expr.typ = expr.to_type | |
290 return ar | |
291 elif type(ft) is BaseType and ft.name == 'int' and \ | |
292 isinstance(tt, PointerType): | |
293 expr.typ = expr.to_type | |
294 return ar | |
295 else: | |
296 self.error('Cannot cast {} to {}' | |
297 .format(ft, tt), expr.loc) | |
298 expr.typ = self.intType | |
299 return ir.Const(0) | |
300 elif type(expr) is FunctionCall: | |
301 # Evaluate the arguments: | |
302 args = [self.genExprCode(e) for e in expr.args] | |
303 # Check arguments: | |
304 if type(expr.proc) is Identifier: | |
305 tg = self.resolveSymbol(expr.proc) | |
306 else: | |
307 raise Exception() | |
308 assert type(tg) is Function | |
309 ftyp = tg.typ | |
310 fname = tg.name | |
311 ptypes = ftyp.parametertypes | |
312 if len(expr.args) != len(ptypes): | |
313 raise SemanticError('Function {2}: {0} arguments required, {1} given' | |
314 .format(len(ptypes), len(expr.args), fname), expr.loc) | |
315 for arg, at in zip(expr.args, ptypes): | |
316 if not self.equalTypes(arg.typ, at): | |
317 raise SemanticError('Got {0}, expected {1}' | |
318 .format(arg.typ, at), arg.loc) | |
319 # determine return type: | |
320 expr.typ = ftyp.returntype | |
321 return ir.Call(fname, args) | |
322 else: | 274 else: |
323 raise NotImplementedError('Unknown expr {}'.format(expr)) | 275 raise NotImplementedError('Unknown expr {}'.format(expr)) |
324 | 276 |
277 def gen_type_cast(self, expr): | |
278 """ Generate code for type casting """ | |
279 ar = self.genExprCode(expr.a) | |
280 from_type = self.theType(expr.a.typ) | |
281 to_type = self.theType(expr.to_type) | |
282 if isinstance(from_type, ast.PointerType) and isinstance(to_type, ast.PointerType): | |
283 expr.typ = expr.to_type | |
284 return ar | |
285 elif type(from_type) is ast.BaseType and from_type.name == 'int' and \ | |
286 isinstance(to_type, ast.PointerType): | |
287 expr.typ = expr.to_type | |
288 return ar | |
289 else: | |
290 raise SemanticError('Cannot cast {} to {}' | |
291 .format(from_type, to_type), expr.loc) | |
292 | |
293 def gen_function_call(self, expr): | |
294 """ Generate code for a function call """ | |
295 # Evaluate the arguments: | |
296 args = [self.genExprCode(e) for e in expr.args] | |
297 # Check arguments: | |
298 tg = self.resolveSymbol(expr.proc) | |
299 if type(tg) is not ast.Function: | |
300 raise SemanticError('cannot call {}'.format(tg)) | |
301 ftyp = tg.typ | |
302 fname = tg.name | |
303 ptypes = ftyp.parametertypes | |
304 if len(expr.args) != len(ptypes): | |
305 raise SemanticError('{} requires {} arguments, {} given' | |
306 .format(fname, len(ptypes), len(expr.args)), expr.loc) | |
307 for arg, at in zip(expr.args, ptypes): | |
308 if not self.equalTypes(arg.typ, at): | |
309 raise SemanticError('Got {}, expected {}' | |
310 .format(arg.typ, at), arg.loc) | |
311 # determine return type: | |
312 expr.typ = ftyp.returntype | |
313 return ir.Call(fname, args) | |
314 | |
325 def resolveSymbol(self, sym): | 315 def resolveSymbol(self, sym): |
326 assert type(sym) in [Identifier, Member] | 316 if type(sym) is ast.Member: |
327 if type(sym) is Member: | |
328 base = self.resolveSymbol(sym.base) | 317 base = self.resolveSymbol(sym.base) |
318 if type(base) is not ast.Package: | |
319 raise SemanticError('Base is not a package', sym.loc) | |
329 scope = base.innerScope | 320 scope = base.innerScope |
330 name = sym.field | 321 name = sym.field |
331 elif type(sym) is Identifier: | 322 elif type(sym) is ast.Identifier: |
332 scope = sym.scope | 323 scope = sym.scope |
333 name = sym.target | 324 name = sym.target |
334 else: | 325 else: |
335 raise NotImplementedError(str(sym)) | 326 raise NotImplementedError(str(sym)) |
336 if name in scope: | 327 if name in scope: |
337 s = scope[name] | 328 s = scope[name] |
338 else: | 329 else: |
339 raise SemanticError('{} undefined'.format(name), sym.loc) | 330 raise SemanticError('{} undefined'.format(name), sym.loc) |
340 assert isinstance(s, Symbol) | 331 assert isinstance(s, ast.Symbol) |
341 return s | 332 return s |
342 | 333 |
343 def theType(self, t): | 334 def theType(self, t): |
344 """ Recurse until a 'real' type is found """ | 335 """ Recurse until a 'real' type is found """ |
345 if type(t) is DefinedType: | 336 if type(t) is ast.DefinedType: |
346 t = self.theType(t.typ) | 337 t = self.theType(t.typ) |
347 elif type(t) is Identifier: | 338 elif type(t) in [ast.Identifier, ast.Member]: |
348 t = self.theType(self.resolveSymbol(t)) | 339 t = self.theType(self.resolveSymbol(t)) |
349 elif type(t) is Member: | 340 elif isinstance(t, ast.Type): |
350 # Possible when using types of modules: | |
351 t = self.theType(self.resolveSymbol(t)) | |
352 elif isinstance(t, Type): | |
353 pass | 341 pass |
354 else: | 342 else: |
355 raise NotImplementedError(str(t)) | 343 raise NotImplementedError(str(t)) |
356 assert isinstance(t, Type) | 344 assert isinstance(t, ast.Type) |
357 return t | 345 return t |
358 | 346 |
359 def equalTypes(self, a, b): | 347 def equalTypes(self, a, b): |
360 """ Compare types a and b for structural equavalence. """ | 348 """ Compare types a and b for structural equavalence. """ |
361 # Recurse into named types: | 349 # Recurse into named types: |
362 a = self.theType(a) | 350 a = self.theType(a) |
363 b = self.theType(b) | 351 b = self.theType(b) |
364 assert isinstance(a, Type) | 352 assert isinstance(a, ast.Type) |
365 assert isinstance(b, Type) | 353 assert isinstance(b, ast.Type) |
366 | 354 |
367 if type(a) is type(b): | 355 if type(a) is type(b): |
368 if type(a) is BaseType: | 356 if type(a) is ast.BaseType: |
369 return a.name == b.name | 357 return a.name == b.name |
370 elif type(a) is PointerType: | 358 elif type(a) is ast.PointerType: |
371 return self.equalTypes(a.ptype, b.ptype) | 359 return self.equalTypes(a.ptype, b.ptype) |
372 elif type(a) is StructureType: | 360 elif type(a) is ast.StructureType: |
373 if len(a.mems) != len(b.mems): | 361 if len(a.mems) != len(b.mems): |
374 return False | 362 return False |
375 return all(self.equalTypes(am.typ, bm.typ) for am, bm in | 363 return all(self.equalTypes(am.typ, bm.typ) for am, bm in |
376 zip(a.mems, b.mems)) | 364 zip(a.mems, b.mems)) |
377 else: | 365 else: |