Konarak
b7dee58454
- modify existing implementation to use variant types for a more accurate representation of the vm byte code - switch to fold from recursion for the main translate function - use separate modules for translating different vm commands - move static arithmetic command translations to a map
62 lines
1.7 KiB
OCaml
62 lines
1.7 KiB
OCaml
open Core
|
|
open Backend
|
|
|
|
let read_file file =
|
|
let lines = In_channel.read_lines file in
|
|
let not_empty str = not (String.is_empty str) in
|
|
List.filter lines ~f:not_empty
|
|
|
|
|
|
let is_vm_file f =
|
|
match Filename.split_extension f with
|
|
| _, Some ext -> String.equal ext "vm"
|
|
| _, None -> false
|
|
|
|
|
|
let generate_hack f =
|
|
let bytecode = read_file f in
|
|
let class_name = Filename.basename f in
|
|
Translate.translate class_name bytecode
|
|
|
|
|
|
let write_hack path hack =
|
|
let output_channel = Out_channel.create path in
|
|
Out_channel.output_lines output_channel hack;
|
|
Out_channel.close output_channel
|
|
|
|
|
|
let compile path =
|
|
let ext = ".asm" in
|
|
let absolute_path x = path ^ x in
|
|
let open Filename_base in
|
|
if Sys_unix.is_directory_exn path then
|
|
let output_file = concat path (basename path ^ ext) in
|
|
let hack =
|
|
path
|
|
|> Sys_unix.ls_dir
|
|
|> List.map ~f:absolute_path
|
|
|> List.filter ~f:is_vm_file
|
|
|> List.concat_map ~f:generate_hack
|
|
|> List.append Translate.bootstrap
|
|
in
|
|
write_hack output_file hack
|
|
else if Sys_unix.is_file_exn path && is_vm_file path then
|
|
let output_file = chop_extension path ^ ext in
|
|
let hack = generate_hack path in
|
|
write_hack output_file hack
|
|
else
|
|
failwith "Incompatible!"
|
|
|
|
|
|
let command =
|
|
let summary = "Translate Jack byte code to Hack assembly" in
|
|
let readme () = "Compiler (backend) for project 7/8 of Nand2Tetris" in
|
|
let param_spec = Command.Param.(anon ("path" %: string)) in
|
|
let param_handler path () = compile path in
|
|
Command.basic
|
|
~summary:summary ~readme:readme
|
|
(Command.Param.map param_spec ~f:param_handler)
|
|
|
|
|
|
let () = Command_unix.run command
|