1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-06-07 22:29:27 +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...
* 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.
* error messages that include the line number of the source code
* 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__':
optparser = OptionParser(__doc__.strip())
optparser.add_option("--analyze",
optparser.add_option("--analyze-only",
action="store_true",
help="")
help="Only parse and analyze the program; do not compile it.")
optparser.add_option("--basic-prelude",
action="store_true",
help="")
optparser.add_option("--compile",
action="store_true",
help="")
help="Insert a Commodore BASIC 2.0 snippet before the program "
"so that it can be LOADed and RUN on Commodore platforms.")
optparser.add_option("--debug",
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",
action="store_true",
help="")
help="When an error occurs, display a full Python traceback.")
(options, args) = optparser.parse_args(sys.argv[1:])
for filename in args:
text = open(filename).read()
parser = Parser(text)
program = parser.program()
if options.analyze:
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.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)
try:
parser = Parser(text)
program = parser.program()
except Exception as e:
if options.traceback:
raise
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))
context.assert_meaningful(instr.index)
elif src.type != dest.type:
raise TypeMismatchError('%s and %s in %s' %
(src.name, dest.name, self.current_routine.name)
raise TypeMismatchError('%r and %r in %s' %
(src, dest, self.current_routine.name)
)
context.assert_meaningful(src)
context.set_written(dest)

View File

@ -7,7 +7,7 @@ static analysis rules.
[Falderal]: http://catseye.tc/node/Falderal
-> 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"
@ -236,7 +236,7 @@ Can't `st` a `word` type.
| ld a, 0
| st a, foo
| }
? TypeMismatchError: a and foo in main
? TypeMismatchError
### tables ###

View File

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

View File

@ -10,7 +10,7 @@ but not necessarily sensible programs.
[Falderal]: http://catseye.tc/node/Falderal
-> 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"