1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-11-29 18:49:22 +00:00
SixtyPical/bin/sixtypical

122 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python
"""Usage: sixtypical [OPTIONS] FILES
Analyzes and compiles a Sixtypical program.
"""
from os.path import realpath, dirname, join
import sys
sys.path.insert(0, join(dirname(realpath(sys.argv[0])), '..', 'src'))
# ----------------------------------------------------------------- #
import codecs
from argparse import ArgumentParser
from pprint import pprint
import sys
import traceback
from sixtypical.parser import Parser
from sixtypical.analyzer import Analyzer
from sixtypical.emitter import Emitter, Byte, Word
from sixtypical.compiler import Compiler
if __name__ == '__main__':
argparser = ArgumentParser(__doc__.strip())
argparser.add_argument(
'filenames', metavar='FILENAME', type=str, nargs='+',
help="The SixtyPical source files to compile."
)
argparser.add_argument(
"--analyze-only",
action="store_true",
help="Only parse and analyze the program; do not compile it."
)
argparser.add_argument(
"--prelude", type=str,
help="Insert a snippet before the compiled program "
"so that it can be LOADed and RUN on a certain platforms. "
"Also sets the origin. "
"Options are: c64 or vic20."
)
argparser.add_argument(
"--debug",
action="store_true",
help="Display debugging information when analyzing and compiling."
)
argparser.add_argument(
"--parse-only",
action="store_true",
help="Only parse the program; do not analyze or compile it."
)
argparser.add_argument(
"--traceback",
action="store_true",
help="When an error occurs, display a full Python traceback."
)
options, unknown = argparser.parse_known_args(sys.argv[1:])
remainder = ' '.join(unknown)
for filename in options.filenames:
text = open(filename).read()
try:
parser = Parser(text)
program = parser.program()
except Exception as e:
if options.traceback:
raise
else:
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.prelude == 'c64':
start_addr = 0x0801
prelude = [0x10, 0x08, 0xc9, 0x07, 0x9e, 0x32,
0x30, 0x36, 0x31, 0x00, 0x00, 0x00]
elif options.prelude == 'vic20':
start_addr = 0x1001
prelude = [0x0b, 0x10, 0xc9, 0x07, 0x9e, 0x34,
0x31, 0x30, 0x39, 0x00, 0x00, 0x00]
else:
raise NotImplementedError
# 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)