Skip to content

Commit 8414b4f

Browse files
committed
WIP Recursive bindings
1 parent 9c7b19b commit 8414b4f

9 files changed

Lines changed: 213 additions & 81 deletions

File tree

elab.ml

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

380+
| EL.PathE(exp) ->
381+
let s, p, zs, e = elab_exp env exp l in
382+
if p = Impure then
383+
error exp.at "impure type expression";
384+
s, p, zs, e
385+
380386
| EL.StrE(bind) ->
381387
elab_bind env bind l
382388

lexer.mll

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,14 @@ module Offside = struct
112112
if column < indent - 2 then error "offside" else
113113
emit token >>
114114
get >>= inside_braces break false indent
115+
| AND ->
116+
if column < indent then error "offside" else
117+
emit token >>
118+
get >>= inside_braces break false indent
115119
| _ ->
116120
if column < indent then error "offside" else
117121
emit_if (column = indent && insert) COMMA >>
118-
nest (token, column) >>
122+
nest false (token, column) >>
119123
get >>= inside_braces break (token <> LOCAL) indent
120124

121125
and inside_local insert indent (token, column) =
@@ -132,7 +136,7 @@ module Offside = struct
132136
emit IN
133137
else
134138
emit_if (column = indent && insert) COMMA >>
135-
nest (token, column) >>
139+
nest false (token, column) >>
136140
get >>= inside_local (token <> LOCAL) indent
137141

138142
and inside_let insert indent (token, column) =
@@ -151,12 +155,13 @@ module Offside = struct
151155
inside_in false column (token, column)
152156
else
153157
emit_if (column = indent && insert) COMMA >>
154-
nest (token, column) >>
158+
nest false (token, column) >>
155159
get >>= inside_let (token <> LOCAL) indent
156160

157161
and inside_in insert indent (token, column) =
158162
match token with
159-
| RBRACE | COMMA | IN | EOF | RPAR | ELSE | THEN -> unget (token, column)
163+
| RBRACE | COMMA | IN | EOF | RPAR | ELSE | THEN | EQUAL ->
164+
unget (token, column)
160165
| SEMI ->
161166
if column < indent - 2 then error "offside" else
162167
emit token >>
@@ -170,7 +175,7 @@ module Offside = struct
170175
let slack = slack_of token in
171176
if column < indent - slack then unget (token, column) else
172177
emit_if (slack = 0 && column = indent && insert) SEMI >>
173-
nest (token, column) >>
178+
nest true (token, column) >>
174179
get >>= inside_in (slack = 0 && indent <= column) indent
175180

176181
and inside_parens indent (token, column) =
@@ -180,7 +185,7 @@ module Offside = struct
180185
emit token >>
181186
get >>= inside_parens indent
182187
| _ ->
183-
nest (token, column) >>
188+
nest true (token, column) >>
184189
get >>= inside_in false indent >>
185190
get >>= inside_parens indent
186191

@@ -203,8 +208,8 @@ module Offside = struct
203208
emit ELSE >> emit LBRACE >> emit RBRACE >>
204209
unget (token, column)
205210

206-
and nest (token, column) =
207-
(match token with FUN | REC | IF -> emit LPAR | _ -> unit) >>
211+
and nest is_expr (token, column) =
212+
(match token with (FUN | REC | IF) when is_expr -> emit LPAR | _ -> unit) >>
208213
emit token >>
209214
match token with
210215
| LBRACE ->
@@ -220,9 +225,11 @@ module Offside = struct
220225
| DARROW ->
221226
get >>= fun (token, column) ->
222227
inside_in false column (token, column) >>
223-
emit RPAR
228+
if is_expr then emit RPAR else unit
224229
| EQUAL | DO ->
225230
get >>= fun (token, column) -> inside_in false column (token, column)
231+
| TYPE_ERROR ->
232+
get >>= fun (token, column) -> inside_in false column (token, column)
226233
| IF ->
227234
inside_if column >>
228235
emit RPAR
@@ -277,6 +284,7 @@ rule token = parse
277284
| "import" { IMPORT }
278285
| "primitive" { PRIMITIVE }
279286
| "rec" { REC }
287+
| "and" { AND }
280288
| "then" { THEN }
281289
| "type" { TYPE }
282290
| "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
@@ -452,12 +452,24 @@ atbind :
452452
{ $2 }
453453
*/
454454
;
455+
atbinds :
456+
| atbind
457+
{ $1 }
458+
| atbind AND atbinds
459+
{ seqB($1, $3)@@at() }
460+
;
461+
recbind :
462+
| atbind
463+
{ $1 }
464+
| REC atbinds
465+
{ recB($2)@@at() }
466+
;
455467
bind :
456468
|
457469
{ EmptyB@@at() }
458-
| atbind
470+
| recbind
459471
{ $1 }
460-
| atbind COMMA bind
472+
| recbind COMMA bind
461473
{ seqB($1, $3)@@at() }
462474
| LOCAL bind IN bind
463475
{ 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
@@ -182,46 +182,37 @@ type_error rec (R: {}) => {
182182
kaboom () = R
183183
}
184184

185-
Kaboom = rec (R: rec R => {kaboom: () ~> R}) => {kaboom () = R} :@ (= R)
185+
rec Kaboom : rec R => {kaboom: () ~> R} = {kaboom () = Kaboom} :@ (= Kaboom)
186+
187+
rec isEven n = n == 0 || isOdd (n-1)
188+
and isOdd n = n == 1 || (not (n == 0) && isEven (n-1))
186189

187190
;;
188191

189192
Mutually = let
190-
T = rec (R: {
191-
Even: {type t _}
192-
Odd: {type t _}
193-
}) => {
194-
Even = {
195-
type t x = {head: x, tail: R.Odd.t x}
193+
T = {
194+
rec Even = {
195+
type t x = {head: x, tail: Odd.t x}
196196
}
197-
Odd = {
198-
type t x = opt (R.Even.t x)
197+
and Odd = {
198+
type t x = opt (Even.t x)
199199
}
200200
}
201201
in {
202-
...rec (R: {
203-
Even: {
204-
size 'x: T.Even.t x ~> int
205-
}
206-
Odd: {
207-
size 'x: T.Odd.t x ~> int
208-
}
209-
}) => {
210-
Even = {
211-
...T.Even
212-
make 'x (head: x) (tail: T.Odd.t x) :@ T.Even.t x =
213-
{head, tail}
214-
size 'x (v :@ T.Even.t x) = 1 + R.Odd.size v.tail
215-
}
216-
Odd = {
217-
...T.Odd
218-
make 'x (v: opt (T.Even.t x)) :@ T.Odd.t x = v
219-
size 'x (v :@ T.Odd.t x) =
220-
v |> Opt.case {
221-
none = 0
222-
some e = R.Even.size e
223-
}
224-
}
202+
rec Even = {
203+
...T.Even
204+
make 'x (head: x) (tail: T.Odd.t x) :@ T.Even.t x : T.Even.t x =
205+
{head, tail}
206+
size 'x (v :@ T.Even.t x) : int = 1 + Odd.size v.tail
207+
}
208+
and Odd = {
209+
...T.Odd
210+
make 'x (v: opt (T.Even.t x)) :@ T.Odd.t x : T.Odd.t x = v
211+
size 'x (v :@ T.Odd.t x) : int =
212+
v |> Opt.case {
213+
none = 0
214+
some = Even.size
215+
}
225216
}
226217

227218
one = Odd.size (Odd.make (some (Even.make true (Odd.make none))))
@@ -248,7 +239,7 @@ type (a `>>` b) c = c
248239
;;
249240

250241
Hungry = {
251-
type eat a = rec eat_a => a ~> eat_a
242+
rec type eat a = a ~> eat a
252243

253244
eater 'a = rec (eater: eat a) => (fun a => eater) :@ eat a
254245

@@ -258,8 +249,8 @@ Hungry = {
258249
}
259250

260251
PolyRec = {
261-
type l a = rec (type t) => a | t
262-
...rec {type t a} => {type t a = a | t (a, a)}
252+
rec type l a = a | l a
253+
rec type t a = a | t (a, a)
263254

264255
t_int = t int
265256

@@ -283,7 +274,7 @@ ListN = let
283274
}
284275
type T x n (type t _ _) = (type p _) -> I x p t ~> p n
285276
in {
286-
...rec {type t _ _} => {type t x n = wrap T x n t}
277+
rec type t x n = wrap T x n t
287278

288279
case 'x 'n (type p _) (cs: I x p t) (e :# wrap T x n t :@ t x n) =
289280
e p cs
@@ -303,9 +294,9 @@ in {
303294

304295
ListN = {
305296
...ListN
306-
map 'x 'y (xy: x ~> y) = rec (map 'n: t x n ~> t y n) =>
297+
rec map 'x 'y 'n (xy: x ~> y) : t x n ~> t y n =
307298
case (t _) {
308299
nil
309-
x :: xs = xy x :: map xs
300+
x :: xs = xy x :: map xy xs
310301
}
311302
}

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
3939
print "\n"
4040
else
@@ -67,13 +67,13 @@ type STREAM = {
6767
}
6868

6969
divides k n =
70-
let loop = rec loop => fun i => (i * k == n) || ((i * k < n) && loop (i + 1))
70+
let rec loop i = (i * k == n) || ((i * k < n) && loop (i + 1))
7171
loop 1
7272

7373
sift (S : STREAM) :> STREAM = {
7474
type state = S.state
7575
divisor = S.value S.start
76-
filter = rec filter => fun s =>
76+
rec filter s =
7777
if divides divisor (S.value s) then filter (S.next s) else s
7878
start = filter S.start
7979
next s = filter (S.next s)
@@ -92,10 +92,10 @@ Sieve :> STREAM = {
9292
value (S :# state) = S.value S.start
9393
}
9494

95-
nthstate = rec (nthstate : int ~> Sieve.state) => fun n =>
95+
rec nthstate n =
9696
if n == 0 then Sieve.start else Sieve.next (nthstate (n -1))
9797
nthprime n = Sieve.value (nthstate n)
9898

99-
printprimes = rec loop => fun n =>
100-
if n == 0 then () else loop (n - 1) ; Int.print (nthprime n) ; print "\n"
99+
rec printprimes n =
100+
if n <> 0 then printprimes (n - 1) ; Int.print (nthprime n) ; print "\n"
101101
do printprimes 20

0 commit comments

Comments
 (0)