1
(* $Id: typing.ml,v 1.1.1.1 2002/05/28 15:59:16 weis Exp $ *)
6
let rec nth n = function
7
| [] -> raise (Failure "nth")
8
| x :: l -> if n = 1 then x else nth (n - 1) l;;
14
| Arrow of asl_type * asl_type
18
mutable value : asl_type
20
and asl_type_scheme = Forall of int list * asl_type
23
exception TypingBug of string;;
25
let new_vartype, reset_vartypes =
26
(* Generating and resetting unknowns *)
27
let counter = ref 0 in
28
(function () -> counter := !counter+1; {index = !counter; value = Unknown}),
29
(function () -> counter := 0)
34
| TypeVar {index = _; value = Unknown} -> t
35
| TypeVar ({index = _;
36
value = TypeVar {index = _;
37
value = Unknown} as tv}) -> tv
38
| TypeVar ({index = _; value = TypeVar tv1} as tv2)
39
-> tv2.value <- tv1.value; shorten t
40
| TypeVar {index = _; value = t'} -> t'
41
| Unknown -> raise (TypingBug "shorten")
44
exception TypeClash of asl_type * asl_type;;
46
let occurs {index = n;value = _} =
47
let rec occrec = function
48
| TypeVar {index = m; value = Unknown} -> (n = m)
49
| TypeVar {index = m; value = t} -> (n = m) || (occrec t)
51
| Arrow (t1, t2) -> (occrec t1) || (occrec t2)
52
| Unknown -> raise (TypingBug "occurs") in
56
let rec unify (tau1, tau2) =
57
match (shorten tau1, shorten tau2) with
58
| (* type variable n and type variable m *)
59
(TypeVar ({index = n; value = Unknown} as tv1) as t1),
60
(TypeVar ({index = m; value = Unknown} as tv2) as t2)
61
-> if n = m then () else tv1.value <- t2
62
| (* type t1 and type variable *)
63
t1, (TypeVar ({index = _; value = Unknown} as tv) as t2)
64
-> if not(occurs tv t1) then tv.value <- t1
65
else raise (TypeClash (t1, t2))
66
| (* type variable and type t2 *)
67
(TypeVar ({index = _; value = Unknown} as tv) as t1), t2
68
-> if not(occurs tv t2) then tv.value <- t2
69
else raise (TypeClash (t1, t2))
70
| Number, Number -> ()
71
| Arrow (t1, t2), (Arrow (t'1, t'2) as t)
72
-> unify(t1, t'1); unify(t2, t'2)
73
| (t1, t2) -> raise (TypeClash (t1, t2));;
78
Forall([], Arrow(Number, Arrow(Number, Number))))
81
let global_typing_env = ref init_typing_env;;
83
let vars_of_type tau =
84
let rec vars vs = function
86
| TypeVar {index = n; value = Unknown} ->
87
if List.mem n vs then vs else n :: vs
88
| TypeVar {index = _; value = t} -> vars vs t
89
| Arrow(t1, t2) -> vars (vars vs t1) t2
90
| Unknown -> raise (TypingBug "vars_of_type") in
93
let unknowns_of_type (bv, t) = subtract (vars_of_type t) bv;;
95
let unknowns_of_type_env env =
96
flat (List.map (function Forall(gv, t) -> unknowns_of_type (gv, t)) env)
99
let generalise_type (gamma, tau) =
101
make_set (subtract (vars_of_type tau) (unknowns_of_type_env gamma))
102
in Forall(genvars, tau)
105
let gen_instance (Forall(gv, tau)) =
106
(* We associate a new unknown to each generic variable *)
108
List.map (function n -> n, TypeVar(new_vartype())) gv in
109
let rec ginstance = function
110
| (TypeVar {index = n; value = Unknown} as t) ->
111
(try List.assoc n unknowns
113
| TypeVar {index = _; value = t} -> ginstance t
115
| Arrow (t1, t2) -> Arrow(ginstance t1, ginstance t2)
116
| Unknown -> raise (TypingBug "gen_instance")
120
let rec asl_typing_expr gamma =
121
let rec type_rec = function
126
with Failure _ -> raise (TypingBug "Unbound")
127
in gen_instance sigma
128
| Cond (e1, e2, e3) ->
129
let t1 = unify(Number, type_rec e1)
130
and t2 = type_rec e2 and t3 = type_rec e3
132
| App((Abs(x, e2) as f), e1) -> (* LET case *)
133
let t1 = type_rec e1 in
134
let sigma = generalise_type (gamma, t1)
135
in asl_typing_expr (sigma :: gamma) e2
137
let u = TypeVar(new_vartype())
138
in unify(type_rec e1, Arrow(type_rec e2, u)); u
140
let u = TypeVar(new_vartype()) in
141
let s = Forall([], u)
142
in Arrow(u, asl_typing_expr (s :: gamma) e) in
147
(* Computes a name "'a", ... for type variables, *)
148
(* given an integer n representing the position *)
149
(* of the type variable in the list of generic *)
152
let q, r = (n / 26), (n mod 26) in
153
let s = String.make 1 (char_of_int (96 + r)) in
154
if q = 0 then s else name_of q ^ s
158
let print_type_scheme (Forall(gv, t)) =
159
(* Prints a type scheme. *)
160
(* Fails when it encounters an unknown *)
162
let rec names_of = function
164
| (n, (v1 :: lv)) -> tvar_name n :: names_of (n + 1, lv) in
166
let tvar_names = List.combine (List.rev gv) names in
167
let rec print_rec = function
168
| TypeVar{index = n; value = Unknown} ->
170
try List.assoc n tvar_names
172
raise (TypingBug "Non generic variable")
174
| TypeVar{index = _;value = t} -> print_rec t
175
| Number -> print_string "Number"
177
print_string "("; print_rec t1;
178
print_string " -> "; print_rec t2;
180
| Unknown -> raise (TypingBug "print_type_scheme") in
184
let typing (Decl(s, e)) =
187
try asl_typing_expr !global_typing_env e
188
with TypeClash(t1, t2) ->
189
let vars = vars_of_type(t1) @ vars_of_type(t2) in
190
print_string "*** ASL Type clash between ";
191
print_type_scheme (Forall(vars, t1));
192
print_string " and ";
193
print_type_scheme (Forall(vars, t2));
195
raise (Failure "ASL typing")
197
generalise_type([], tau)
201
global_env:=init_env;;
202
typing (parse_top "x=1;");;
203
typing (parse_top "y = + 2 ((\\x.x) 3);");;
204
typing (parse_top "z = C (+ 0 1) 1 0;");;
205
typing (parse_top "i = \\x.x;");;
206
typing (parse_top "t = + (i 1) (i i 2);");;
207
typing (parse_top "f = (\\x.x x) (\\x.x);");;
208
typing (parse_top "a = + (\\x.x) 1;");;
209
typing (parse_top "z = \\f.((\\x.f(\\z.(x x)z)) (\\x.f(\\z.(x x)z)));");;
210
global_env := `z`::init_env;
213
Arrow(Arrow(TypeVar{index=1;value=Unknown},
214
TypeVar{index=1;value=Unknown}),
215
TypeVar{index=1;value=Unknown})))
218
typing (parse_top "f = z(\\f.(\\n. C (= n 0) 1 ( * n (f (- n 1)))));");;
219
typing (parse_top "x = f 8;");;
221
"b = z(\\b.(\\n. C (= n 1) 1 (C (= n 2) 1 (+ (b(- n 1)) (b(- n 2))))));");;
222
typing (parse_top "x = b 9;");;