summaryrefslogtreecommitdiff
path: root/projects/hack-vm/__main__.py
diff options
context:
space:
mode:
Diffstat (limited to 'projects/hack-vm/__main__.py')
-rw-r--r--projects/hack-vm/__main__.py63
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)