open Base let _unary = [ "@SP"; "A=M-1" ] let _binary = [ "@SP"; "AM=M-1"; "D=M"; "A=A-1" ] let _add = _binary @ [ "M=M+D" ] let _sub = _binary @ [ "M=M-D" ] let _neg = _unary @ [ "M=-M" ] let _and = _binary @ [ "M=D&M" ] let _or = _binary @ [ "M=D|M" ] let _not = _unary @ [ "M=!M" ] let _eq loc = _binary @ [ "D=M-D" ; "M=-1" ; "@END_EQ_" ^ loc ; "D;JEQ" ; "@SP" ; "A=M-1" ; "M=0" ; "(END_EQ_" ^ loc ^ ")" ] ;; let _gt loc = _binary @ [ "D=M-D" ; "M=-1" ; "@END_GT_" ^ loc ; "D;JGT" ; "@SP" ; "A=M-1" ; "M=0" ; "(END_GT_" ^ loc ^ ")" ] ;; let _lt loc = _binary @ [ "D=M-D" ; "M=-1" ; "@END_LT_" ^ loc ; "D;JLT" ; "@SP" ; "A=M-1" ; "M=0" ; "(END_LT_" ^ loc ^ ")" ] ;; let a_command ?(loc = 0) a = let suffix = Int.to_string loc in match a with | "add" -> _add | "sub" -> _sub | "neg" -> _neg | "eq" -> _eq suffix | "gt" -> _gt suffix | "lt" -> _lt suffix | "and" -> _and | "or" -> _or | "not" -> _not | _ -> failwith "a_command: Invalid Command" ;; let addr a = [ String.concat [ "@"; a ] ] let push_constant = [ "D=A"; "@SP"; "A=M"; "M=D"; "@SP"; "M=M+1" ] let _end = ["(TERMINATE)"; "@TERMINATE"; "0;JMP"] let _process_push s a = match s with | "constant" -> addr a @ push_constant | _ -> failwith "Invalid Segment" ;; let m_command (c, s, a) = match c with | "push" -> _process_push s a | _ -> failwith "m_command: Invalid Command" ;;