diff --git a/projects/06/assembler/.ocamlformat b/projects/06/assembler/.ocamlformat index 5ea2c65..8d15ff8 100644 --- a/projects/06/assembler/.ocamlformat +++ b/projects/06/assembler/.ocamlformat @@ -1,2 +1,2 @@ profile = janestreet -version = 0.23.0 +version = 0.24.1 diff --git a/projects/06/assembler/bin/assembler.ml b/projects/06/assembler/bin/assembler.ml index 549d6b1..d3e66d9 100644 --- a/projects/06/assembler/bin/assembler.ml +++ b/projects/06/assembler/bin/assembler.ml @@ -1,32 +1,31 @@ open Core open Hack -let read_file file = - let not_empty str = not (String.is_empty str) in - List.filter (In_channel.read_lines file) ~f:(not_empty) +let read_file file = + let not_empty str = not (String.is_empty str) in + List.filter (In_channel.read_lines file) ~f:not_empty ;; -let outfile file = String.concat [Filename.chop_extension file; ".hack"];; +let outfile file = String.concat [ Filename.chop_extension file; ".hack" ] let gen_hack file = let assembly = read_file file in let binary = Translate.translate assembly in let outchan = Out_channel.create (outfile file) in Out_channel.output_lines outchan binary; - Out_channel.close outchan; + Out_channel.close outchan ;; let param = let open Command.Param in - anon ("filename" %: string) + anon ("filename" %: string) ;; let command = Command.basic ~summary:"Translate .asm to .hack" - ~readme: (fun () -> "Assembler for project 6 of Nand2Tetris") - (Command.Param.map param ~f:(fun filename -> - (fun () -> gen_hack filename))) + ~readme:(fun () -> "Assembler for project 6 of Nand2Tetris") + (Command.Param.map param ~f:(fun filename () -> gen_hack filename)) ;; -let () = Command_unix.run command;; +let () = Command_unix.run command diff --git a/projects/06/assembler/lib/Predef.ml b/projects/06/assembler/lib/Predef.ml index 7ebfee5..2f953d4 100644 --- a/projects/06/assembler/lib/Predef.ml +++ b/projects/06/assembler/lib/Predef.ml @@ -1,44 +1,48 @@ open Base -let symbols = Map.of_alist_exn (module String) [ - "R0", 0; - "R1", 1; - "R2", 2; - "R3", 3; - "R4", 4; - "R5", 5; - "R6", 6; - "R7", 7; - "R8", 8; - "R9", 9; - "R10", 10; - "R11", 11; - "R12", 12; - "R13", 13; - "R14", 14; - "R15", 15; - "SP", 0; - "LCL", 1; - "ARG", 2; - "THIS", 3; - "THAT", 4; - "SCREEN", 16384; - "KBD", 24576; - ] + +let symbols = + Map.of_alist_exn + (module String) + [ "R0", 0 + ; "R1", 1 + ; "R2", 2 + ; "R3", 3 + ; "R4", 4 + ; "R5", 5 + ; "R6", 6 + ; "R7", 7 + ; "R8", 8 + ; "R9", 9 + ; "R10", 10 + ; "R11", 11 + ; "R12", 12 + ; "R13", 13 + ; "R14", 14 + ; "R15", 15 + ; "SP", 0 + ; "LCL", 1 + ; "ARG", 2 + ; "THIS", 3 + ; "THAT", 4 + ; "SCREEN", 16384 + ; "KBD", 24576 + ] +;; let comp c = match c with - | "0" -> "0101010" - | "1" -> "0111111" - | "-1" -> "0111010" - | "D" -> "0001100" - | "A" -> "0110000" - | "M" -> "1110000" - | "!D" -> "0001101" - | "!A" -> "0110001" - | "!M" -> "1110001" - | "-D" -> "0001111" - | "-A" -> "0110011" - | "-M" -> "1110011" + | "0" -> "0101010" + | "1" -> "0111111" + | "-1" -> "0111010" + | "D" -> "0001100" + | "A" -> "0110000" + | "M" -> "1110000" + | "!D" -> "0001101" + | "!A" -> "0110001" + | "!M" -> "1110001" + | "-D" -> "0001111" + | "-A" -> "0110011" + | "-M" -> "1110011" | "D+1" -> "0011111" | "A+1" -> "0110111" | "M+1" -> "1110111" @@ -60,20 +64,20 @@ let comp c = let dest d = match d with - | "" -> "000" - | "M" -> "001" - | "D" -> "010" - | "MD" -> "011" - | "A" -> "100" - | "AM" -> "101" - | "AD" -> "110" + | "" -> "000" + | "M" -> "001" + | "D" -> "010" + | "MD" -> "011" + | "A" -> "100" + | "AM" -> "101" + | "AD" -> "110" | "ADM" -> "111" | _ -> failwith "Unknown DEST Instruction" ;; let jump j = match j with - | "" -> "000" + | "" -> "000" | "JGT" -> "001" | "JEQ" -> "010" | "JGE" -> "011" diff --git a/projects/06/assembler/lib/Translate.ml b/projects/06/assembler/lib/Translate.ml index 80aff9b..ce81106 100644 --- a/projects/06/assembler/lib/Translate.ml +++ b/projects/06/assembler/lib/Translate.ml @@ -2,80 +2,76 @@ open Base open Ast open Predef -(* Check if symbol(k) exists in map(map), add it if it does not. *) -let add_symbol map k d = - if Map.mem map k then map - else Map.add_exn map ~key:k ~data:d -;; +let add_symbol map k d = if Map.mem map k then map else Map.add_exn map ~key:k ~data:d -(* First Pass. FIXME *) let rec first_pass exprs st loc = match exprs with | [] -> st - | (Ginstr s)::t -> first_pass t (add_symbol st s loc) loc - | (Ainstr _ | Cinstr _ )::t -> first_pass t st (loc + 1) - | _::t -> first_pass t st loc + | Ginstr s :: t -> first_pass t (add_symbol st s loc) loc + | (Ainstr _ | Cinstr _) :: t -> first_pass t st (loc + 1) + | _ :: t -> first_pass t st loc ;; -(* Second Pass. FIXME *) let rec second_pass exprs st loc = - let is_new s = - try Int.of_string s |> ignore; false - with Failure _ -> not (Map.mem st s) in + let is_new s = + try + Int.of_string s |> ignore; + false + with + | Failure _ -> not (Map.mem st s) + in match exprs with | [] -> st - | (Ainstr a)::t when (is_new a) -> second_pass t (add_symbol st a loc) (loc + 1) - | _::t -> second_pass t st loc - ;; + | Ainstr a :: t when is_new a -> second_pass t (add_symbol st a loc) (loc + 1) + | _ :: t -> second_pass t st loc +;; -(* Decimal to Binary . FIXME *) let translate_ainstr addr st = - let to_int addr = - try Map.find_exn st addr - with Not_found_s _ -> Int.of_string addr in - let pad binary = + let to_int addr = + try Map.find_exn st addr with + | Not_found_s _ -> Int.of_string addr + in + let pad binary = let length = 16 - String.length binary in let prefix = String.init length ~f:(fun _ -> '0') in - String.concat [prefix; binary] in + String.concat [ prefix; binary ] + in let rec to_binary a = match a with | 0 -> "" | _ -> let rem = a % 2 in - match rem with - | 0 -> to_binary (a / 2) ^ "0" - | _ -> to_binary (a / 2) ^ "1" in + (match rem with + | 0 -> to_binary (a / 2) ^ "0" + | _ -> to_binary (a / 2) ^ "1") + in pad (to_binary (to_int addr)) ;; -let translate_cinstr (d, c, j) = - String.concat ["111"; comp c; dest d; jump j] -;; +let translate_cinstr (d, c, j) = String.concat [ "111"; comp c; dest d; jump j ] -let rec _translate exprs st tt = +let rec _translate exprs st tt = match exprs with | [] -> tt - | (Ainstr a)::t -> translate_ainstr a st :: _translate t st tt - | (Cinstr (d, c, j))::t -> translate_cinstr (d, c, j) :: _translate t st tt - | _::t -> _translate t st tt + | Ainstr a :: t -> translate_ainstr a st :: _translate t st tt + | Cinstr (d, c, j) :: t -> translate_cinstr (d, c, j) :: _translate t st tt + | _ :: t -> _translate t st tt ;; let parse s = let lexbuf = Lexing.from_string s in - let ast = Parser.prog Lexer.read lexbuf in + let ast = Parser.prog Lexer.read lexbuf in ast ;; -let generate_exprs lines = - List.map lines ~f:parse -;; +let generate_exprs lines = List.map lines ~f:parse -let generate_st exprs = +let generate_st exprs = let _st = first_pass exprs symbols 0 in second_pass exprs _st 16 ;; -let translate lines = +let translate lines = let exprs = generate_exprs lines in let st = generate_st exprs in _translate exprs st [] diff --git a/projects/06/assembler/lib/dune b/projects/06/assembler/lib/dune index 398842a..12b926e 100644 --- a/projects/06/assembler/lib/dune +++ b/projects/06/assembler/lib/dune @@ -5,4 +5,4 @@ (library (name hack) - (libraries base core)) + (libraries base))