finish project seven backend compiler
This commit is contained in:
parent
dae97b7a76
commit
5973c64e78
@ -6,11 +6,12 @@ let read_file file =
|
||||
List.filter (In_channel.read_lines file) ~f:not_empty
|
||||
;;
|
||||
|
||||
let classname file = Filename.chop_extension (Filename.basename file)
|
||||
let outfile file = String.concat [ Filename.chop_extension file; ".asm" ]
|
||||
|
||||
let gen_hack file =
|
||||
let ircode = read_file file in
|
||||
let assembly = Be_translate.translate ircode in
|
||||
let assembly = Be_translate.translate (classname file) ircode in
|
||||
let outchan = Out_channel.create (outfile file) in
|
||||
Out_channel.output_lines outchan assembly;
|
||||
Out_channel.close outchan
|
||||
|
@ -48,34 +48,30 @@ let _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 push = [ "@SP"; "A=M"; "M=D"; "@SP"; "M=M+1" ]
|
||||
let pop = [ "@R13"; "M=D"; "@SP"; "AM=M-1"; "D=M"; "@R13"; "A=M"; "M=D" ]
|
||||
|
||||
let s_pointer = function
|
||||
| "0" -> "@THIS"
|
||||
| "1" -> "@THAT"
|
||||
| _ -> failwith "Invalid Pointer"
|
||||
;;
|
||||
|
||||
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
|
||||
let s_common = function
|
||||
| "local" -> "@LCL"
|
||||
| "this" -> "@THIS"
|
||||
| "that" -> "@THAT"
|
||||
| "argument" -> "@ARG"
|
||||
| _ -> failwith "Invalid Segment"
|
||||
;;
|
||||
|
||||
let m_command (c, s, a) =
|
||||
match c with
|
||||
| "push" -> _process_push s a
|
||||
| _ -> failwith "m_command: Invalid Command"
|
||||
;;
|
||||
let push_constant a = [ "@" ^ a; "D=A" ] @ push
|
||||
let push_common a sp = [ "@" ^ a; "D=A"; s_common sp; "A=D+M"; "D=M" ] @ push
|
||||
let push_temp a = [ "@" ^ a; "D=A"; "@R5"; "A=D+A"; "D=M" ] @ push
|
||||
let push_pointer a = [ s_pointer a; "D=M" ] @ push
|
||||
let push_static a cn = [ "@" ^ cn ^ "." ^ a; "D=M" ] @ push
|
||||
let pop_common a sp = [ "@" ^ a; "D=A"; s_common sp; "D=D+M" ] @ pop
|
||||
let pop_temp a = [ "@" ^ a; "D=A"; "@R5"; "D=D+A" ] @ pop
|
||||
let pop_pointer a = [ "@SP"; "AM=M-1"; "D=M"; s_pointer a; "M=D" ]
|
||||
let pop_static a cn = [ "@SP"; "AM=M-1"; "D=M"; "@" ^ cn ^ "." ^ a; "M=D" ]
|
||||
let _end = [ "(TERMINATE)"; "@TERMINATE"; "0;JMP" ]
|
||||
|
@ -10,15 +10,56 @@ let parse s =
|
||||
|
||||
let generate_exprs lines = List.map lines ~f:parse
|
||||
|
||||
let rec _translate expr loc tt =
|
||||
match expr with
|
||||
| [] -> tt
|
||||
| Acommand a :: t -> a_command ?loc:(Some loc) a @ _translate t (loc+1) tt
|
||||
| Mcommand (c, s, a) :: t -> m_command (c, s, a) @ _translate t loc tt
|
||||
| _ :: t -> _translate t loc tt
|
||||
let a_command loc 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 translate lines =
|
||||
let exprs = generate_exprs lines in
|
||||
_translate exprs 0 [] @ _end
|
||||
let process_push cn sp a =
|
||||
match sp with
|
||||
| "local" | "argument" | "this" | "that" -> push_common a sp
|
||||
| "constant" -> push_constant a
|
||||
| "temp" -> push_temp a
|
||||
| "static" -> push_static a cn
|
||||
| "pointer" -> push_pointer a
|
||||
| _ -> failwith "PROCESS PUSH: Invalid Segment"
|
||||
;;
|
||||
|
||||
let process_pop cn sp a =
|
||||
match sp with
|
||||
| "local" | "argument" | "this" | "that" -> pop_common a sp
|
||||
| "temp" -> pop_temp a
|
||||
| "static" -> pop_static a cn
|
||||
| "pointer" -> pop_pointer a
|
||||
| _ -> failwith "PROCESS POP: Invalid Segment"
|
||||
;;
|
||||
|
||||
let m_command cn (c, s, a) =
|
||||
match c with
|
||||
| "pop" -> process_pop cn s a
|
||||
| "push" -> process_push cn s a
|
||||
| _ -> failwith "m_command: Invalid Command"
|
||||
;;
|
||||
|
||||
let rec _translate expr cn loc tt =
|
||||
match expr with
|
||||
| [] -> tt
|
||||
| Acommand a :: t -> a_command loc a @ _translate t cn (loc + 1) tt
|
||||
| Mcommand (c, s, a) :: t -> m_command cn (c, s, a) @ _translate t cn loc tt
|
||||
| _ :: t -> _translate t cn loc tt
|
||||
;;
|
||||
|
||||
let translate cn lines =
|
||||
let exprs = generate_exprs lines in
|
||||
_translate exprs cn 0 [] @ _end
|
||||
;;
|
||||
|
Loading…
Reference in New Issue
Block a user