Skip to content

Commit edd2c91

Browse files
committed
WIP Recursive bindings
1 parent 04ed4dc commit edd2c91

5 files changed

Lines changed: 162 additions & 36 deletions

File tree

elab.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,13 @@ Trace.debug (lazy ("[RecT] t = " ^ string_of_norm_typ t));
561561
IL.LetE(e, "_", materialize_typ t)
562562
)
563563

564+
| EL.AnnotE(e, t) ->
565+
let exp =
566+
let open Syntax in
567+
let x' = var "annot" in
568+
appE(FunE(x'@@t.at, t, VarE(x'@@t.at)@@t.at, Expl@@t.at)@@span[e.at; t.at], e)@@exp.at in
569+
elab_exp env exp l
570+
564571
(*
565572
rec (X : (b : type) => {type t; type u a}) fun (b : type) => {type t = (X int.u b, X bool.t); type u a = (a, X b.t)}
566573
s1 = ?Xt:*->*, Xu:*->*->*. !b:*. [= b] -> {t : [= Xt b], u : !a:*. [= a] => [= Xu b a]}

lexer.mll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ rule token = parse
8585
| "wrap" { WRAP }
8686
| "primitive" { PRIMITIVE }
8787
| "rec" { REC }
88+
| "and" { AND }
8889
| "then" { THEN }
8990
| "type" { TYPE }
9091
| "unwrap" { UNWRAP }

parser.mly

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let parse_error s = raise (Source.Error (Source.nowhere_region, s))
2626
%}
2727

2828
%token HOLE PRIMITIVE
29-
%token FUN REC LET LOCAL IN DO WRAP UNWRAP TYPE INCLUDE END
29+
%token FUN REC AND LET LOCAL IN DO WRAP UNWRAP TYPE INCLUDE END
3030
%token IF THEN ELSE LOGICAL_OR LOGICAL_AND AS
3131
%token EQUAL COLON SEAL ARROW DARROW
3232
%token WITH
@@ -376,12 +376,24 @@ atbind :
376376
{ $2 }
377377
*/
378378
;
379+
atbinds :
380+
| atbind
381+
{ $1 }
382+
| atbind AND atbinds
383+
{ SeqB($1, $3)@@at() }
384+
;
385+
recbind :
386+
| atbind
387+
{ $1 }
388+
| REC atbinds
389+
{ recB($2)@@at() }
390+
;
379391
bind :
380392
|
381393
{ EmptyB@@at() }
382-
| atbind
394+
| recbind
383395
{ $1 }
384-
| atbind SEMI bind
396+
| recbind SEMI bind
385397
{ SeqB($1, $3)@@at() }
386398
;
387399

regression.1ml

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -38,40 +38,33 @@ type_error {
3838

3939
;;
4040

41+
rec isEven n = n == 0 || isOdd (n-1)
42+
and isOdd n = n == 1 || (not (n == 0) && isEven (n-1));
43+
44+
;;
45+
4146
Mutually = {
42-
T = rec (R: {
43-
Even: {type t _};
44-
Odd: {type t _};
45-
}) => {
46-
Even = {
47-
type t x = {head: x; tail: R.Odd.t x};
48-
};
49-
Odd = {
50-
type t x = opt (R.Even.t x);
47+
T = {
48+
rec Even = {
49+
type t x = {head: x; tail: Odd.t x};
50+
}
51+
and Odd = {
52+
type t x = opt (Even.t x);
5153
};
5254
};
5355

54-
V = rec (R: {
55-
Even: {
56-
make 'x: x => T.Odd.t x => T.Even.t x;
57-
size 'x: T.Even.t x -> int;
58-
};
59-
Odd: {
60-
make 'x: opt (T.Even.t x) => T.Odd.t x;
61-
size 'x: T.Odd.t x -> int;
62-
};
63-
}) => {
64-
Even = {
56+
V = {
57+
rec Even = {
6558
make 'x (head: x) (tail: T.Odd.t x) : T.Even.t x =
6659
@(T.Even.t x) {head; tail};
67-
size 'x (v: T.Even.t x) = 1 + R.Odd.size v.@(T.Even.t _).tail;
68-
};
69-
Odd = {
60+
size 'x (v: T.Even.t x) : int = 1 + Odd.size v.@(T.Even.t _).tail;
61+
}
62+
and Odd = {
7063
make 'x (v: opt (T.Even.t x)) : T.Odd.t x = @(T.Odd.t x) v;
71-
size 'x (v: T.Odd.t x) =
64+
size 'x (v: T.Odd.t x) : int =
7265
caseopt v.@(T.Odd.t x)
7366
(fun () => 0)
74-
(fun e => R.Even.size e);
67+
(fun e => Even.size e);
7568
};
7669
};
7770
};
@@ -97,7 +90,7 @@ Hungry = {
9790

9891
PolyRec = {
9992
type l a = rec (type t) => alt a t;
100-
...rec {type t a} => {type t a = alt a (t (type (a, a)))};
93+
rec type t a = alt a (t (type (a, a)));
10194

10295
t_int = t int;
10396

@@ -121,7 +114,7 @@ ListN = let
121114
};
122115
type T x n (type t _ _) = (type p _) => I x p t -> p n;
123116
in {
124-
...rec {type t _ _} => {type t x n = wrap T x n t};
117+
rec type t x n = wrap T x n t;
125118

126119
case 'x 'n (type p _) (cs: I x p t) e =
127120
(unwrap e.@(t _ _): wrap T x n t) p cs;
@@ -143,9 +136,9 @@ in {
143136

144137
ListN = {
145138
...ListN;
146-
map 'x 'y 'n (xy: x -> y) = rec (map: 'n => t x n -> t y n) =>
147-
case (t y) {
139+
rec map 'x 'y 'n (xy: x -> y) : t x n -> t y n =
140+
case (t _) {
148141
nil = nil;
149-
(::) x xs = xy x :: map xs;
142+
(::) x xs = xy x :: map xy xs;
150143
};
151144
};

syntax.ml

Lines changed: 116 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ and exp' =
5151
| UnwrapE of var * typ
5252
| UnrollE of var * typ
5353
| RecE of var * typ * exp
54+
| AnnotE of exp * typ
5455

5556
and bind = (bind', unit) phrase
5657
and bind' =
@@ -195,9 +196,7 @@ let unrollE(e, t) =
195196
let x' = var "@" in
196197
letE(VarB(x'@@e.at, e)@@e.at, UnrollE(x'@@e.at, t)@@span[e.at; t.at])
197198

198-
let annotE(e, t) =
199-
let x' = var "annot" in
200-
appE(FunE(x'@@t.at, t, VarE(x'@@t.at)@@t.at, Expl@@t.at)@@span[e.at; t.at], e)
199+
let annotE(e, t) = AnnotE(e, t)
201200

202201
let sealE(e, t) =
203202
(* TODO: clone t! *)
@@ -316,6 +315,65 @@ let rollP(p, t2) =
316315
TypE(t1.it@@p.at)@@p.at)@@p.at)@@p.at)@@span[p.at; t2.at])
317316

318317

318+
(* Substitution *)
319+
320+
type 'a subst = (string * 'a) list
321+
322+
let subst_exp_var (s: 'a subst) (v: var) = try List.assoc v.it s with Not_found -> VarE(v)
323+
324+
let rec subst_exp_typ s t =
325+
(match t.it with
326+
| PathT(e) -> PathT(subst_exp_exp s e)
327+
| PrimT(s) -> PrimT(s)
328+
| TypT -> TypT
329+
| HoleT -> HoleT
330+
| StrT(d) -> StrT(subst_exp_dec s d)
331+
| FunT(v, td, tr, e, i) ->
332+
FunT(v, subst_exp_typ s td, subst_exp_typ ((v.it, VarE(v))::s) tr, e, i)
333+
| WrapT(t) -> WrapT(subst_exp_typ s t)
334+
| EqT(e) -> EqT(subst_exp_exp s e)
335+
| AsT(tl, tr) -> AsT(subst_exp_typ s tl, subst_exp_typ s tr)
336+
| WithT(t, vs, e) -> WithT(subst_exp_typ s t, vs, subst_exp_exp s e)
337+
)@@t.at
338+
339+
and subst_exp_dec s d =
340+
(match d.it with
341+
| EmptyD -> EmptyD
342+
| SeqD(dl, dr) -> SeqD(subst_exp_dec s dl, subst_exp_dec s dr)
343+
| VarD(v, t) -> VarD(v, subst_exp_typ s t)
344+
| InclD(t) -> InclD(subst_exp_typ s t)
345+
)@@d.at
346+
347+
and subst_exp_exp s e =
348+
(match e.it with
349+
| VarE(v) -> subst_exp_var s v
350+
| PrimE(s) -> PrimE(s)
351+
| TypE(t) -> TypE(subst_exp_typ s t)
352+
| StrE(b) -> StrE(subst_exp_bind s b)
353+
| FunE(v, t, e, i) ->
354+
FunE(v, subst_exp_typ s t, subst_exp_exp ((v.it, VarE(v))::s) e, i)
355+
| WrapE(v, t) -> wrapE(subst_exp_var s v@@e.at, subst_exp_typ s t)
356+
| RollE(v, t) -> rollE(subst_exp_var s v@@e.at, subst_exp_typ s t)
357+
| IfE(v, ec, ea, t) ->
358+
ifE(subst_exp_var s v@@e.at, subst_exp_exp s ec, subst_exp_exp s ea, subst_exp_typ s t)
359+
| DotE(e, v) -> DotE(subst_exp_exp s e, v)
360+
| AppE(vf, va) -> appE(subst_exp_var s vf@@e.at, subst_exp_var s va@@e.at)
361+
| UnwrapE(v, t) -> unwrapE(subst_exp_var s v@@e.at, subst_exp_typ s t)
362+
| UnrollE(v, t) -> unrollE(subst_exp_var s v@@e.at, subst_exp_typ s t)
363+
| RecE(v, t, e) -> RecE(v, subst_exp_typ s t, subst_exp_exp ((v.it, VarE(v))::s) e)
364+
| AnnotE(e, t) -> AnnotE(subst_exp_exp s e, subst_exp_typ s t)
365+
)@@e.at
366+
367+
and subst_exp_bind s b =
368+
(match b.it with
369+
| EmptyB -> EmptyB
370+
| SeqB(bl, br) -> SeqB(subst_exp_bind s bl, subst_exp_bind s br)
371+
| VarB(v, e) -> VarB(v, subst_exp_exp s e)
372+
| InclB(e) -> InclB(subst_exp_exp s e)
373+
| TypeErrorB(e) -> TypeErrorB(subst_exp_exp s e)
374+
)@@b.at
375+
376+
319377
(* String conversion *)
320378

321379
let node label = function
@@ -367,6 +425,7 @@ let label_of_exp e =
367425
| UnwrapE _ -> "UnwrapE"
368426
| UnrollE _ -> "UnrollE"
369427
| RecE _ -> "RecE"
428+
| AnnotE _ -> "AnnotE"
370429

371430
let label_of_bind b =
372431
match b.it with
@@ -425,6 +484,7 @@ and string_of_exp e =
425484
| UnwrapE(x, t) -> node' [string_of_var x; string_of_typ t]
426485
| UnrollE(x, t) -> node' [string_of_var x; string_of_typ t]
427486
| RecE(x, t, e) -> node' [string_of_var x; string_of_typ t; string_of_exp e]
487+
| AnnotE(e, t) -> node' [string_of_exp e; string_of_typ t]
428488

429489
and string_of_bind b =
430490
let node' = node (label_of_bind b) in
@@ -434,3 +494,56 @@ and string_of_bind b =
434494
| VarB(x, e) -> node' [string_of_var x; string_of_exp e]
435495
| InclB(e) -> node' [string_of_exp e]
436496
| TypeErrorB(e) -> node' [string_of_exp e]
497+
498+
499+
(* rec ... and ... *)
500+
501+
let rec extract_sig_exp p e =
502+
let s, d =
503+
match e.it with
504+
| StrE(b) ->
505+
let s, d = extract_sig_bind p b in
506+
s, StrT(d)
507+
| TypE _ ->
508+
[], TypT
509+
| FunE(v, td, e, i) ->
510+
let _, tc = extract_sig_exp p e in
511+
let p =
512+
if i.it == Impl then Pure else
513+
match e.it with
514+
| FunE _ -> Pure
515+
| TypE _ -> Pure
516+
| _ -> Impure in
517+
[], FunT(v, td, tc, p@@e.at, i)
518+
| AnnotE(e, t) ->
519+
[], t.it
520+
| _ -> [], HoleT in
521+
s, d@@e.at
522+
523+
and extract_sig_bind p b =
524+
let s, d =
525+
match b.it with
526+
| EmptyB -> [], EmptyD
527+
| SeqB(bl, br) ->
528+
let sl, dl = extract_sig_bind p bl in
529+
let sr, dr = extract_sig_bind p br in
530+
(sl @ sr), SeqD(dl, dr)
531+
| VarB(v, e) ->
532+
let s, t = extract_sig_exp (DotE(p, v)@@b.at) e in
533+
((v.it, DotE(p, v)) :: s), VarD(v, t)
534+
| InclB(e) ->
535+
let s, t = extract_sig_exp p e in
536+
s, InclD(t)
537+
| TypeErrorB(e) -> [], EmptyD in
538+
s, d@@b.at
539+
540+
let recB(b) =
541+
let r = var "R" in
542+
let s, d = extract_sig_bind (VarE(r@@b.at)@@b.at) b in
543+
let b' = subst_exp_bind s b in
544+
let b' = InclB(RecE(r@@b.at, StrT(d)@@b.at, StrE(b')@@b.at)@@b.at) in
545+
(*
546+
List.iter (fun (v, e) -> Printf.printf "%s %s\n" v (string_of_exp (e@@b.at))) s;
547+
Printf.printf "%s\n" (string_of_bind (b'@@b.at));
548+
*)
549+
b'

0 commit comments

Comments
 (0)