diff options
Diffstat (limited to 'projects/hack-vm/__main__.py')
-rw-r--r-- | projects/hack-vm/__main__.py | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/projects/hack-vm/__main__.py b/projects/hack-vm/__main__.py new file mode 100644 index 0000000..a1dce1f --- /dev/null +++ b/projects/hack-vm/__main__.py @@ -0,0 +1,63 @@ +from argparse import ArgumentParser +from .memory import translate_memory +from .arith_logic import translate_arith_logic +from .compare import translate_compare +from .utils import * + + +def vm_translate(input_path): + # program name, for static variable labels + input_fn = input_path.split("/")[-1] + prog = input_fn[:-3] if input_fn.endswith(".vm") else input_fn + + try: + input_file = open(input_path) + except: + exit_on_error(f"Cannot open input file: {input_fn}", EXIT_CODE_FILE_ERROR) + + # load all vm commands from file + vm_cmds = [] + line = input_file.readline() + while line: + cmd = line.rstrip("\n").split("//", maxsplit=1)[0].strip() + if cmd: + vm_cmds.append(cmd) + line = input_file.readline() + + input_file.close() + + asm = "" + for cmd in vm_cmds: + # tokenize vm_line, hand to sub-translators based on first token + match cmd.split(): + case []: + continue + case [("push" | "pop") as action, segment, index]: + asm += translate_memory(action, segment, index, prog) + case [("add" | "sub" | "neg" | "and" | "or" | "not") as command]: + asm += translate_arith_logic(command) + case [("lt" | "eq" | "gt") as command]: + asm += translate_compare(command) + case _: + exit_on_error( + f"Syntax error: invalid command: {cmd}", EXIT_CODE_SYNTAX_ERROR + ) + + output_path = ( + input_path[:-3] + ".asm" if input_path.endswith(".vm") else input_path + ".asm" + ) + try: + output_file = open(output_path, "w") + except: + exit_on_error(f"Cannot open output file: {output_fn}", EXIT_CODE_FILE_ERROR) + + output_file.write(asm) + output_file.close() + print(f"Assembly written to {output_path}") + + +if __name__ == "__main__": + parser = ArgumentParser("hack-vm") + parser.add_argument("input_path", help="input file in HACK VM") + args = parser.parse_args() + vm_translate(args.input_path) |