Support save'ing user-defined locations.
Chris Pressey
4 years ago
334 | 334 | self.routines = {} |
335 | 335 | self.debug = debug |
336 | 336 | |
337 | def assert_type(self, type, *locations): | |
337 | def assert_type(self, type_, *locations): | |
338 | 338 | for location in locations: |
339 | if location.type != type: | |
339 | if location.type != type_: | |
340 | 340 | raise TypeMismatchError(self.current_routine, location.name) |
341 | 341 | |
342 | 342 | def assert_affected_within(self, name, affecting_type, limiting_type): |
463 | 463 | context.assert_meaningful(dest.ref, REG_Y) |
464 | 464 | context.set_written(dest.ref) |
465 | 465 | elif src.type != dest.type: |
466 | raise TypeMismatchError(instr, '{} and {}'.format(src, name)) | |
466 | raise TypeMismatchError(instr, '{} and {}'.format(src, dest)) | |
467 | 467 | else: |
468 | 468 | context.set_written(dest) |
469 | 469 | # FIXME: context.copy_range(src, dest) ? |
771 | 771 | if len(instr.locations) != 1: |
772 | 772 | raise NotImplementedError("Only 1 location in save is supported right now") |
773 | 773 | location = instr.locations[0] |
774 | self.assert_type(TYPE_BYTE, location) | |
774 | 775 | |
775 | 776 | baton = context.extract(location) |
776 | 777 | self.analyze_block(instr.block, context) |
635 | 635 | self.emitter.emit(PLA()) |
636 | 636 | self.emitter.emit(TAY()) |
637 | 637 | else: |
638 | raise NotImplementedError | |
638 | src_label = self.get_label(location.name) | |
639 | self.emitter.emit(LDA(Absolute(src_label))) | |
640 | self.emitter.emit(PHA()) | |
641 | self.compile_block(instr.block) | |
642 | self.emitter.emit(PLA()) | |
643 | self.emitter.emit(STA(Absolute(src_label))) |
2046 | 2046 | | } |
2047 | 2047 | = ok |
2048 | 2048 | |
2049 | Not just registers, but also user-defined locations can be saved. | |
2050 | ||
2051 | | byte foo | |
2052 | | | |
2053 | | routine main | |
2054 | | trashes a, z, n | |
2055 | | { | |
2056 | | save foo { | |
2057 | | st 5, foo | |
2058 | | } | |
2059 | | } | |
2060 | = ok | |
2061 | ||
2062 | But only if they are bytes. | |
2063 | ||
2064 | | word foo | |
2065 | | | |
2066 | | routine main | |
2067 | | trashes a, z, n | |
2068 | | { | |
2069 | | save foo { | |
2070 | | copy 555, foo | |
2071 | | } | |
2072 | | } | |
2073 | ? TypeMismatchError | |
2074 | ||
2075 | | byte table[16] tab | |
2076 | | | |
2077 | | routine main | |
2078 | | trashes a, y, z, n | |
2079 | | { | |
2080 | | save tab { | |
2081 | | ld y, 0 | |
2082 | | st 5, tab + y | |
2083 | | } | |
2084 | | } | |
2085 | ? TypeMismatchError | |
2086 | ||
2049 | 2087 | ### copy ### |
2050 | 2088 | |
2051 | 2089 | Can't `copy` from a memory location that isn't initialized. |
602 | 602 | = $0816 PLA |
603 | 603 | = $0817 RTS |
604 | 604 | |
605 | Compiling `save` on a user-defined location. | |
606 | ||
607 | | byte foo | |
608 | | routine main | |
609 | | trashes a, z, n | |
610 | | { | |
611 | | save foo { | |
612 | | ld a, 0 | |
613 | | st a, foo | |
614 | | } | |
615 | | } | |
616 | = $080D LDA $081B | |
617 | = $0810 PHA | |
618 | = $0811 LDA #$00 | |
619 | = $0813 STA $081B | |
620 | = $0816 PLA | |
621 | = $0817 STA $081B | |
622 | = $081A RTS | |
623 | ||
605 | 624 | Indexed access. |
606 | 625 | |
607 | 626 | | byte one |