git @ Cat's Eye Technologies SixtyPical / 4d1f9d0
First cut at implementing `save`. Only the most basic tests though. Chris Pressey 4 years ago
5 changed file(s) with 88 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
00 # encoding: UTF-8
11
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
33 from sixtypical.model import (
44 TYPE_BYTE, TYPE_WORD,
55 TableType, BufferType, PointerType, VectorType, RoutineType,
268268 self._writeable.remove(ref)
269269
270270 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`."""
272272 for ref in refs:
273273 self._writeable.add(ref)
274274
290290 self.assert_meaningful(dest.index)
291291 self.assert_in_range(dest.index, dest.ref)
292292 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)
293328
294329
295330 class Analyzer(object):
384419 self.analyze_for(instr, context)
385420 elif isinstance(instr, WithInterruptsOff):
386421 self.analyze_block(instr.block, context)
422 elif isinstance(instr, Save):
423 self.analyze_save(instr, context)
387424 else:
388425 raise NotImplementedError
389426
729766 # after it is executed, we know the range of the loop variable.
730767 context.set_range(instr.dest, instr.final, instr.final)
731768 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)
8989
9090 class WithInterruptsOff(Instr):
9191 child_attrs = ('block',)
92
93
94 class Save(Instr):
95 value_attrs = ('locations',)
96 child_attrs = ('block',)
00 # encoding: UTF-8
11
2 from sixtypical.ast import Program, Defn, Routine, Block, SingleOp, If, Repeat, For, WithInterruptsOff
2 from sixtypical.ast import Program, Defn, Routine, Block, SingleOp, If, Repeat, For, WithInterruptsOff, Save
33 from sixtypical.model import (
44 TYPE_BIT, TYPE_BYTE, TYPE_WORD,
55 RoutineType, VectorType, TableType, BufferType, PointerType,
469469 self.scanner.expect("off")
470470 block = self.block()
471471 return WithInterruptsOff(self.scanner.line_number, block=block)
472 elif self.scanner.consume("save"):
473 locations = self.locexprs()
474 block = self.block()
475 return Save(self.scanner.line_number, locations=locations, block=block)
472476 elif self.scanner.consume("trash"):
473477 dest = self.locexpr()
474478 return SingleOp(self.scanner.line_number, opcode='trash', src=None, dest=dest)
19371937 | }
19381938 ? UnmeaningfulReadError: y
19391939
1940 ### save ###
1941
1942 Basic neutral test.
1943
1944 | routine main
1945 | inputs a, x
1946 | outputs a, x
1947 | trashes z, n
1948 | {
1949 | save x {
1950 | ld a, 0
1951 | }
1952 | }
1953 = ok
1954
19401955 ### copy ###
19411956
19421957 Can't `copy` from a memory location that isn't initialized.
156156 | ld x, 15
157157 | for x down to 0 {
158158 | ld a, tab + x
159 | }
160 | }
161 = ok
162
163 Other blocks.
164
165 | routine main trashes a, x, c, z, v {
166 | with interrupts off {
167 | save a, x, c {
168 | ld a, 0
169 | }
170 | }
171 | save a, x, c {
172 | ld a, 0
159173 | }
160174 | }
161175 = ok