Statics are always writeable. Statics are always meaningful.
Chris Pressey
4 years ago
50 | 50 | |
51 | 51 | class IncompatibleConstraintsError(ConstraintsError): |
52 | 52 | pass |
53 | ||
54 | ||
55 | def routine_has_static(routine, ref): | |
56 | if not hasattr(routine, 'statics'): | |
57 | return False | |
58 | return ref in [static.location for static in routine.statics] | |
53 | 59 | |
54 | 60 | |
55 | 61 | class Context(object): |
111 | 117 | def assert_meaningful(self, *refs, **kwargs): |
112 | 118 | exception_class = kwargs.get('exception_class', UnmeaningfulReadError) |
113 | 119 | for ref in refs: |
120 | # statics are always meaningful | |
121 | if routine_has_static(self.routine, ref): | |
122 | continue | |
114 | 123 | if ref.is_constant() or ref in self.routines: |
115 | 124 | pass |
116 | 125 | elif isinstance(ref, LocationRef): |
128 | 137 | def assert_writeable(self, *refs, **kwargs): |
129 | 138 | exception_class = kwargs.get('exception_class', ForbiddenWriteError) |
130 | 139 | for ref in refs: |
140 | # statics are always writeable | |
141 | if routine_has_static(self.routine, ref): | |
142 | continue | |
131 | 143 | if ref not in self._writeable: |
132 | 144 | message = '%s in %s' % (ref.name, self.routine.name) |
133 | 145 | if kwargs.get('message'): |
230 | 242 | for ref in type_.outputs: |
231 | 243 | context.assert_meaningful(ref, exception_class=UnmeaningfulOutputError) |
232 | 244 | for ref in context.each_touched(): |
233 | if ref not in type_.outputs and ref not in type_.trashes: | |
245 | if ref not in type_.outputs and ref not in type_.trashes and not routine_has_static(routine, ref): | |
234 | 246 | message = '%s in %s' % (ref.name, routine.name) |
235 | 247 | raise ForbiddenWriteError(message) |
236 | 248 | self.current_routine = None |
144 | 144 | # just to be sure. |
145 | 145 | equal = isinstance(other, self.__class__) and other.name == self.name |
146 | 146 | if equal: |
147 | assert other.type == self.type | |
147 | assert other.type == self.type, repr((self, other)) | |
148 | 148 | return equal |
149 | 149 | |
150 | 150 | def __hash__(self): |
12 | 12 | def __init__(self, ast_node, model): |
13 | 13 | self.ast_node = ast_node |
14 | 14 | self.model = model |
15 | ||
16 | def __repr__(self): | |
17 | return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model) | |
15 | 18 | |
16 | 19 | |
17 | 20 | class Parser(object): |
220 | 223 | else: |
221 | 224 | statics = self.statics() |
222 | 225 | |
223 | self.current_statics = {} | |
224 | for defn in statics: | |
225 | name = defn.name | |
226 | if name in self.symbols or name in self.current_statics: | |
227 | raise SyntaxError('Symbol "%s" already declared' % name) | |
228 | self.current_statics[name] = SymEntry(defn, defn.location) | |
226 | self.current_statics = self.compose_statics_dict(statics) | |
229 | 227 | block = self.block() |
230 | 228 | self.current_statics = {} |
231 | 229 | |
235 | 233 | name=name, block=block, addr=addr, |
236 | 234 | location=location, statics=statics |
237 | 235 | ) |
236 | ||
237 | def compose_statics_dict(self, statics): | |
238 | c = {} | |
239 | for defn in statics: | |
240 | name = defn.name | |
241 | if name in self.symbols or name in self.current_statics: | |
242 | raise SyntaxError('Symbol "%s" already declared' % name) | |
243 | c[name] = SymEntry(defn, defn.location) | |
244 | return c | |
238 | 245 | |
239 | 246 | def labels(self): |
240 | 247 | accum = [] |
2282 | 2282 | | copy foo, vec |
2283 | 2283 | | } |
2284 | 2284 | = ok |
2285 | ||
2286 | ### static ### | |
2287 | ||
2288 | When memory locations are defined static to a routine, they cannot be | |
2289 | directly input, nor directly output; and since they are always initialized, | |
2290 | they cannot be trashed. Thus, they really don't participate in the analysis. | |
2291 | ||
2292 | | define foo routine | |
2293 | | inputs x | |
2294 | | outputs x | |
2295 | | trashes z, n | |
2296 | | static byte t : 0 | |
2297 | | { | |
2298 | | st x, t | |
2299 | | inc t | |
2300 | | ld x, t | |
2301 | | } | |
2302 | | | |
2303 | | define main routine | |
2304 | | trashes a, x, z, n | |
2305 | | static byte t : 0 | |
2306 | | { | |
2307 | | ld x, t | |
2308 | | call foo | |
2309 | | } | |
2310 | = ok |