Always analyze before compiling.
Chris Pressey
4 years ago
84 | 84 | ### And at some point... |
85 | 85 | |
86 | 86 | * Check that the buffer being read or written to through pointer, appears in approporiate inputs or outputs set. |
87 | * always analyze before executing or compiling, unless told not to | |
88 | 87 | * `interrupt` routines -- to indicate that "the supervisor" has stored values on the stack, so we can trash them. |
89 | 88 | * error messages that include the line number of the source code |
90 | 89 | * add absolute addressing in shl/shr, absolute-indexed for add, sub, etc. |
26 | 26 | if __name__ == '__main__': |
27 | 27 | optparser = OptionParser(__doc__.strip()) |
28 | 28 | |
29 | optparser.add_option("--analyze", | |
29 | optparser.add_option("--analyze-only", | |
30 | 30 | action="store_true", |
31 | help="") | |
31 | help="Only parse and analyze the program; do not compile it.") | |
32 | 32 | optparser.add_option("--basic-prelude", |
33 | 33 | action="store_true", |
34 | help="") | |
35 | optparser.add_option("--compile", | |
36 | action="store_true", | |
37 | help="") | |
34 | help="Insert a Commodore BASIC 2.0 snippet before the program " | |
35 | "so that it can be LOADed and RUN on Commodore platforms.") | |
38 | 36 | optparser.add_option("--debug", |
39 | 37 | action="store_true", |
40 | help="") | |
38 | help="Display debugging information when analyzing and compiling.") | |
39 | optparser.add_option("--parse-only", | |
40 | action="store_true", | |
41 | help="Only parse the program; do not analyze or compile it.") | |
41 | 42 | optparser.add_option("--traceback", |
42 | 43 | action="store_true", |
43 | help="") | |
44 | help="When an error occurs, display a full Python traceback.") | |
44 | 45 | |
45 | 46 | (options, args) = optparser.parse_args(sys.argv[1:]) |
46 | 47 | |
47 | 48 | for filename in args: |
48 | 49 | text = open(filename).read() |
49 | parser = Parser(text) | |
50 | program = parser.program() | |
51 | 50 | |
52 | if options.analyze: | |
53 | try: | |
54 | analyzer = Analyzer(debug=options.debug) | |
55 | analyzer.analyze_program(program) | |
56 | except Exception as e: | |
57 | if options.traceback: | |
58 | raise | |
59 | else: | |
60 | traceback.print_exception(e.__class__, e, None) | |
61 | sys.exit(1) | |
51 | try: | |
52 | parser = Parser(text) | |
53 | program = parser.program() | |
54 | except Exception as e: | |
55 | if options.traceback: | |
56 | raise | |
57 | else: | |
58 | traceback.print_exception(e.__class__, e, None) | |
59 | sys.exit(1) | |
62 | 60 | |
63 | if options.compile: | |
64 | fh = sys.stdout | |
65 | start_addr = 0xc000 | |
66 | prelude = [] | |
67 | if options.basic_prelude: | |
68 | start_addr = 0x0801 | |
69 | prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32, | |
70 | 0x30, 0x36, 0x31, 0x00, 0x00, 0x00] | |
61 | if options.parse_only: | |
62 | sys.exit(0) | |
71 | 63 | |
72 | # we are outputting a .PRG, so we output the load address first | |
73 | # we don't use the Emitter for this b/c not part of addr space | |
74 | if not options.debug: | |
75 | fh.write(Word(start_addr).serialize(0)) | |
64 | try: | |
65 | analyzer = Analyzer(debug=options.debug) | |
66 | analyzer.analyze_program(program) | |
67 | except Exception as e: | |
68 | if options.traceback: | |
69 | raise | |
70 | else: | |
71 | traceback.print_exception(e.__class__, e, None) | |
72 | sys.exit(1) | |
76 | 73 | |
77 | emitter = Emitter(start_addr) | |
78 | for byte in prelude: | |
79 | emitter.emit(Byte(byte)) | |
80 | compiler = Compiler(emitter) | |
81 | compiler.compile_program(program) | |
82 | if options.debug: | |
83 | pprint(emitter.accum) | |
84 | else: | |
85 | emitter.serialize(fh) | |
74 | if options.analyze_only: | |
75 | sys.exit(0) | |
76 | ||
77 | fh = sys.stdout | |
78 | start_addr = 0xc000 | |
79 | prelude = [] | |
80 | if options.basic_prelude: | |
81 | start_addr = 0x0801 | |
82 | prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32, | |
83 | 0x30, 0x36, 0x31, 0x00, 0x00, 0x00] | |
84 | ||
85 | # we are outputting a .PRG, so we output the load address first | |
86 | # we don't use the Emitter for this b/c not part of addr space | |
87 | if not options.debug: | |
88 | fh.write(Word(start_addr).serialize(0)) | |
89 | ||
90 | emitter = Emitter(start_addr) | |
91 | for byte in prelude: | |
92 | emitter.emit(Byte(byte)) | |
93 | compiler = Compiler(emitter) | |
94 | compiler.compile_program(program) | |
95 | if options.debug: | |
96 | pprint(emitter.accum) | |
97 | else: | |
98 | emitter.serialize(fh) |
257 | 257 | raise TypeMismatchError((src, dest)) |
258 | 258 | context.assert_meaningful(instr.index) |
259 | 259 | elif src.type != dest.type: |
260 | raise TypeMismatchError('%s and %s in %s' % | |
261 | (src.name, dest.name, self.current_routine.name) | |
260 | raise TypeMismatchError('%r and %r in %s' % | |
261 | (src, dest, self.current_routine.name) | |
262 | 262 | ) |
263 | 263 | context.assert_meaningful(src) |
264 | 264 | context.set_written(dest) |
6 | 6 | [Falderal]: http://catseye.tc/node/Falderal |
7 | 7 | |
8 | 8 | -> Functionality "Analyze SixtyPical program" is implemented by |
9 | -> shell command "bin/sixtypical --analyze --traceback %(test-body-file) && echo ok" | |
9 | -> shell command "bin/sixtypical --analyze-only --traceback %(test-body-file) && echo ok" | |
10 | 10 | |
11 | 11 | -> Tests for functionality "Analyze SixtyPical program" |
12 | 12 | |
235 | 235 | | ld a, 0 |
236 | 236 | | st a, foo |
237 | 237 | | } |
238 | ? TypeMismatchError: a and foo in main | |
238 | ? TypeMismatchError | |
239 | 239 | |
240 | 240 | ### tables ### |
241 | 241 |
6 | 6 | [Falderal]: http://catseye.tc/node/Falderal |
7 | 7 | |
8 | 8 | -> Functionality "Compile SixtyPical program" is implemented by |
9 | -> shell command "bin/sixtypical --basic-prelude --compile %(test-body-file) | tests/appliances/bin/dcc6502-adapter" | |
9 | -> shell command "bin/sixtypical --basic-prelude --traceback %(test-body-file) >/tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo" | |
10 | 10 | |
11 | 11 | -> Tests for functionality "Compile SixtyPical program" |
12 | 12 | |
276 | 276 | | trashes a, x, y, z, n, c, v |
277 | 277 | | { |
278 | 278 | | ld a, 0 |
279 | | ld y, 0 | |
279 | 280 | | if z { |
280 | 281 | | ld y, 1 |
281 | 282 | | } |
282 | 283 | | } |
283 | 284 | = $080D LDA #$00 |
284 | = $080F BNE $0813 | |
285 | = $0811 LDY #$01 | |
286 | = $0813 RTS | |
285 | = $080F LDY #$00 | |
286 | = $0811 BNE $0815 | |
287 | = $0813 LDY #$01 | |
288 | = $0815 RTS | |
287 | 289 | |
288 | 290 | Compiling `repeat`. |
289 | 291 | |
494 | 496 | |
495 | 497 | Copy routine to vector, inside an `interrupts off` block. |
496 | 498 | |
497 | | vector routine bar | |
499 | | vector routine | |
500 | | inputs x | |
501 | | outputs x | |
502 | | trashes z, n | |
503 | | bar | |
498 | 504 | | |
499 | 505 | | routine foo |
500 | 506 | | inputs x |
505 | 511 | | } |
506 | 512 | | |
507 | 513 | | routine main |
508 | | inputs foo | |
509 | 514 | | outputs bar |
510 | 515 | | trashes a, n, z |
511 | 516 | | { |
567 | 572 | |
568 | 573 | Indirect call. |
569 | 574 | |
570 | | vector routine outputs x trashes z, n foo | |
571 | | | |
572 | | routine bar outputs x trashes z, n { | |
575 | | vector routine | |
576 | | outputs x | |
577 | | trashes z, n | |
578 | | foo | |
579 | | | |
580 | | routine bar | |
581 | | outputs x | |
582 | | trashes z, n | |
583 | | { | |
573 | 584 | | ld x, 200 |
574 | 585 | | } |
575 | 586 | | |
576 | | routine main inputs bar outputs x, foo trashes a, z, n { | |
587 | | routine main | |
588 | | outputs x, foo | |
589 | | trashes a, z, n | |
590 | | { | |
577 | 591 | | copy bar, foo |
578 | 592 | | call foo |
579 | 593 | | } |
589 | 603 | |
590 | 604 | goto. |
591 | 605 | |
592 | | routine bar outputs x trashes z, n { | |
606 | | routine bar | |
607 | | inputs y | |
608 | | outputs x, y | |
609 | | trashes z, n | |
610 | | { | |
593 | 611 | | ld x, 200 |
594 | 612 | | } |
595 | 613 | | |
596 | | routine main outputs x trashes a, z, n { | |
614 | | routine main | |
615 | | outputs x, y | |
616 | | trashes a, z, n | |
617 | | { | |
597 | 618 | | ld y, 200 |
598 | 619 | | goto bar |
599 | 620 | | } |
840 | 861 | | routine main |
841 | 862 | | inputs buf |
842 | 863 | | outputs y, foo, delta |
843 | | trashes a, z, n, ptr | |
864 | | trashes a, c, v, z, n, ptr | |
844 | 865 | | { |
845 | 866 | | copy 619, delta |
846 | 867 | | ld y, 0 |
868 | | st off, c | |
847 | 869 | | copy ^buf, ptr |
848 | 870 | | add ptr, delta |
849 | 871 | | add ptr, word 1 |
850 | 872 | | copy [ptr] + y, foo |
851 | 873 | | } |
852 | 874 | = $080D LDA #$6B |
853 | = $080F STA $1042 | |
875 | = $080F STA $1043 | |
854 | 876 | = $0812 LDA #$02 |
855 | = $0814 STA $1043 | |
877 | = $0814 STA $1044 | |
856 | 878 | = $0817 LDY #$00 |
857 | = $0819 LDA #$41 | |
858 | = $081B STA $FE | |
859 | = $081D LDA #$08 | |
860 | = $081F STA $FF | |
861 | = $0821 LDA $FE | |
862 | = $0823 ADC $1042 | |
863 | = $0826 STA $FE | |
864 | = $0828 LDA $FF | |
865 | = $082A ADC $1043 | |
866 | = $082D STA $FF | |
867 | = $082F LDA $FE | |
868 | = $0831 ADC #$01 | |
869 | = $0833 STA $FE | |
870 | = $0835 LDA $FF | |
871 | = $0837 ADC #$00 | |
872 | = $0839 STA $FF | |
873 | = $083B LDA ($FE),Y | |
874 | = $083D STA $1041 | |
875 | = $0840 RTS | |
879 | = $0819 CLC | |
880 | = $081A LDA #$42 | |
881 | = $081C STA $FE | |
882 | = $081E LDA #$08 | |
883 | = $0820 STA $FF | |
884 | = $0822 LDA $FE | |
885 | = $0824 ADC $1043 | |
886 | = $0827 STA $FE | |
887 | = $0829 LDA $FF | |
888 | = $082B ADC $1044 | |
889 | = $082E STA $FF | |
890 | = $0830 LDA $FE | |
891 | = $0832 ADC #$01 | |
892 | = $0834 STA $FE | |
893 | = $0836 LDA $FF | |
894 | = $0838 ADC #$00 | |
895 | = $083A STA $FF | |
896 | = $083C LDA ($FE),Y | |
897 | = $083E STA $1042 | |
898 | = $0841 RTS | |
876 | 899 | |
877 | 900 | ### Trash |
878 | 901 |
9 | 9 | [Falderal]: http://catseye.tc/node/Falderal |
10 | 10 | |
11 | 11 | -> Functionality "Check syntax of SixtyPical program" is implemented by |
12 | -> shell command "bin/sixtypical %(test-body-file) && echo ok" | |
12 | -> shell command "bin/sixtypical --parse-only --traceback %(test-body-file) && echo ok" | |
13 | 13 | |
14 | 14 | -> Tests for functionality "Check syntax of SixtyPical program" |
15 | 15 |