1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-01-23 10:30:16 +00:00

Always analyze before compiling.

This commit is contained in:
Chris Pressey 2018-02-06 16:14:44 +00:00
parent 43b3a088b0
commit ed1ed3eb5d
6 changed files with 117 additions and 82 deletions

View File

@ -85,7 +85,6 @@ If one branch trashes {`a`} and the other branch trashes {`b`} then the whole
### And at some point... ### And at some point...
* Check that the buffer being read or written to through pointer, appears in approporiate inputs or outputs set. * Check that the buffer being read or written to through pointer, appears in approporiate inputs or outputs set.
* always analyze before executing or compiling, unless told not to
* `interrupt` routines -- to indicate that "the supervisor" has stored values on the stack, so we can trash them. * `interrupt` routines -- to indicate that "the supervisor" has stored values on the stack, so we can trash them.
* error messages that include the line number of the source code * error messages that include the line number of the source code
* add absolute addressing in shl/shr, absolute-indexed for add, sub, etc. * add absolute addressing in shl/shr, absolute-indexed for add, sub, etc.

View File

@ -27,60 +27,73 @@ from sixtypical.compiler import Compiler
if __name__ == '__main__': if __name__ == '__main__':
optparser = OptionParser(__doc__.strip()) optparser = OptionParser(__doc__.strip())
optparser.add_option("--analyze", optparser.add_option("--analyze-only",
action="store_true", action="store_true",
help="") help="Only parse and analyze the program; do not compile it.")
optparser.add_option("--basic-prelude", optparser.add_option("--basic-prelude",
action="store_true", action="store_true",
help="") help="Insert a Commodore BASIC 2.0 snippet before the program "
optparser.add_option("--compile", "so that it can be LOADed and RUN on Commodore platforms.")
action="store_true",
help="")
optparser.add_option("--debug", optparser.add_option("--debug",
action="store_true", action="store_true",
help="") help="Display debugging information when analyzing and compiling.")
optparser.add_option("--parse-only",
action="store_true",
help="Only parse the program; do not analyze or compile it.")
optparser.add_option("--traceback", optparser.add_option("--traceback",
action="store_true", action="store_true",
help="") help="When an error occurs, display a full Python traceback.")
(options, args) = optparser.parse_args(sys.argv[1:]) (options, args) = optparser.parse_args(sys.argv[1:])
for filename in args: for filename in args:
text = open(filename).read() text = open(filename).read()
parser = Parser(text)
program = parser.program()
if options.analyze: try:
try: parser = Parser(text)
analyzer = Analyzer(debug=options.debug) program = parser.program()
analyzer.analyze_program(program) except Exception as e:
except Exception as e: if options.traceback:
if options.traceback: raise
raise
else:
traceback.print_exception(e.__class__, e, None)
sys.exit(1)
if options.compile:
fh = sys.stdout
start_addr = 0xc000
prelude = []
if options.basic_prelude:
start_addr = 0x0801
prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
# we are outputting a .PRG, so we output the load address first
# we don't use the Emitter for this b/c not part of addr space
if not options.debug:
fh.write(Word(start_addr).serialize(0))
emitter = Emitter(start_addr)
for byte in prelude:
emitter.emit(Byte(byte))
compiler = Compiler(emitter)
compiler.compile_program(program)
if options.debug:
pprint(emitter.accum)
else: else:
emitter.serialize(fh) traceback.print_exception(e.__class__, e, None)
sys.exit(1)
if options.parse_only:
sys.exit(0)
try:
analyzer = Analyzer(debug=options.debug)
analyzer.analyze_program(program)
except Exception as e:
if options.traceback:
raise
else:
traceback.print_exception(e.__class__, e, None)
sys.exit(1)
if options.analyze_only:
sys.exit(0)
fh = sys.stdout
start_addr = 0xc000
prelude = []
if options.basic_prelude:
start_addr = 0x0801
prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
# we are outputting a .PRG, so we output the load address first
# we don't use the Emitter for this b/c not part of addr space
if not options.debug:
fh.write(Word(start_addr).serialize(0))
emitter = Emitter(start_addr)
for byte in prelude:
emitter.emit(Byte(byte))
compiler = Compiler(emitter)
compiler.compile_program(program)
if options.debug:
pprint(emitter.accum)
else:
emitter.serialize(fh)

View File

@ -258,8 +258,8 @@ class Analyzer(object):
raise TypeMismatchError((src, dest)) raise TypeMismatchError((src, dest))
context.assert_meaningful(instr.index) context.assert_meaningful(instr.index)
elif src.type != dest.type: elif src.type != dest.type:
raise TypeMismatchError('%s and %s in %s' % raise TypeMismatchError('%r and %r in %s' %
(src.name, dest.name, self.current_routine.name) (src, dest, self.current_routine.name)
) )
context.assert_meaningful(src) context.assert_meaningful(src)
context.set_written(dest) context.set_written(dest)

View File

@ -7,7 +7,7 @@ static analysis rules.
[Falderal]: http://catseye.tc/node/Falderal [Falderal]: http://catseye.tc/node/Falderal
-> Functionality "Analyze SixtyPical program" is implemented by -> Functionality "Analyze SixtyPical program" is implemented by
-> shell command "bin/sixtypical --analyze --traceback %(test-body-file) && echo ok" -> shell command "bin/sixtypical --analyze-only --traceback %(test-body-file) && echo ok"
-> Tests for functionality "Analyze SixtyPical program" -> Tests for functionality "Analyze SixtyPical program"
@ -236,7 +236,7 @@ Can't `st` a `word` type.
| ld a, 0 | ld a, 0
| st a, foo | st a, foo
| } | }
? TypeMismatchError: a and foo in main ? TypeMismatchError
### tables ### ### tables ###

View File

@ -7,7 +7,7 @@ SixtyPical to 6502 machine code.
[Falderal]: http://catseye.tc/node/Falderal [Falderal]: http://catseye.tc/node/Falderal
-> Functionality "Compile SixtyPical program" is implemented by -> Functionality "Compile SixtyPical program" is implemented by
-> shell command "bin/sixtypical --basic-prelude --compile %(test-body-file) | tests/appliances/bin/dcc6502-adapter" -> shell command "bin/sixtypical --basic-prelude --traceback %(test-body-file) >/tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo"
-> Tests for functionality "Compile SixtyPical program" -> Tests for functionality "Compile SixtyPical program"
@ -277,14 +277,16 @@ Compiling `if` without `else`.
| trashes a, x, y, z, n, c, v | trashes a, x, y, z, n, c, v
| { | {
| ld a, 0 | ld a, 0
| ld y, 0
| if z { | if z {
| ld y, 1 | ld y, 1
| } | }
| } | }
= $080D LDA #$00 = $080D LDA #$00
= $080F BNE $0813 = $080F LDY #$00
= $0811 LDY #$01 = $0811 BNE $0815
= $0813 RTS = $0813 LDY #$01
= $0815 RTS
Compiling `repeat`. Compiling `repeat`.
@ -495,7 +497,11 @@ Copy vector to vector.
Copy routine to vector, inside an `interrupts off` block. Copy routine to vector, inside an `interrupts off` block.
| vector routine bar | vector routine
| inputs x
| outputs x
| trashes z, n
| bar
| |
| routine foo | routine foo
| inputs x | inputs x
@ -506,7 +512,6 @@ Copy routine to vector, inside an `interrupts off` block.
| } | }
| |
| routine main | routine main
| inputs foo
| outputs bar | outputs bar
| trashes a, n, z | trashes a, n, z
| { | {
@ -568,13 +573,22 @@ Copy word to word table and back, with both `x` and `y` as indexes.
Indirect call. Indirect call.
| vector routine outputs x trashes z, n foo | vector routine
| outputs x
| trashes z, n
| foo
| |
| routine bar outputs x trashes z, n { | routine bar
| outputs x
| trashes z, n
| {
| ld x, 200 | ld x, 200
| } | }
| |
| routine main inputs bar outputs x, foo trashes a, z, n { | routine main
| outputs x, foo
| trashes a, z, n
| {
| copy bar, foo | copy bar, foo
| call foo | call foo
| } | }
@ -590,11 +604,18 @@ Indirect call.
goto. goto.
| routine bar outputs x trashes z, n { | routine bar
| inputs y
| outputs x, y
| trashes z, n
| {
| ld x, 200 | ld x, 200
| } | }
| |
| routine main outputs x trashes a, z, n { | routine main
| outputs x, y
| trashes a, z, n
| {
| ld y, 200 | ld y, 200
| goto bar | goto bar
| } | }
@ -841,39 +862,41 @@ Note that this is *not* range-checked. (Yet.)
| routine main | routine main
| inputs buf | inputs buf
| outputs y, foo, delta | outputs y, foo, delta
| trashes a, z, n, ptr | trashes a, c, v, z, n, ptr
| { | {
| copy 619, delta | copy 619, delta
| ld y, 0 | ld y, 0
| st off, c
| copy ^buf, ptr | copy ^buf, ptr
| add ptr, delta | add ptr, delta
| add ptr, word 1 | add ptr, word 1
| copy [ptr] + y, foo | copy [ptr] + y, foo
| } | }
= $080D LDA #$6B = $080D LDA #$6B
= $080F STA $1042 = $080F STA $1043
= $0812 LDA #$02 = $0812 LDA #$02
= $0814 STA $1043 = $0814 STA $1044
= $0817 LDY #$00 = $0817 LDY #$00
= $0819 LDA #$41 = $0819 CLC
= $081B STA $FE = $081A LDA #$42
= $081D LDA #$08 = $081C STA $FE
= $081F STA $FF = $081E LDA #$08
= $0821 LDA $FE = $0820 STA $FF
= $0823 ADC $1042 = $0822 LDA $FE
= $0826 STA $FE = $0824 ADC $1043
= $0828 LDA $FF = $0827 STA $FE
= $082A ADC $1043 = $0829 LDA $FF
= $082D STA $FF = $082B ADC $1044
= $082F LDA $FE = $082E STA $FF
= $0831 ADC #$01 = $0830 LDA $FE
= $0833 STA $FE = $0832 ADC #$01
= $0835 LDA $FF = $0834 STA $FE
= $0837 ADC #$00 = $0836 LDA $FF
= $0839 STA $FF = $0838 ADC #$00
= $083B LDA ($FE),Y = $083A STA $FF
= $083D STA $1041 = $083C LDA ($FE),Y
= $0840 RTS = $083E STA $1042
= $0841 RTS
### Trash ### Trash

View File

@ -10,7 +10,7 @@ but not necessarily sensible programs.
[Falderal]: http://catseye.tc/node/Falderal [Falderal]: http://catseye.tc/node/Falderal
-> Functionality "Check syntax of SixtyPical program" is implemented by -> Functionality "Check syntax of SixtyPical program" is implemented by
-> shell command "bin/sixtypical %(test-body-file) && echo ok" -> shell command "bin/sixtypical --parse-only --traceback %(test-body-file) && echo ok"
-> Tests for functionality "Check syntax of SixtyPical program" -> Tests for functionality "Check syntax of SixtyPical program"