Skip to content

Commit e3296d6

Browse files
committed
WIP Recursive bindings
1 parent 93a850f commit e3296d6

9 files changed

Lines changed: 222 additions & 84 deletions

File tree

elab.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,12 @@ Trace.debug (lazy ("[VarE] s = " ^ string_of_norm_extyp (ExT([], lookup_var env
372372
let s, zs = elab_typ env typ "" in
373373
ExT([], TypT(s)), Pure, zs, IL.LamE("_", erase_extyp s, IL.TupE[])
374374

375+
| EL.PathE(exp) ->
376+
let s, p, zs, e = elab_exp env exp l in
377+
if p = Impure then
378+
error exp.at "impure type expression";
379+
s, p, zs, e
380+
375381
| EL.StrE(bind) ->
376382
elab_bind env bind l
377383

@@ -574,6 +580,13 @@ Trace.debug (lazy ("[RecT] t = " ^ string_of_norm_typ t));
574580
| Some canonic ->
575581
ExT([], lookup_var env (canonic@@path.at)), Pure, [], IL.VarE(canonic))
576582

583+
| EL.AnnotE(e, t) ->
584+
let exp =
585+
let open Syntax in
586+
let x' = var "annot" in
587+
appE(FunE(x'@@t.at, t, VarE(x'@@t.at)@@t.at, Expl@@t.at)@@span[e.at; t.at], e)@@exp.at in
588+
elab_exp env exp l
589+
577590
(*
578591
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)}
579592
s1 = ?Xt:*->*, Xu:*->*->*. !b:*. [= b] -> {t : [= Xt b], u : !a:*. [= a] => [= Xu b a]}

lexer.mll

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,14 @@ module Offside = struct
108108
if column < indent - 2 then error "offside" else
109109
emit token >>
110110
get >>= inside_braces break false indent
111+
| AND ->
112+
if column < indent then error "offside" else
113+
emit token >>
114+
get >>= inside_braces break false indent
111115
| _ ->
112116
if column < indent then error "offside" else
113117
emit_if (column = indent && insert) COMMA >>
114-
nest token >>
118+
nest false token >>
115119
get >>= inside_braces break (token <> LOCAL) indent
116120

117121
and inside_local insert indent (token, column) =
@@ -128,7 +132,7 @@ module Offside = struct
128132
emit IN
129133
else
130134
emit_if (column = indent && insert) COMMA >>
131-
nest token >>
135+
nest false token >>
132136
get >>= inside_local (token <> LOCAL) indent
133137

134138
and inside_let insert indent (token, column) =
@@ -147,12 +151,12 @@ module Offside = struct
147151
inside_in false column (token, column)
148152
else
149153
emit_if (column = indent && insert) COMMA >>
150-
nest token >>
154+
nest false token >>
151155
get >>= inside_let (token <> LOCAL) indent
152156

153157
and inside_in insert indent (token, column) =
154158
match token with
155-
| RBRACE | COMMA | IN | EOF | RPAR -> unget (token, column)
159+
| RBRACE | COMMA | IN | EOF | RPAR | EQUAL -> unget (token, column)
156160
| SEMI ->
157161
if column < indent - 2 then error "offside" else
158162
emit token >>
@@ -170,18 +174,18 @@ module Offside = struct
170174
let slack = slack_of token in
171175
if column < indent - slack then unget (token, column) else
172176
emit_if (slack = 0 && column = indent && insert) SEMI >>
173-
nest token >>
177+
nest true token >>
174178
get >>= inside_in (slack = 0 && indent < column) indent
175179

176180
and inside_parens (token, column) =
177181
match token with
178182
| RPAR -> emit token
179-
| _ -> nest token >> get >>= inside_parens
183+
| _ -> nest true token >> get >>= inside_parens
180184

181-
and nest token =
185+
and nest is_expr token =
182186
match token with
183187
| FUN | REC ->
184-
emit LPAR >> emit token
188+
if is_expr then emit LPAR >> emit token else emit token
185189
| _ ->
186190
emit token >>
187191
match token with
@@ -197,7 +201,7 @@ module Offside = struct
197201
| DARROW ->
198202
get >>= fun (token, column) ->
199203
inside_in false column (token, column) >>
200-
emit RPAR
204+
if is_expr then emit RPAR else unit
201205
| EQUAL | DO ->
202206
get >>= fun (token, column) -> inside_in false column (token, column)
203207
| _ ->
@@ -251,6 +255,7 @@ rule token = parse
251255
| "import" { IMPORT }
252256
| "primitive" { PRIMITIVE }
253257
| "rec" { REC }
258+
| "and" { AND }
254259
| "then" { THEN }
255260
| "type" { TYPE }
256261
| "with" { WITH }

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 IN DO WRAP TYPE ELLIPSIS
29+
%token FUN REC AND LET IN DO WRAP TYPE ELLIPSIS
3030
%token IF THEN ELSE LOGICAL_OR LOGICAL_AND AS
3131
%token EQUAL COLON SEAL ARROW SARROW DARROW
3232
%token WITH
@@ -456,12 +456,24 @@ atbind :
456456
{ $2 }
457457
*/
458458
;
459+
atbinds :
460+
| atbind
461+
{ $1 }
462+
| atbind AND atbinds
463+
{ seqB($1, $3)@@at() }
464+
;
465+
recbind :
466+
| atbind
467+
{ $1 }
468+
| REC atbinds
469+
{ recB($2)@@at() }
470+
;
459471
bind :
460472
|
461473
{ EmptyB@@at() }
462-
| atbind
474+
| recbind
463475
{ $1 }
464-
| atbind COMMA bind
476+
| recbind COMMA bind
465477
{ seqB($1, $3)@@at() }
466478
| LOCAL bind IN bind
467479
{ letB($2, $4)@@at() }

prelude/index.1ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Alt = {
4848
;;
4949

5050
Opt = {
51-
type t x = Alt.t {} x
51+
type t = Alt.t {}
5252
none = Alt.inl ()
5353
some = Alt.inr
5454
case {none, some} = Alt.case {inl () = none, inr = some}
@@ -68,7 +68,7 @@ Pair = {
6868

6969
List = {
7070
local ...Opt, ...Fun
71-
...rec {type t _} => {type t x = Opt.t (x, t x)}
71+
rec type t x = Opt.t (x, t x)
7272
nil :@ t _ = none
7373
hd :: tl :@ t _ = some (hd, tl)
7474
case {nil, (::)} (x :@ t _) = x |> Opt.case {

readme.1ml

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,25 @@ p = f (fun x => x)
4646

4747

4848

49-
type stream = rec t => {hd : int, tl : () ~> opt t} ;; creates rec type
50-
single x :@ stream = {hd = x, tl = fun () => none} ;; b :@ t rolls value into t
51-
({hd = n} :@ stream) = single 5 ;; p :@ t pattern matches on rec value
52-
do Int.print n ;; or:
53-
do Int.print (single 7 @: stream).hd ;; e @: t unrolls rec value directly
49+
rec type stream t = {hd : t, tl : () ~> opt (stream t)} ;; creates rec type
50+
single x :@ stream _ = {hd = x, tl () = none} ;; b :@ t rolls value into t
51+
({hd = n} :@ stream _) = single 5 ;; p :@ t pattern matches on rec value
52+
do Int.print n ;; or:
53+
do Int.print (single 7 @: stream _).hd ;; e @: t unrolls rec value directly
5454

5555

5656

5757

58-
count = rec self => fun i =>
59-
if i == 0 then () else self (i - 1)
58+
rec count i =
59+
if i == 0 then () else count (i - 1)
6060

61-
repeat = rec self => fun x =>
62-
{hd = x, tl = fun () => some (self x)} :@ stream
61+
rec repeat x :@ stream _ =
62+
{hd = x, tl () = some (repeat x)}
6363

6464

6565

66-
{even, odd} = rec (self : {even : int ~> stream, odd : int ~> stream}) => {
67-
even x :@ stream = {hd = x, tl = fun () => some (self.odd (x + 1))}
68-
odd x :@ stream = {hd = x, tl = fun () => some (self.even (x + 1))}
69-
}
66+
rec even x :@ stream _ = {hd = x, tl () = some (odd (x + 1))}
67+
and odd x :@ stream _ = {hd = x, tl () = some (even (x + 1))}
7068

7169

7270

regression.1ml

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -166,46 +166,37 @@ type_error rec (R: {}) => {
166166
kaboom () = R
167167
}
168168

169-
Kaboom = rec (R: rec R => {kaboom: () ~> R}) => {kaboom () = R} :@ (= R)
169+
rec Kaboom : rec R => {kaboom: () ~> R} = {kaboom () = Kaboom} :@ (= Kaboom)
170+
171+
rec isEven n = n == 0 || isOdd (n-1)
172+
and isOdd n = n == 1 || (not (n == 0) && isEven (n-1))
170173

171174
;;
172175

173176
Mutually = let
174-
T = rec (R: {
175-
Even: {type t _}
176-
Odd: {type t _}
177-
}) => {
178-
Even = {
179-
type t x = {head: x, tail: R.Odd.t x}
177+
T = {
178+
rec Even = {
179+
type t x = {head: x, tail: Odd.t x}
180180
}
181-
Odd = {
182-
type t x = opt (R.Even.t x)
181+
and Odd = {
182+
type t x = opt (Even.t x)
183183
}
184184
}
185185
in {
186-
...rec (R: {
187-
Even: {
188-
size 'x: T.Even.t x ~> int
189-
}
190-
Odd: {
191-
size 'x: T.Odd.t x ~> int
192-
}
193-
}) => {
194-
Even = {
195-
...T.Even
196-
make 'x (head: x) (tail: T.Odd.t x) :@ T.Even.t x =
197-
{head, tail}
198-
size 'x (v :@ T.Even.t x) = 1 + R.Odd.size v.tail
199-
}
200-
Odd = {
201-
...T.Odd
202-
make 'x (v: opt (T.Even.t x)) :@ T.Odd.t x = v
203-
size 'x (v :@ T.Odd.t x) =
204-
v |> Opt.case {
205-
none = 0
206-
some e = R.Even.size e
207-
}
208-
}
186+
rec Even = {
187+
...T.Even
188+
make 'x (head: x) (tail: T.Odd.t x) :@ T.Even.t x : T.Even.t x =
189+
{head, tail}
190+
size 'x (v :@ T.Even.t x) : int = 1 + Odd.size v.tail
191+
}
192+
and Odd = {
193+
...T.Odd
194+
make 'x (v: opt (T.Even.t x)) :@ T.Odd.t x : T.Odd.t x = v
195+
size 'x (v :@ T.Odd.t x) : int =
196+
v |> Opt.case {
197+
none = 0
198+
some = Even.size
199+
}
209200
}
210201

211202
one = Odd.size (Odd.make (some (Even.make true (Odd.make none))))
@@ -232,7 +223,7 @@ type (a `>>` b) c = c
232223
;;
233224

234225
Hungry = {
235-
type eat a = rec eat_a => a ~> eat_a
226+
rec type eat a = a ~> eat a
236227

237228
eater 'a = rec (eater: eat a) => (fun a => eater) :@ eat a
238229

@@ -242,8 +233,8 @@ Hungry = {
242233
}
243234

244235
PolyRec = {
245-
type l a = rec (type t) => a | t
246-
...rec {type t a} => {type t a = a | t (a, a)}
236+
rec type l a = a | l a
237+
rec type t a = a | t (a, a)
247238

248239
t_int = t int
249240

@@ -267,7 +258,7 @@ ListN = let
267258
}
268259
type T x n (type t _ _) = (type p _) -> I x p t ~> p n
269260
in {
270-
...rec {type t _ _} => {type t x n = wrap T x n t}
261+
rec type t x n = wrap T x n t
271262

272263
case 'x 'n (type p _) (cs: I x p t) (e :# wrap T x n t :@ t x n) =
273264
e p cs
@@ -287,9 +278,9 @@ in {
287278

288279
ListN = {
289280
...ListN
290-
map 'x 'y (xy: x ~> y) = rec (map 'n: t x n ~> t y n) =>
281+
rec map 'x 'y 'n (xy: x ~> y) : t x n ~> t y n =
291282
case (t _) {
292283
nil
293-
x :: xs = xy x :: map xs
284+
x :: xs = xy x :: map xy xs
294285
}
295286
}

russo.1ml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ ArraySucc (A : ARRAY) = {
3030
else (a.1, A.update a.2 (i / 2) x)
3131
}
3232

33-
MkArray = rec (mkArray : int ~> ARRAY) => fun n =>
34-
if n == 0 then ArrayZero else ArraySucc (mkArray (n - 1)) : ARRAY
33+
rec MkArray n : ARRAY =
34+
if n == 0 then ArrayZero else ArraySucc (MkArray (n - 1)) : ARRAY
3535

3636
printArray 't (A : ARRAY) (pr : t ~> ()) a =
37-
let loop = rec loop => fun i =>
37+
let rec loop i =
3838
if i == A.dim then print "\n"
3939
else (pr (A.sub a i) ; print " " ; loop (i + 1))
4040
loop 0
@@ -63,13 +63,13 @@ type STREAM = {
6363
}
6464

6565
divides k n =
66-
let loop = rec loop => fun i => (i * k == n) || ((i * k < n) && loop (i + 1))
66+
let rec loop i = (i * k == n) || ((i * k < n) && loop (i + 1))
6767
loop 1
6868

6969
sift (S : STREAM) :> STREAM = {
7070
type state = S.state
7171
divisor = S.value S.start
72-
filter = rec filter => fun s =>
72+
rec filter s =
7373
if divides divisor (S.value s) then filter (S.next s) else s
7474
start = filter S.start
7575
next s = filter (S.next s)
@@ -88,10 +88,10 @@ Sieve :> STREAM = {
8888
value (S :# state) = S.value S.start
8989
}
9090

91-
nthstate = rec (nthstate : int ~> Sieve.state) => fun n =>
91+
rec nthstate n =
9292
if n == 0 then Sieve.start else Sieve.next (nthstate (n -1))
9393
nthprime n = Sieve.value (nthstate n)
9494

95-
printprimes = rec loop => fun n =>
96-
if n == 0 then () else (loop (n - 1) ; Int.print (nthprime n) ; print "\n")
95+
rec printprimes n =
96+
if n == 0 then () else (printprimes (n - 1) ; Int.print (nthprime n) ; print "\n")
9797
do printprimes 20

0 commit comments

Comments
 (0)