forked from thehandsomepanther/system-f
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsyntax.ml
142 lines (130 loc) · 4.49 KB
/
syntax.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
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
open Core
(* Variables *)
type var = Var.t
(* Types *)
type typ = IntT
| ArrT of typ list * typ
| TupT of typ list
| VarT of int
| AllT of int * typ
| HoleT of typ option ref
(* Expressions *)
type exp =
| VarE of var
| LetE of (var * exp * typ) list * exp
| IntE of int
| SubE of exp * exp
| If0E of exp * exp * exp
| TupE of exp list
| PrjE of exp * int
| LamE of (var * typ) list * exp
| AppE of exp * exp list
| FixE of var * typ * exp
| LAME of int * exp
| APPE of exp * typ list
| HoleE of exp ref
module S = Sexp
(* Converts a type to its s-expression representation. *)
let rec sexp_of_sexp type_env = function
| IntT ->
S.Atom "int"
| ArrT(ts, tr) ->
S.List (S.Atom "->" :: List.map ~f:(sexp_of_sexp type_env) (ts @ [tr]))
| TupT ts ->
S.List (S.Atom "*" :: List.map ~f:(sexp_of_sexp type_env) ts)
| VarT n ->
(match List.nth type_env n with
| Some x -> S.Atom x
| None -> S.Atom ("?" ^ Int.to_string n))
| AllT (n, t) ->
let tvs = Var.fresh_n n (Var.Set.of_list type_env) in
S.List [S.Atom "all";
S.List (List.map ~f:(fun s -> S.Atom s) tvs);
sexp_of_sexp ((List.rev tvs) @ type_env) t]
| HoleT {contents = Some t} ->
sexp_of_sexp type_env t
| HoleT {contents = None} ->
S.Atom "_"
(* Prints a type as a string. *)
let string_of_type t = S.to_string_hum (sexp_of_sexp [] t)
(* Reveal the outtermost constructor, quotient HoleT links *)
let rec view_type = function
| HoleT {contents = Some t} -> view_type t
| t -> t
let rec type_has_hole = function
| IntT -> false
| ArrT (ts, tr) -> type_has_hole tr || List.exists ts ~f:type_has_hole
| TupT ts -> List.exists ts ~f:type_has_hole
| VarT _ -> false
| AllT (_, t) -> type_has_hole t
| HoleT {contents = None} -> true
| HoleT {contents = Some t} -> type_has_hole t
(* Check if r appears anywhere in t (using physical equality) *)
let ref_occurs_in r t =
let rec do_check = function
| IntT -> false
| ArrT (ts, tr) -> List.exists ~f:do_check (tr :: ts)
| TupT ts -> List.exists ~f:do_check ts
| VarT _ -> false
| AllT (_, t) -> do_check t
| HoleT r' ->
if phys_equal r r'
then true
else (match !r' with None -> false | Some t -> do_check t)
in do_check t
(* Given a type without holes, remove all HoleT {contents = Some _} indirections. *)
let rec normalize_complete_type = function
| IntT -> IntT
| ArrT (ts, tr) -> ArrT (List.map ~f:normalize_complete_type ts,
normalize_complete_type tr)
| TupT ts -> TupT (List.map ~f:normalize_complete_type ts)
| VarT n -> VarT n
| AllT (n, t) -> AllT (n, normalize_complete_type t)
| HoleT {contents = Some t} -> normalize_complete_type t
| HoleT {contents = None} ->
failwith "got type with holes in normalize_complete_type"
(* Computes the free variables of an expression. *)
let rec fv e0 =
let module Set = Var.Set in
let remove_bindings remv bindings fvset =
List.fold ~f:Set.remove ~init:fvset (List.map ~f:remv bindings) in
match e0 with
| VarE x -> Set.singleton x
| LetE(bindings, body) -> remove_bindings (fun (x,_,_) -> x) bindings (fv body)
| IntE _ -> Set.empty
| SubE(e1, e2) -> Set.union (fv e1) (fv e2)
| If0E(e1, e2, e3) -> Set.union_list [fv e1; fv e2; fv e3]
| TupE es -> Set.union_list (List.map ~f:fv es)
| PrjE(e, _) -> fv e
| LamE(bindings, body) -> remove_bindings fst bindings (fv body)
| AppE(e, es) -> Set.union_list (List.map ~f:fv (e :: es))
| FixE(x, _, e) -> Set.remove (fv e) x
| LAME (_, e) -> fv e
| APPE (e, _) -> fv e
| HoleE e -> fv (!e)
let rec normalize_expr = function
| VarE x -> VarE x
| LetE (xes, body) ->
LetE (List.map ~f:(fun (x, e, t) -> x, normalize_expr e, t) xes,
normalize_expr body)
| IntE n -> IntE n
| SubE (e1, e2) ->
SubE (normalize_expr e1, normalize_expr e2)
| If0E (e1, e2, e3) ->
If0E (normalize_expr e1, normalize_expr e2, normalize_expr e3)
| TupE es ->
TupE (List.map ~f:normalize_expr es)
| PrjE (e, ix) ->
PrjE (normalize_expr e, ix)
| LamE (xts, body) ->
LamE (xts, normalize_expr body)
| AppE (e0, es) ->
AppE (normalize_expr e0, List.map ~f:normalize_expr es)
| FixE (x, t, e) ->
FixE (x, t, normalize_expr e)
| LAME (n, e) ->
LAME (n, normalize_expr e)
| APPE (e, ts) ->
APPE (normalize_expr e, ts)
| HoleE {contents = e} ->
normalize_expr e