Skip to content

Commit 546e8ff

Browse files
committed
Recursively dependent signatures
1 parent db6923a commit 546e8ff

6 files changed

Lines changed: 152 additions & 30 deletions

File tree

elab.ml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,18 @@ Trace.debug (lazy ("[WithT] aks12 = " ^ string_of_norm_extyp (ExT(aks12, StrT []
270270
ExT(aks11, subst_typ (subst aks12 ts) t1),
271271
lift_warn typ.at t1 (add_typs aks11 env) (zs1 @ zs2 @ zs3)
272272

273+
| EL.RecT(var, typ1, typ2) ->
274+
let ExT(aks1, t1), zs1 = elab_typ env typ1 l in
275+
let env1 = add_val var.it t1 (add_typs aks1 env) in
276+
let ExT(aks2, t2), zs2 = elab_typ env1 typ2 l in
277+
let ts, zs3, e =
278+
try sub_typ env1 t2 t1 (varTs aks1) with Sub e -> error typ.at
279+
("recursive type does not match annotation: " ^ Sub.string_of_error e)
280+
in
281+
let aks' = freshen_vars env aks1 in
282+
let t3 = subst_typ (subst aks1 (varTs aks')) t2 in
283+
ExT(aks', t3), lift_warn typ.at t3 env (zs1 @ zs2 @ zs3)
284+
273285
and elab_dec env dec l =
274286
Trace.elab (lazy ("[elab_dec] " ^ EL.label_of_dec dec));
275287
(fun (s, zs) -> dec.at, env, s, zs, None, EL.label_of_dec dec) <<<

regression.1ml

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
type RDS = rec (R: let type T'1 = {type t _} in {A: T'1; B: T'1}) => let
2+
type ONE (type this _) (type that _) = {
3+
t = this;
4+
aThis 'a: this a;
5+
ofThat 'a: that a -> this a;
6+
};
7+
in {A: ONE R.A.t R.B.t; B: ONE R.B.t R.A.t};
8+
9+
Rds :> RDS = let
10+
One = {
11+
type t _ = ();
12+
aThis = ();
13+
ofThat _ = ();
14+
};
15+
in {A = One; B = One};
16+
17+
;;
18+
119
Equivalence: {
220
type t a b;
321

@@ -38,6 +56,22 @@ type_error {
3856

3957
;;
4058

59+
type MUTUALLY = rec (R: {
60+
Even: {type t _};
61+
Odd: {type t _};
62+
}) => {
63+
Even: {
64+
t = R.Even.t;
65+
make 'x: x => R.Odd.t x => R.Even.t x;
66+
size 'x: R.Even.t x -> int;
67+
};
68+
Odd: {
69+
t = R.Odd.t;
70+
make 'x: opt (R.Even.t x) => R.Odd.t x;
71+
size 'x: R.Odd.t x -> int;
72+
};
73+
};
74+
4175
Mutually = {
4276
T = rec (R: {
4377
Even: {type t _};
@@ -76,7 +110,7 @@ Mutually = {
76110
};
77111
};
78112

79-
Mutually = {
113+
Mutually :> MUTUALLY = {
80114
Even = {...Mutually.T.Even; ...Mutually.V.Even};
81115
Odd = {...Mutually.T.Odd; ...Mutually.V.Odd};
82116

@@ -86,7 +120,7 @@ Mutually = {
86120
;;
87121

88122
Hungry = {
89-
type eat a = rec eat_a => a -> eat_a;
123+
...rec {type eat a} => {type eat a = a -> eat a};
90124

91125
eater 'a: eat a = rec (eater: eat a) => @(eat a) (fun a => eater);
92126

@@ -96,7 +130,7 @@ Hungry = {
96130
};
97131

98132
PolyRec = {
99-
type l a = rec (type t) => alt a t;
133+
...rec {type l a} => {type l a = alt a (l a)};
100134
...rec {type t a} => {type t a = alt a (t (type (a, a)))};
101135

102136
t_int = t int;

sub.ml

Lines changed: 84 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,31 @@ let unify_typ t1 t2 =
101101
Trace.sub (lazy ("[unify_typ] t2 = " ^ string_of_norm_typ t2));
102102
unify_typ t1 t2
103103

104+
let rec psubst p t =
105+
match p with
106+
| VarT(a, k) -> a, t
107+
| AppT(p', ts) -> psubst p' (LamT(List.map unvarT ts, t))
108+
| _ -> assert false
109+
104110

105111
let rec sub_typ env t1 t2 ps =
106112
Trace.sub (lazy ("[sub_typ] t1 = " ^ string_of_norm_typ t1));
107113
Trace.sub (lazy ("[sub_typ] t2 = " ^ string_of_norm_typ t2));
108114
Trace.sub (lazy ("[sub_typ] ps = " ^
109115
String.concat ", " (List.map string_of_norm_typ ps)));
116+
let ts', zs', t2, ps =
117+
if ps <> [] then
118+
let su, zs' = match_typ env t1 t2 ps in
119+
Trace.sub (lazy ("[sub_typ] su = " ^
120+
String.concat ", " (List.map (fun (p, t) -> Printf.sprintf "[= %s] - [= %s]\n" (string_of_typ p) (string_of_typ t)) su)));
121+
let t2 = subst_typ (List.map (fun (p, t) -> psubst p t) su) t2 in
122+
let ps' = List.filter (fun p -> List.mem_assoc p su) ps in
123+
let ts' = List.map (fun p -> List.assoc p su) ps' in
124+
let ps = List.filter (fun p -> not (List.mem_assoc p su)) ps in
125+
ts', zs', t2, ps
126+
else
127+
[], [], t2, ps
128+
in
110129
let e1 = IL.VarE("x") in
111130
let ts, zs, e =
112131
match norm_typ t1, freshen_typ env (norm_typ t2) with
@@ -267,7 +286,7 @@ let rec sub_typ env t1 t2 ps =
267286
Trace.sub (lazy ("[sub_typ] done ts = " ^
268287
String.concat ", " (List.map string_of_norm_typ ts)));
269288
Trace.sub (lazy ("[sub_typ] done x -> " ^ IL.string_of_exp e));
270-
ts, zs, IL.LamE("x", erase_typ t1, e)
289+
ts' @ ts, zs' @ zs, IL.LamE("x", erase_typ t1, e)
271290

272291
and sub_extyp env s1 s2 ps =
273292
Trace.sub (lazy ("[sub_extyp] s1 = " ^ string_of_norm_extyp s1));
@@ -290,18 +309,11 @@ and sub_row env tr1 tr2 ps =
290309
| [] ->
291310
[], [], []
292311
| (l, t2)::tr2' ->
293-
Trace.sub (lazy ("[sub_row] l = " ^ l));
294312
let ts1, zs1, f =
295313
try sub_typ env (List.assoc l tr1) t2 ps with
296314
| Not_found -> raise (Sub (Struct(l, Missing)))
297315
| Sub e -> raise (Sub (Struct(l, e)))
298316
in
299-
let rec psubst p t =
300-
match p with
301-
| VarT(a, k) -> a, t
302-
| AppT(p', ts) -> psubst p' (LamT(List.map unvarT ts, t))
303-
| _ -> assert false
304-
in
305317
let su = List.map2 psubst (Lib.List.take (List.length ts1) ps) ts1 in
306318
let ps' = Lib.List.drop (List.length ts1) ps in
307319
let ts2, zs2, fs = sub_row env tr1 (subst_row su tr2') ps' in
@@ -331,3 +343,67 @@ and equal_row env tr1 tr2 ps =
331343
let _, zs2, _ =
332344
try sub_row env tr2 tr1 ps with Sub e -> raise (Sub (Right e)) in
333345
zs1 @ zs2
346+
347+
and match_typ env t1 t2 ps =
348+
Trace.sub (lazy ("[match_typ] t1 = " ^ string_of_norm_typ t1));
349+
Trace.sub (lazy ("[match_typ] t2 = " ^ string_of_norm_typ t2));
350+
Trace.sub (lazy ("[match_typ] ps = " ^
351+
String.concat ", " (List.map string_of_norm_typ ps)));
352+
match norm_typ t1, freshen_typ env (norm_typ t2) with
353+
| t1, FunT(aks21, t21, ExT(aks22, t22), Implicit) ->
354+
assert (aks22 = []);
355+
let su, zs = match_typ (add_typs aks21 env) t1 t22 ps in
356+
List.map (fun (p, t) -> (p, LamT(aks21, t))) su, lift env zs
357+
358+
| FunT(aks11, t11, ExT(aks12, t12), Implicit), t2 ->
359+
[], []
360+
361+
| TypT(s1), TypT(s2) ->
362+
(match s1, s2 with
363+
| ExT(aks1, t), ExT([], p) when List.mem p ps ->
364+
if aks1 <> [] || not (!undecidable_flag || is_small_typ t) then
365+
raise (Sub (Mismatch (t1, t2)));
366+
[(p, t)], []
367+
| _ ->
368+
[], [])
369+
370+
| StrT(tr1), StrT(tr2) ->
371+
match_row env tr1 tr2 ps
372+
373+
| FunT(aks1, t11, s1, Explicit p1), FunT(aks2, t21, s2, Explicit p2) ->
374+
if p1 = Impure && p2 = Pure then raise (Sub (FunEffect(p1, p2)));
375+
let env' = add_typs aks2 env in
376+
let ts1, zs1, f1 =
377+
try sub_typ env' t21 t11 (varTs aks1) with Sub e ->
378+
raise (Sub (FunParam e)) in
379+
let ps' = List.map (fun p -> AppT(p, varTs aks2)) ps in
380+
let su, zs2 =
381+
try match_extyp env' (subst_extyp (subst aks1 ts1) s1) s2 ps'
382+
with Sub e -> raise (Sub (FunResult e)) in
383+
List.map (function (AppT(p, _), t) -> (p, LamT(aks2, t))
384+
| _ -> assert false) su, lift env (zs1 @ zs2)
385+
386+
| _ ->
387+
[], []
388+
389+
and match_extyp env s1 s2 ps =
390+
let ExT(aks2, t2) = freshen_extyp env s2 in
391+
let ExT(aks1, t1) = freshen_extyp (add_typs aks2 env) s1 in
392+
match aks1, aks2 with
393+
| [], [] ->
394+
match_typ env t1 t2 ps
395+
| _ ->
396+
[], []
397+
398+
and match_row env tr1 tr2 ps =
399+
match tr2 with
400+
| [] ->
401+
[], []
402+
| (l, t2)::tr2' ->
403+
let su1, zs1 =
404+
try match_typ env (List.assoc l tr1) t2 ps with
405+
| Not_found -> raise (Sub (Struct(l, Missing)))
406+
| Sub e -> raise (Sub (Struct(l, e)))
407+
in
408+
let su2, zs2 = match_row env tr1 (subst_row (List.map (fun (p, t) -> psubst p t) su1) tr2') ps in
409+
su1 @ su2, zs1 @ zs2

syntax.ml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ and typ' =
2828
| EqT of exp
2929
| AsT of typ * typ
3030
| WithT of typ * var list * exp
31+
| RecT of var * typ * typ
3132

3233
and dec = (dec', unit) phrase
3334
and dec' =
@@ -210,13 +211,10 @@ let dotopE(x) =
210211

211212
let recT(p, t2) =
212213
let b, t1 = p.it in
213-
let e = TypE(t2)@@t2.at in
214-
let e' =
215-
match b.it with
216-
| VarB(x, _) -> RecE(x, t1, e)
217-
| EmptyB -> RecE("_"@@b.at, t1, e)
218-
| _ -> RecE("$"@@b.at, t1, letE(b, e)@@span[b.at; e.at])
219-
in PathT(e'@@span[p.at; t2.at])
214+
match b.it with
215+
| VarB(x, _) -> RecT(x, t1, t2)
216+
| EmptyB -> RecT("_"@@b.at, t1, t2)
217+
| _ -> RecT("$"@@b.at, t1, letT(b, t2)@@span[b.at; t2.at])
220218

221219
let recE(p, e) =
222220
let b, t = p.it in
@@ -344,6 +342,7 @@ let label_of_typ t =
344342
| EqT _ -> "EqT"
345343
| AsT _ -> "AsT"
346344
| WithT _ -> "WithT"
345+
| RecT _ -> "RecT"
347346

348347
let label_of_dec d =
349348
match d.it with
@@ -398,6 +397,8 @@ let rec string_of_typ t =
398397
| AsT(t1, t2) -> node' [string_of_typ t1; string_of_typ t2]
399398
| WithT(t, xs, e) ->
400399
node' ([string_of_typ t] @ List.map string_of_var xs @ [string_of_exp e])
400+
| RecT(x, b, t) ->
401+
node' [string_of_var x; string_of_typ b; string_of_typ t]
401402

402403
and string_of_dec d =
403404
let node' = node (label_of_dec d) in

talk.1ml

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,24 +107,23 @@ do map :
107107

108108
;; Objects
109109

110-
type point' self =
111-
{
112-
getX : () -> int;
113-
getY : () -> int;
114-
move : int -> int -> self;
110+
...rec {type point} => {
111+
type point = {
112+
getX : () -> int;
113+
getY : () -> int;
114+
move : int -> int -> point;
115+
}
115116
};
116-
type recpoint = rec (x : type) => point' x;
117-
type point = point' recpoint;
118117

119118
newpoint = rec (newpoint : int -> int -> point) => fun x y =>
120-
{
119+
@point {
121120
getX () = x;
122121
getY () = y;
123-
move dx dy = @recpoint (newpoint (x + dx) (y + dy));
122+
move dx dy = newpoint (x + dx) (y + dy);
124123
};
125124

126125
p = newpoint 3 4;
127-
p' = (p.move 1 2).@recpoint;
126+
p' = (p.@point.move 1 2).@point;
128127
do Int.print (p'.getX ());
129128
do print " ";
130129
do Int.print (p'.getY ());

test.1ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,11 @@ end;
295295

296296

297297
type int = primitive "int";
298-
type t = rec a => int;
298+
...rec {type t} => {type t = int};
299299
v = @t 3;
300300
n = v.@t;
301301
@t m = v;
302-
type u a = rec _ => a;
302+
u (type a) = rec (_: type) => a;
303303
w = @(u int) 4;
304304
@(u int) x = w;
305305
type p a b = (a,b);

0 commit comments

Comments
 (0)