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
|