More Functions
These notes are very sparse right now–they will be updated soon.
Interpreter:
let rec interp_exp (defns : defn list) (env : value symtab) (exp : s_exp) : value = (* ... *) | Lst (Sym f :: args) when is_defn defns f -> let defn = get_defn defns f in if List.length args = List.length defn.args then let vals = List.map (interp_exp defns env) args in let fenv = List.combine (defn.args, vals) |> Symtab.of_list in interp_exp defns fenv defn.body else raise (BadExpression exp) let interp (program : string) : unit = let defns, body = parse_many program |> get_defns_and_body in interp_exp defns Symtab.empty body |> ignore
Compiler:
let rec compile_exp (defns : defn list) (tab : int symtab) (stack_index : int) (exp : s_exp) : directive list = (* ... *) | Lst (Sym f :: args) when is_defn defns f -> let defn = get_defn defns f in if List.length args = List.length defn.args then let stack_base = align_stack_index (stack_index + 8) in let compiled_args = args |> List.mapi (fun i arg -> compile_exp defns tab (stack_base - ((i + 2) * 8)) arg @ [Mov (stack_address (stack_base - ((i + 2) * 8)), Reg Rax)]) |> List.concat in compiled_args @ [ Add (Reg Rsp, Imm stack_base) ; Call (defn_label f) ; Sub (Reg Rsp, Imm stack_base) ] else raise (BadExpression exp) let compile_defn defns {name; args; body} = let ftab = args |> List.mapi (fun i arg -> (arg, -8 * (i + 1))) |> Symtab.of_list in [Label (defn_label name)] @ compile_exp defns ftab (-8 * (List.length args + 1)) body @ [Ret] let compile (program : s_exp list) : string = let defns, body = defns_and_body program in [ Global "entry" ; Extern "error" ; Extern "read_num" ; Extern "print_value" ; Extern "print_newline" ] @ [Label "entry"] @ compile_exp defns Symtab.empty (-8) body @ [Ret] @ List.concat_map (compile_defn defns) defns |> List.map string_of_directive |> String.concat "\n" let compile_to_file (program : string) : unit = let file = open_out "program.s" in output_string file (compile (parse_many program)) ; close_out file