-
Notifications
You must be signed in to change notification settings - Fork 18
/
repl.ml
58 lines (48 loc) · 1.35 KB
/
repl.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
(* REPL *)
open Ast
let parse (s: string) : Ast.expr =
Parser.main Scanner.token (Lexing.from_string s)
;;
module NameMap = Map.Make(String)
let rec get_ids (e: expr): id list =
let rec dedup = function
| [] -> []
| x :: y :: xs when x = y -> y :: dedup xs
| x :: xs -> x :: dedup xs in
let ids = match e with
| NumLit(_) | BoolLit(_) -> []
| Val(x) -> [x]
| Fun(x, y) -> [x] @ (get_ids y)
| Binop(e1, _, e2) -> (get_ids e1) @ (get_ids e2)
| App(fn, arg) -> (get_ids fn) @ (get_ids arg) in
dedup ids
;;
let infer (e: Ast.expr): Ast.aexpr =
let vals = get_ids e in
let env = List.fold_left (fun m x -> NameMap.add x (Infer.gen_new_type ()) m) NameMap.empty vals in
Infer.infer env e
;;
let rec repl () =
print_string "> ";
let input = read_line () in
if input = "" then () else
try
let e = parse input in
let aexpr = infer e in
print_endline (string_of_type (Infer.type_of aexpr));
repl ();
with
| Failure(msg) ->
if msg = "lexing: empty token" then repl ()
else print_endline msg; repl ()
| _ -> print_endline "Error"; repl ()
;;
let intro () =
let template = format_of_string "
Welcome to the REPL.
Type in expressions and let Hindley-Milner Type Inference run its magic.
Out of ideas? Try out a simple lambda expression: (fun x -> x + 10)
" in
Printf.printf template
;;
intro(); repl ();