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
95 lines
1.4 KiB
OCaml
95 lines
1.4 KiB
OCaml
open! Ast
|
|
open! Base
|
|
|
|
let counter = ref 0
|
|
|
|
let count =
|
|
fun () ->
|
|
counter := (!counter) + 1;
|
|
!counter
|
|
|
|
let addr a = "@" ^ a
|
|
|
|
let label name = "(" ^ name ^ ")"
|
|
|
|
let function_definition name arg =
|
|
let push_inner n = [
|
|
addr n
|
|
; "D=A"
|
|
; "@LCL"
|
|
; "A=D+M"
|
|
; "M=0"
|
|
; "@SP"
|
|
; "M=M+1"
|
|
] in
|
|
let locals = arg
|
|
|> List.init ~f:Int.to_string
|
|
|> List.concat_map ~f:push_inner in
|
|
List.append [ label name ] locals
|
|
|
|
let function_call name arg =
|
|
let i = Int.to_string (count ()) in
|
|
let arg = Int.to_string arg in
|
|
let ret = name ^ "_RETURN_" ^ i in
|
|
[ addr ret
|
|
; "D=A"
|
|
; "@SP"
|
|
; "A=M"
|
|
; "M=D"
|
|
; "@SP"
|
|
; "M=M+1"
|
|
; "// push LCL "
|
|
; "@LCL"
|
|
; "D=M"
|
|
; "@SP"
|
|
; "A=M"
|
|
; "M=D"
|
|
; "@SP"
|
|
; "M=M+1"
|
|
; "// push ARG "
|
|
; "@ARG"
|
|
; "D=M"
|
|
; "@SP"
|
|
; "A=M"
|
|
; "M=D"
|
|
; "@SP"
|
|
; "M=M+1"
|
|
; "// push THIS "
|
|
; "@THIS"
|
|
; "D=M"
|
|
; "@SP"
|
|
; "A=M"
|
|
; "M=D"
|
|
; "@SP"
|
|
; "M=M+1"
|
|
; "// push THAT "
|
|
; "@THAT"
|
|
; "D=M"
|
|
; "@SP"
|
|
; "A=M"
|
|
; "M=D"
|
|
; "@SP"
|
|
; "M=M+1"
|
|
; "// reposition ARG"
|
|
; "D=M"
|
|
; addr arg
|
|
; "D=D-A"
|
|
; "@5"
|
|
; "D=D-A"
|
|
; "@ARG"
|
|
; "M=D"
|
|
; "// reposition LCL"
|
|
; "@SP"
|
|
; "D=M"
|
|
; "@LCL"
|
|
; "M=D"
|
|
; "// goto function"
|
|
; addr name
|
|
; "0;JMP"
|
|
; label ret ]
|
|
|
|
let translate command name arg =
|
|
match command with
|
|
| Function -> function_definition name arg
|
|
| Call -> function_call name arg
|
|
|