Mercurial > lcfOS
annotate python/ppci/c3/astnodes.py @ 366:39bf68bf1891
Fix sample tests and deterministic build
author | Windel Bouwman |
---|---|
date | Fri, 21 Mar 2014 09:43:01 +0100 |
parents | 5477e499b039 |
children | 2ec730e45ea1 |
rev | line source |
---|---|
148 | 1 """ |
213 | 2 AST (abstract syntax tree) nodes for the c3 language. |
3 The tree is build by the parser. | |
4 Then it is checked | |
5 Finally code is generated from it. | |
148 | 6 """ |
7 | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
8 from ppci import SourceLocation |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
9 |
288 | 10 |
148 | 11 class Node: |
306 | 12 """ Base class of all nodes in a AST """ |
288 | 13 pass |
14 | |
148 | 15 |
300 | 16 # Variables, parameters, local variables, constants and named types: |
17 class Symbol(Node): | |
308 | 18 """ Symbol is the base class for all named things like variables, |
306 | 19 functions, constants and types and modules """ |
300 | 20 def __init__(self, name): |
21 self.name = name | |
22 self.refs = [] | |
23 | |
24 def addRef(self, r): | |
25 self.refs.append(r) | |
26 | |
27 @property | |
28 def References(self): | |
29 return self.refs | |
30 | |
31 | |
213 | 32 # Modules |
301 | 33 class Package(Symbol): |
213 | 34 def __init__(self, name, loc): |
301 | 35 super().__init__(name) |
213 | 36 self.loc = loc |
37 self.declarations = [] | |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
249
diff
changeset
|
38 self.imports = [] |
288 | 39 |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
316
diff
changeset
|
40 def add_declaration(self, decl): |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
316
diff
changeset
|
41 self.declarations.append(decl) |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
316
diff
changeset
|
42 if isinstance(decl, Function): |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
316
diff
changeset
|
43 decl.package = self |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
316
diff
changeset
|
44 |
213 | 45 def __repr__(self): |
284 | 46 return 'MODULE {}'.format(self.name) |
47 | |
213 | 48 |
149 | 49 class Type(Node): |
306 | 50 """ Base class of all types """ |
288 | 51 pass |
272 | 52 |
148 | 53 |
300 | 54 class NamedType(Type, Symbol): |
308 | 55 """ Some types are named, for example a user defined type (typedef) |
306 | 56 and built in types. That is why this class derives from both Type |
57 and Symbol. """ | |
272 | 58 def __init__(self, name): |
300 | 59 Symbol.__init__(self, name) |
60 | |
61 | |
62 class BaseType(NamedType): | |
306 | 63 """ Built in type """ |
300 | 64 def __init__(self, name): |
65 super().__init__(name) | |
272 | 66 |
67 def __repr__(self): | |
68 return '{}'.format(self.name) | |
69 | |
148 | 70 |
71 class FunctionType(Type): | |
306 | 72 """ Function blueprint, defines argument types and return type """ |
288 | 73 def __init__(self, parametertypes, returntype): |
74 self.parametertypes = parametertypes | |
75 self.returntype = returntype | |
76 | |
77 def __repr__(self): | |
78 params = ', '.join([str(v) for v in self.parametertypes]) | |
79 return '{1} f({0})'.format(params, self.returntype) | |
148 | 80 |
272 | 81 |
213 | 82 class PointerType(Type): |
288 | 83 """ A type that points to data of some other type """ |
213 | 84 def __init__(self, ptype): |
306 | 85 assert isinstance(ptype, Type) or isinstance(ptype, Expression) |
213 | 86 self.ptype = ptype |
288 | 87 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
88 def __repr__(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
89 return '({}*)'.format(self.ptype) |
213 | 90 |
230 | 91 |
227 | 92 class StructField: |
316 | 93 """ Field of a struct type """ |
227 | 94 def __init__(self, name, typ): |
306 | 95 assert type(name) is str |
227 | 96 self.name = name |
97 self.typ = typ | |
230 | 98 |
227 | 99 |
213 | 100 class StructureType(Type): |
306 | 101 """ Struct type consisting of several named members """ |
213 | 102 def __init__(self, mems): |
103 self.mems = mems | |
306 | 104 assert all(type(mem) is StructField for mem in mems) |
230 | 105 |
225 | 106 def hasField(self, name): |
227 | 107 for mem in self.mems: |
108 if name == mem.name: | |
225 | 109 return True |
110 return False | |
230 | 111 |
225 | 112 def fieldType(self, name): |
230 | 113 return self.findField(name).typ |
114 | |
115 def fieldOffset(self, name): | |
116 return self.findField(name).offset | |
117 | |
118 def findField(self, name): | |
227 | 119 for mem in self.mems: |
120 if name == mem.name: | |
230 | 121 return mem |
122 raise KeyError(name) | |
225 | 123 |
230 | 124 def __repr__(self): |
125 return 'STRUCT' | |
213 | 126 |
272 | 127 |
354 | 128 class ArrayType(Type): |
129 """ Array type """ | |
130 def __init__(self, element_type, size): | |
131 self.element_type = element_type | |
132 self.size = size | |
133 | |
134 def __repr__(self): | |
135 return 'ARRAY {}'.format(self.size) | |
136 | |
137 | |
300 | 138 class DefinedType(NamedType): |
288 | 139 """ A named type indicating another type """ |
225 | 140 def __init__(self, name, typ, loc): |
141 assert isinstance(name, str) | |
300 | 142 super().__init__(name) |
225 | 143 self.typ = typ |
144 self.loc = loc | |
230 | 145 |
225 | 146 def __repr__(self): |
147 return 'Named type {0} of type {1}'.format(self.name, self.typ) | |
148 | 148 |
221 | 149 |
148 | 150 class Constant(Symbol): |
316 | 151 """ Constant definition """ |
213 | 152 def __init__(self, name, typ, value): |
272 | 153 super().__init__(name) |
154 self.typ = typ | |
155 self.value = value | |
156 | |
213 | 157 def __repr__(self): |
272 | 158 return 'CONSTANT {0} = {1}'.format(self.name, self.value) |
159 | |
148 | 160 |
161 class Variable(Symbol): | |
272 | 162 def __init__(self, name, typ): |
163 super().__init__(name) | |
164 self.typ = typ | |
165 self.isLocal = False | |
166 self.isParameter = False | |
167 | |
168 def __repr__(self): | |
169 return 'Var {} [{}]'.format(self.name, self.typ) | |
170 | |
171 | |
172 class LocalVariable(Variable): | |
173 def __init__(self, name, typ): | |
174 super().__init__(name, typ) | |
175 self.isLocal = True | |
176 | |
177 | |
178 class FormalParameter(Variable): | |
179 def __init__(self, name, typ): | |
180 super().__init__(name, typ) | |
181 self.isParameter = True | |
182 | |
148 | 183 |
150 | 184 # Procedure types |
185 class Function(Symbol): | |
213 | 186 """ Actual implementation of a function """ |
187 def __init__(self, name, loc): | |
188 super().__init__(name) | |
189 self.loc = loc | |
215 | 190 self.declarations = [] |
213 | 191 |
336
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
316
diff
changeset
|
192 def add_declaration(self, decl): |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
316
diff
changeset
|
193 self.declarations.append(decl) |
d1ecc493384e
Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
Windel Bouwman
parents:
316
diff
changeset
|
194 |
213 | 195 def __repr__(self): |
217 | 196 return 'Func {}'.format(self.name) |
148 | 197 |
288 | 198 |
163 | 199 # Operations / Expressions: |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
200 class Expression(Node): |
230 | 201 def __init__(self, loc): |
202 self.loc = loc | |
203 | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
204 |
225 | 205 class Deref(Expression): |
206 def __init__(self, ptr, loc): | |
230 | 207 super().__init__(loc) |
225 | 208 assert isinstance(ptr, Expression) |
209 self.ptr = ptr | |
288 | 210 |
225 | 211 def __repr__(self): |
288 | 212 return 'DEREF {}'.format(self.ptr) |
225 | 213 |
230 | 214 |
215 class TypeCast(Expression): | |
216 def __init__(self, to_type, x, loc): | |
217 super().__init__(loc) | |
218 self.to_type = to_type | |
219 self.a = x | |
288 | 220 |
230 | 221 def __repr__(self): |
222 return 'TYPECAST {}'.format(self.to_type) | |
223 | |
224 | |
306 | 225 class Member(Expression): |
226 """ Field reference of some object, can also be package selection """ | |
225 | 227 def __init__(self, base, field, loc): |
230 | 228 super().__init__(loc) |
225 | 229 assert isinstance(base, Expression) |
230 assert isinstance(field, str) | |
231 self.base = base | |
232 self.field = field | |
288 | 233 |
225 | 234 def __repr__(self): |
306 | 235 return 'MEMBER {}.{}'.format(self.base, self.field) |
225 | 236 |
230 | 237 |
354 | 238 class Index(Expression): |
239 """ Index something, for example an array """ | |
240 def __init__(self, base, i, loc): | |
241 super().__init__(loc) | |
242 self.base = base | |
243 self.i = i | |
244 | |
245 def __repr__(self): | |
246 return 'Index {}'.format(self.i) | |
247 | |
248 | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
249 class Unop(Expression): |
306 | 250 """ Operation on one operand """ |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
251 def __init__(self, op, a, loc): |
230 | 252 super().__init__(loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
253 assert isinstance(a, Expression) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
254 assert isinstance(op, str) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
255 self.a = a |
230 | 256 self.op = op |
288 | 257 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
258 def __repr__(self): |
288 | 259 return 'UNOP {}'.format(self.op) |
260 | |
148 | 261 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
262 class Binop(Expression): |
306 | 263 """ Expression taking two operands and one operator """ |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
264 def __init__(self, a, op, b, loc): |
230 | 265 super().__init__(loc) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
266 assert isinstance(a, Expression), type(a) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
267 assert isinstance(b, Expression) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
268 assert isinstance(op, str) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
269 self.a = a |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
270 self.b = b |
288 | 271 self.op = op # Operation: '+', '-', '*', '/', 'mod' |
148 | 272 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
273 def __repr__(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
274 return 'BINOP {}'.format(self.op) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
275 |
288 | 276 |
306 | 277 class Identifier(Expression): |
278 """ Reference to some identifier, can be anything from package, variable | |
279 function or type, any named thing! """ | |
228 | 280 def __init__(self, target, loc): |
230 | 281 super().__init__(loc) |
228 | 282 self.target = target |
288 | 283 |
228 | 284 def __repr__(self): |
306 | 285 return 'ID {}'.format(self.target) |
163 | 286 |
284 | 287 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
288 class Literal(Expression): |
306 | 289 """ Constant value or string """ |
228 | 290 def __init__(self, val, loc): |
230 | 291 super().__init__(loc) |
228 | 292 self.val = val |
288 | 293 |
228 | 294 def __repr__(self): |
295 return 'LITERAL {}'.format(self.val) | |
150 | 296 |
284 | 297 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
298 class FunctionCall(Expression): |
306 | 299 """ Call to a some function """ |
228 | 300 def __init__(self, proc, args, loc): |
230 | 301 super().__init__(loc) |
228 | 302 self.proc = proc |
303 self.args = args | |
288 | 304 |
228 | 305 def __repr__(self): |
306 return 'CALL {0} '.format(self.proc) | |
148 | 307 |
284 | 308 |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
309 # Statements |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
310 class Statement(Node): |
306 | 311 """ Base class of all statements """ |
228 | 312 def __init__(self, loc): |
313 self.loc = loc | |
314 | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
315 |
307 | 316 class Empty(Statement): |
306 | 317 """ Empty statement which does nothing! """ |
318 def __init__(self): | |
319 super().__init__(None) | |
320 | |
321 def __repr__(self): | |
322 return 'NOP' | |
323 | |
324 | |
307 | 325 class Compound(Statement): |
306 | 326 """ Statement consisting of a sequence of other statements """ |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
327 def __init__(self, statements): |
249 | 328 super().__init__(None) |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
329 self.statements = statements |
228 | 330 for s in self.statements: |
331 assert isinstance(s, Statement) | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
332 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
333 def __repr__(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
334 return 'COMPOUND STATEMENT' |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
335 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
336 |
307 | 337 class Return(Statement): |
228 | 338 def __init__(self, expr, loc): |
339 super().__init__(loc) | |
340 self.expr = expr | |
341 | |
342 def __repr__(self): | |
343 return 'RETURN STATEMENT' | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
344 |
284 | 345 |
222 | 346 class Assignment(Statement): |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
347 def __init__(self, lval, rval, loc): |
228 | 348 super().__init__(loc) |
306 | 349 assert isinstance(lval, Expression) |
350 assert isinstance(rval, Expression) | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
351 self.lval = lval |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
352 self.rval = rval |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
353 |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
354 def __repr__(self): |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
355 return 'ASSIGNMENT' |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
356 |
288 | 357 |
222 | 358 class ExpressionStatement(Statement): |
359 def __init__(self, ex, loc): | |
228 | 360 super().__init__(loc) |
222 | 361 self.ex = ex |
228 | 362 |
222 | 363 def __repr__(self): |
364 return 'Epression' | |
365 | |
228 | 366 |
307 | 367 class If(Statement): |
228 | 368 def __init__(self, condition, truestatement, falsestatement, loc): |
369 super().__init__(loc) | |
370 self.condition = condition | |
371 self.truestatement = truestatement | |
372 self.falsestatement = falsestatement | |
373 | |
374 def __repr__(self): | |
375 return 'IF-statement' | |
376 | |
148 | 377 |
307 | 378 class While(Statement): |
228 | 379 def __init__(self, condition, statement, loc): |
380 super().__init__(loc) | |
381 self.condition = condition | |
382 self.statement = statement | |
148 | 383 |
228 | 384 def __repr__(self): |
385 return 'WHILE-statement' | |
315 | 386 |
387 | |
388 class For(Statement): | |
389 def __init__(self, init, condition, final, statement, loc): | |
390 super().__init__(loc) | |
391 self.init = init | |
392 self.condition = condition | |
393 self.final = final | |
394 self.statement = statement | |
395 | |
396 def __repr__(self): | |
397 return 'FOR-statement' |