0 | 0 |
# encoding: UTF-8
|
1 | 1 |
|
2 | |
from sixtypical.ast import Program, Routine, Block, Instr, SingleOp, If, Repeat, For, WithInterruptsOff
|
|
2 |
from sixtypical.ast import Program, Routine, Block, Instr, SingleOp, If, Repeat, For, WithInterruptsOff, Save
|
3 | 3 |
from sixtypical.model import (
|
4 | 4 |
TYPE_BYTE, TYPE_WORD,
|
5 | 5 |
TableType, BufferType, PointerType, VectorType, RoutineType,
|
|
268 | 268 |
self._writeable.remove(ref)
|
269 | 269 |
|
270 | 270 |
def set_writeable(self, *refs):
|
271 | |
"""Intended to be used for implementing analyzing `for`."""
|
|
271 |
"""Intended to be used for implementing analyzing `for`, but also used in `save`."""
|
272 | 272 |
for ref in refs:
|
273 | 273 |
self._writeable.add(ref)
|
274 | 274 |
|
|
290 | 290 |
self.assert_meaningful(dest.index)
|
291 | 291 |
self.assert_in_range(dest.index, dest.ref)
|
292 | 292 |
self.set_written(dest.ref)
|
|
293 |
|
|
294 |
def extract(self, location):
|
|
295 |
"""Used in `save`."""
|
|
296 |
baton = (
|
|
297 |
location,
|
|
298 |
location in self._touched,
|
|
299 |
self._range.get(location, None),
|
|
300 |
location in self._writeable,
|
|
301 |
)
|
|
302 |
|
|
303 |
if location in self._touched:
|
|
304 |
self._touched.remove(location)
|
|
305 |
self.set_unmeaningful(location)
|
|
306 |
self.set_writeable(location)
|
|
307 |
|
|
308 |
return baton
|
|
309 |
|
|
310 |
def re_introduce(self, baton):
|
|
311 |
"""Used in `save`."""
|
|
312 |
location, was_touched, was_range, was_writeable = baton
|
|
313 |
|
|
314 |
if was_touched:
|
|
315 |
self._touched.add(location)
|
|
316 |
elif location in self._touched:
|
|
317 |
self._touched.remove(location)
|
|
318 |
|
|
319 |
if was_range is not None:
|
|
320 |
self._range[location] = was_range
|
|
321 |
elif location in self._range:
|
|
322 |
del self._range[location]
|
|
323 |
|
|
324 |
if was_writeable:
|
|
325 |
self._writeable.add(location)
|
|
326 |
elif location in self._writeable:
|
|
327 |
self._writeable.remove(location)
|
293 | 328 |
|
294 | 329 |
|
295 | 330 |
class Analyzer(object):
|
|
384 | 419 |
self.analyze_for(instr, context)
|
385 | 420 |
elif isinstance(instr, WithInterruptsOff):
|
386 | 421 |
self.analyze_block(instr.block, context)
|
|
422 |
elif isinstance(instr, Save):
|
|
423 |
self.analyze_save(instr, context)
|
387 | 424 |
else:
|
388 | 425 |
raise NotImplementedError
|
389 | 426 |
|
|
729 | 766 |
# after it is executed, we know the range of the loop variable.
|
730 | 767 |
context.set_range(instr.dest, instr.final, instr.final)
|
731 | 768 |
context.set_writeable(instr.dest)
|
|
769 |
|
|
770 |
def analyze_save(self, instr, context):
|
|
771 |
if len(instr.locations) != 1:
|
|
772 |
raise NotImplementedError("Only 1 location in save is supported right now")
|
|
773 |
location = instr.locations[0]
|
|
774 |
|
|
775 |
baton = context.extract(location)
|
|
776 |
self.analyze_block(instr.block, context)
|
|
777 |
# TODO assert no goto was encountered
|
|
778 |
context.re_introduce(baton)
|