-
Notifications
You must be signed in to change notification settings - Fork 0
/
compile.ml
61 lines (48 loc) · 1.33 KB
/
compile.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
open Sexplib.Sexp
module Sexp = Sexplib.Sexp
(*
expr := <number>
| (<op> <expr>)
op := inc | dec
*)
type op =
| Inc
| Dec
type expr =
| ENum of int
| EOp of op * expr
let rec sexp_to_expr (se : Sexp.t) : expr =
match se with
| Atom(s) -> ENum(int_of_string s)
| List(sexps) ->
match sexps with
| [Atom("inc"); arg] -> EOp(Inc, sexp_to_expr arg)
| [Atom("dec"); arg] -> EOp(Dec, sexp_to_expr arg)
| _ -> failwith "Parse error"
let parse (s : string) : expr =
sexp_to_expr (Sexp.of_string s)
open Printf
let rec expr_to_instrs (e : expr) : string list =
match e with
| ENum(i) -> [sprintf "mov rax, %d" i]
| EOp(op, e) ->
let arg_exprs = expr_to_instrs e in
match op with
| Inc -> arg_exprs @ ["add rax, 1"]
| Dec -> arg_exprs @ ["sub rax, 1"]
(* Compiles a source program string to an x86 string *)
let compile (program : string) : string =
let ast = parse program in
let instrs = expr_to_instrs ast in
let instrs_str = (String.concat "\n" instrs) in
sprintf "
section .text
global our_code_starts_here
our_code_starts_here:
%s
ret\n" instrs_str;;
let () =
let input_file = (open_in (Sys.argv.(1))) in
let input_program = (input_line input_file) in
let program = (compile input_program) in
printf "%s\n" program;;