nand2tetris/compiler/backend/bin/compiler.ml

62 lines
1.7 KiB
OCaml
Raw Normal View History

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