forked from ymyzk/lambda-dti
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.ml
More file actions
112 lines (104 loc) · 3.49 KB
/
main.ml
File metadata and controls
112 lines (104 loc) · 3.49 KB
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
open Format
open Lambda_dti
let debug = ref false
let rec read_eval_print lexbuf env tyenv =
(* Used in all modes *)
let print f = fprintf std_formatter f in
(* Used in debug mode *)
let print_debug f = Utils.Format.make_print_debug !debug f in
flush stderr;
flush stdout;
if lexbuf.Lexing.lex_curr_p.pos_fname = "" then print "# @?";
begin try
(* Parsing *)
print_debug "***** Parser *****\n";
let e = Parser.toplevel Lexer.main lexbuf in
print_debug "e: %a\n" Pp.ITGL.pp_program e;
(* Type inference *)
print_debug "***** Typing *****\n";
let e, u = Typing.ITGL.type_of_program tyenv e in
print_debug "e: %a\n" Pp.ITGL.pp_program e;
print_debug "U: %a\n" Pp.pp_ty u;
(* NOTE: Typing.ITGL.translate and Typing.CC.type_of_program expect
* normalized input *)
let tyenv, e, u = Typing.ITGL.normalize tyenv e u in
(* Translation *)
print_debug "***** Cast-insertion *****\n";
let new_tyenv, f, u' = Typing.ITGL.translate tyenv e in
print_debug "f: %a\n" Pp.CC.pp_program f;
print_debug "U: %a\n" Pp.pp_ty u';
assert (Typing.is_equal u u');
let u'' = Typing.CC.type_of_program tyenv f in
assert (Typing.is_equal u u'');
(* Evaluation *)
print_debug "***** Eval *****\n";
let env, x, v = Eval.eval_program env f ~debug:!debug in
print "%a : %a = %a\n"
pp_print_string x
Pp.pp_ty2 u
Pp.CC.pp_value v;
read_eval_print lexbuf env new_tyenv
with
| Failure message ->
print "Failure: %s\n" message;
Utils.Lexing.flush_input lexbuf
| Parser.Error -> (* Menhir *)
let token = Lexing.lexeme lexbuf in
print "Parser.Error: unexpected token %s\n" token;
Utils.Lexing.flush_input lexbuf
| Typing.Type_error message ->
print "Type_error: %s\n" message
| Eval.Blame (r, p) -> begin
match p with
| Pos -> print "Blame on the expression side:\n%a\n" Utils.Error.pp_range r
| Neg -> print "Blame on the environment side:\n%a\n" Utils.Error.pp_range r
end
end;
read_eval_print lexbuf env tyenv
let start file =
let print_debug f = Utils.Format.make_print_debug !debug f in
print_debug "***** Lexer *****\n";
let channel, lexbuf = match file with
| None ->
print_debug "Reading from stdin\n%!";
stdin, Lexing.from_channel stdin
| Some f ->
print_debug "Reading from file \"%s\"\n%!" f;
let channel = open_in f in
let lexbuf = Lexing.from_channel channel in
lexbuf.lex_curr_p <- {lexbuf.lex_curr_p with pos_fname = f};
channel, lexbuf
in
let env, tyenv = Stdlib.pervasives in
try
read_eval_print lexbuf env tyenv
with
| Lexer.Eof ->
(* Exiting normally *)
close_in channel
| Stdlib.Stdlib_exit i ->
(* Exiting with the status code *)
close_in channel;
exit i
| e ->
(* Unexpected error occurs, close the opened channel *)
close_in_noerr channel;
raise e
let () =
let program = Sys.argv.(0) in
let usage =
"Interpreter of the ITGL with dynamic type inference\n" ^
asprintf "Usage: %s <options> [file]\n" program ^
"Options: "
in
let file = ref None in
let options = Arg.align [
("-d", Arg.Set debug, " Enable debug mode");
]
in
let parse_argv arg = match !file with
| None -> file := Some arg
| Some _ -> raise @@ Arg.Bad "error: only one file can be specified"
in
Arg.parse options parse_argv usage;
start !file