Refactor to avoid storing LocationRefs in SymEntry.
Chris Pressey
3 years ago
11 | 11 | |
12 | 12 | |
13 | 13 | class SymEntry(object): |
14 | def __init__(self, ast_node, model): | |
14 | def __init__(self, ast_node, type_): | |
15 | 15 | self.ast_node = ast_node |
16 | self.model = model | |
16 | self.type_ = type_ | |
17 | 17 | |
18 | 18 | def __repr__(self): |
19 | return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model) | |
19 | return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.type_) | |
20 | 20 | |
21 | 21 | |
22 | 22 | class ForwardReference(object): |
34 | 34 | self.typedefs = {} # token -> Type AST |
35 | 35 | self.consts = {} # token -> Loc |
36 | 36 | |
37 | for token in ('a', 'x', 'y'): | |
38 | self.symbols[token] = SymEntry(None, LocationRef(TYPE_BYTE, token)) | |
39 | for token in ('c', 'z', 'n', 'v'): | |
40 | self.symbols[token] = SymEntry(None, LocationRef(TYPE_BIT, token)) | |
37 | for name in ('a', 'x', 'y'): | |
38 | self.symbols[name] = SymEntry(None, TYPE_BYTE) | |
39 | for name in ('c', 'z', 'n', 'v'): | |
40 | self.symbols[name] = SymEntry(None, TYPE_BIT) | |
41 | 41 | |
42 | 42 | def __str__(self): |
43 | 43 | return "Symbols: {}\nStatics: {}\nTypedefs: {}\nConsts: {}".format(self.symbols, self.statics, self.typedefs, self.consts) |
44 | 44 | |
45 | def fetch(self, name): | |
45 | def fetch_ref(self, name): | |
46 | 46 | if name in self.statics: |
47 | return self.statics[name].model | |
47 | return LocationRef(self.statics[name].type_, name) | |
48 | 48 | if name in self.symbols: |
49 | return self.symbols[name].model | |
49 | return LocationRef(self.symbols[name].type_, name) | |
50 | 50 | return None |
51 | 51 | |
52 | 52 | |
59 | 59 | self.scanner.syntax_error(msg) |
60 | 60 | |
61 | 61 | def lookup(self, name): |
62 | model = self.context.fetch(name) | |
62 | model = self.context.fetch_ref(name) | |
63 | 63 | if model is None: |
64 | 64 | self.syntax_error('Undefined symbol "{}"'.format(name)) |
65 | 65 | return model |
66 | 66 | |
67 | def declare(self, name, symentry, static=False): | |
68 | if self.context.fetch(name): | |
67 | def declare(self, name, ast_node, type_, static=False): | |
68 | if self.context.fetch_ref(name): | |
69 | 69 | self.syntax_error('Symbol "%s" already declared' % name) |
70 | 70 | if static: |
71 | self.context.statics[name] = symentry | |
72 | else: | |
73 | self.context.symbols[name] = symentry | |
71 | self.context.statics[name] = SymEntry(ast_node, type_) | |
72 | else: | |
73 | self.context.symbols[name] = SymEntry(ast_node, type_) | |
74 | 74 | |
75 | 75 | def clear_statics(self): |
76 | 76 | self.context.statics = {} |
128 | 128 | typenames = ['byte', 'word', 'table', 'vector', 'pointer'] # 'routine', |
129 | 129 | typenames.extend(self.context.typedefs.keys()) |
130 | 130 | while self.scanner.on(*typenames): |
131 | defn = self.defn() | |
132 | self.declare(defn.name, SymEntry(defn, defn.location)) | |
131 | type_, defn = self.defn() | |
132 | self.declare(defn.name, defn, type_) | |
133 | 133 | defns.append(defn) |
134 | 134 | while self.scanner.consume('define'): |
135 | 135 | name = self.scanner.token |
136 | 136 | self.scanner.scan() |
137 | routine = self.routine(name) | |
138 | self.declare(name, SymEntry(routine, routine.location)) | |
137 | type_, routine = self.routine(name) | |
138 | self.declare(name, routine, type_) | |
139 | 139 | routines.append(routine) |
140 | 140 | self.scanner.check_type('EOF') |
141 | 141 | |
190 | 190 | |
191 | 191 | location = LocationRef(type_, name) |
192 | 192 | |
193 | return Defn(self.scanner.line_number, name=name, addr=addr, initial=initial, location=location) | |
193 | return type_, Defn(self.scanner.line_number, name=name, addr=addr, initial=initial, location=location) | |
194 | 194 | |
195 | 195 | def const(self): |
196 | 196 | if self.scanner.token in ('on', 'off'): |
299 | 299 | |
300 | 300 | self.clear_statics() |
301 | 301 | for defn in statics: |
302 | self.declare(defn.name, SymEntry(defn, defn.location), static=True) | |
302 | self.declare(defn.name, defn, defn.location.type, static=True) | |
303 | 303 | block = self.block() |
304 | 304 | self.clear_statics() |
305 | 305 | |
306 | 306 | addr = None |
307 | 307 | location = LocationRef(type_, name) |
308 | return Routine( | |
308 | return type_, Routine( | |
309 | 309 | self.scanner.line_number, |
310 | 310 | name=name, block=block, addr=addr, |
311 | location=location, statics=statics | |
311 | location=location, statics=statics, | |
312 | 312 | ) |
313 | 313 | |
314 | 314 | def labels(self): |
338 | 338 | else: |
339 | 339 | name = self.scanner.token |
340 | 340 | self.scanner.scan() |
341 | loc = self.context.fetch(name) | |
341 | loc = self.context.fetch_ref(name) | |
342 | 342 | if loc: |
343 | 343 | return loc |
344 | 344 | else: |
370 | 370 | def statics(self): |
371 | 371 | defns = [] |
372 | 372 | while self.scanner.consume('static'): |
373 | defn = self.defn() | |
373 | type_, defn = self.defn() | |
374 | 374 | if defn.initial is None: |
375 | 375 | self.syntax_error("Static definition {} must have initial value".format(defn)) |
376 | 376 | defns.append(defn) |