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