-
Notifications
You must be signed in to change notification settings - Fork 9
/
main.ml
64 lines (59 loc) · 1.73 KB
/
main.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
60
61
62
63
(* Compiler Construction - Minimal Lambda Language
*
* Entry point to the compiler: parses arguments and runs the
* code generation pipeline. In case of an error, a diagnostic
* is emitted pointing to a location in the source code.
*)
let in_chan = ref stdin
let out_chan = ref stdout
let backend = ref Backend_x86_64.compile
let dump_ir = ref false
let usage = "usage: " ^ Sys.argv.(0) ^ "[-o out] [-x86_64] input"
let speclist =
[ ( "-x86_64"
, Arg.Unit (fun () -> backend := Backend_x86_64.compile)
, ": x86_64 target"
)
; ( "-armv7"
, Arg.Unit (fun () -> backend := Backend_armv7.compile)
, ": armv7 target"
)
; ( "-o"
, Arg.String (fun s -> out_chan := open_out s)
, ": output stream"
)
; ( "-dump-ir"
, Arg.Unit (fun () -> dump_ir := true)
, ": dump the IR to stdout"
)
]
let () =
Arg.parse speclist (fun s -> in_chan := open_in s) usage;
let lexbuf = Lexing.from_channel !in_chan in
try
let ast = Parser.program Lexer.token lexbuf in
let typed_ast = Typing.check ast in
let ir = Ir_lowering.lower typed_ast in
if !dump_ir then
Ir.print_program stdout ir;
!backend ir !out_chan
with
| Lexer.Error(lnum, cnum, chr) ->
Printf.eprintf "(%d:%d) lexer error: invalid character '%c'\n"
lnum
cnum
chr;
exit 1
| Parser.Error ->
let pos = Lexing.lexeme_start_p lexbuf in
Printf.eprintf "(%d:%d) parser error: invalid token '%s'\n"
pos.Lexing.pos_lnum
(pos.Lexing.pos_cnum - pos.Lexing.pos_bol + 1)
(Lexing.lexeme lexbuf);
exit 1
| Typing.Error(pos, msg) ->
Printf.eprintf "(%d, %d) type error: %s\n"
pos.Lexing.pos_lnum
(pos.Lexing.pos_cnum - pos.Lexing.pos_bol + 1)
msg;
exit 1