Skip to content

Commit 4bf0cd3

Browse files
authored
Fix iterator / iterable typedefs, add generator typedefs (#8355)
* Fix iterator / iterable typedefs, add generator typedefs * Fix `Generator.asIteratorObject` signature * fixes * result normalization * Add asyncIterable to predef * gentype tests * CHANGELOG
1 parent b0dffe8 commit 4bf0cd3

77 files changed

Lines changed: 3475 additions & 671 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#### :boom: Breaking Change
1616

1717
- Support for `break` and `continue` in loops. `break` and `continue` are new keywords. https://github.com/rescript-lang/rescript/pull/8348
18+
- Fix iterator / iterable typedefs, add generator typedefs. https://github.com/rescript-lang/rescript/pull/8355
1819

1920
#### :eyeglasses: Spec Compliance
2021

compiler/gentype/TranslateTypeExprFromTypes.ml

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,156 @@ let translate_constr ~config ~params_translation ~(path : Path.t) ~type_env =
149149
{dependencies = []; type_ = ident ("Intl." ^ intl_module)}
150150
| (["Stdlib"; "Error"; "t"] | ["Stdlib"; "JsError"; "t"]), [] ->
151151
{dependencies = []; type_ = ident "Error"}
152-
| ["Stdlib"; "Iterator"; "t"], [param_translation] ->
152+
| (["Stdlib"; "Iterable"; "t"] | ["iterable"]), [param_translation] ->
153153
{
154154
dependencies = param_translation.dependencies;
155-
type_ = ident ~type_args:[param_translation.type_] "Iterator";
155+
type_ = ident ~type_args:[param_translation.type_] "Iterable";
156156
}
157-
| ["Stdlib"; "AsyncIterator"; "t"], [param_translation] ->
157+
| ( ["Stdlib"; "Iterator"; "t"],
158+
[yield_translation; return_translation; next_translation] ) ->
159+
{
160+
dependencies =
161+
List.concat
162+
[
163+
yield_translation.dependencies;
164+
return_translation.dependencies;
165+
next_translation.dependencies;
166+
];
167+
type_ =
168+
ident
169+
~type_args:
170+
[
171+
yield_translation.type_;
172+
return_translation.type_;
173+
next_translation.type_;
174+
]
175+
"Iterator";
176+
}
177+
| ( ["Stdlib"; "IteratorObject"; "t"],
178+
[yield_translation; return_translation; next_translation] ) ->
179+
{
180+
dependencies =
181+
List.concat
182+
[
183+
yield_translation.dependencies;
184+
return_translation.dependencies;
185+
next_translation.dependencies;
186+
];
187+
type_ =
188+
ident
189+
~type_args:
190+
[
191+
yield_translation.type_;
192+
return_translation.type_;
193+
next_translation.type_;
194+
]
195+
"IteratorObject";
196+
}
197+
| ( ["Stdlib"; "IterableIterator"; "t"],
198+
[yield_translation; return_translation; next_translation] ) ->
199+
{
200+
dependencies =
201+
List.concat
202+
[
203+
yield_translation.dependencies;
204+
return_translation.dependencies;
205+
next_translation.dependencies;
206+
];
207+
type_ =
208+
ident
209+
~type_args:
210+
[
211+
yield_translation.type_;
212+
return_translation.type_;
213+
next_translation.type_;
214+
]
215+
"IterableIterator";
216+
}
217+
| ( ["Stdlib"; "Generator"; "t"],
218+
[yield_translation; return_translation; next_translation] ) ->
219+
{
220+
dependencies =
221+
List.concat
222+
[
223+
yield_translation.dependencies;
224+
return_translation.dependencies;
225+
next_translation.dependencies;
226+
];
227+
type_ =
228+
ident
229+
~type_args:
230+
[
231+
yield_translation.type_;
232+
return_translation.type_;
233+
next_translation.type_;
234+
]
235+
"Generator";
236+
}
237+
| (["Stdlib"; "AsyncIterable"; "t"] | ["asyncIterable"]), [param_translation]
238+
->
158239
{
159240
dependencies = param_translation.dependencies;
160-
type_ = ident ~type_args:[param_translation.type_] "AsyncIterator";
241+
type_ = ident ~type_args:[param_translation.type_] "AsyncIterable";
242+
}
243+
| ( ["Stdlib"; "AsyncIterator"; "t"],
244+
[yield_translation; return_translation; next_translation] ) ->
245+
{
246+
dependencies =
247+
List.concat
248+
[
249+
yield_translation.dependencies;
250+
return_translation.dependencies;
251+
next_translation.dependencies;
252+
];
253+
type_ =
254+
ident
255+
~type_args:
256+
[
257+
yield_translation.type_;
258+
return_translation.type_;
259+
next_translation.type_;
260+
]
261+
"AsyncIterator";
262+
}
263+
| ( ["Stdlib"; "AsyncIterableIterator"; "t"],
264+
[yield_translation; return_translation; next_translation] ) ->
265+
{
266+
dependencies =
267+
List.concat
268+
[
269+
yield_translation.dependencies;
270+
return_translation.dependencies;
271+
next_translation.dependencies;
272+
];
273+
type_ =
274+
ident
275+
~type_args:
276+
[
277+
yield_translation.type_;
278+
return_translation.type_;
279+
next_translation.type_;
280+
]
281+
"AsyncIterableIterator";
282+
}
283+
| ( ["Stdlib"; "AsyncGenerator"; "t"],
284+
[yield_translation; return_translation; next_translation] ) ->
285+
{
286+
dependencies =
287+
List.concat
288+
[
289+
yield_translation.dependencies;
290+
return_translation.dependencies;
291+
next_translation.dependencies;
292+
];
293+
type_ =
294+
ident
295+
~type_args:
296+
[
297+
yield_translation.type_;
298+
return_translation.type_;
299+
next_translation.type_;
300+
]
301+
"AsyncGenerator";
161302
}
162303
| ["Stdlib"; "Ordering"; "t"], [] -> {dependencies = []; type_ = number_t}
163304
| ["unit"], [] -> {dependencies = []; type_ = unit_t}

compiler/ml/predef.ml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ and ident_exn = ident_create "exn"
4343

4444
and ident_array = ident_create "array"
4545

46+
and ident_iterable = ident_create "iterable"
47+
48+
and ident_async_iterable = ident_create "asyncIterable"
49+
4650
and ident_list = ident_create "list"
4751

4852
and ident_option = ident_create "option"
@@ -86,6 +90,10 @@ and path_exn = Pident ident_exn
8690

8791
and path_array = Pident ident_array
8892

93+
and path_iterable = Pident ident_iterable
94+
95+
and path_async_iterable = Pident ident_async_iterable
96+
8997
and path_list = Pident ident_list
9098

9199
and path_option = Pident ident_option
@@ -118,6 +126,11 @@ and type_exn = newgenty (Tconstr (path_exn, [], ref Mnil))
118126

119127
and type_array t = newgenty (Tconstr (path_array, [t], ref Mnil))
120128

129+
and type_iterable t = newgenty (Tconstr (path_iterable, [t], ref Mnil))
130+
131+
and type_async_iterable t =
132+
newgenty (Tconstr (path_async_iterable, [t], ref Mnil))
133+
121134
and type_list t = newgenty (Tconstr (path_list, [t], ref Mnil))
122135

123136
and type_option t = newgenty (Tconstr (path_option, [t], ref Mnil))
@@ -245,6 +258,22 @@ let common_initial_env add_type add_extension empty_env =
245258
type_arity = 1;
246259
type_variance = [Variance.full];
247260
}
261+
and decl_iterable =
262+
let tvar = newgenvar () in
263+
{
264+
decl_abstr with
265+
type_params = [tvar];
266+
type_arity = 1;
267+
type_variance = [Variance.covariant];
268+
}
269+
and decl_async_iterable =
270+
let tvar = newgenvar () in
271+
{
272+
decl_abstr with
273+
type_params = [tvar];
274+
type_arity = 1;
275+
type_variance = [Variance.covariant];
276+
}
248277
and decl_list =
249278
let tvar = newgenvar () in
250279
{
@@ -369,6 +398,8 @@ let common_initial_env add_type add_extension empty_env =
369398
|> add_type ident_result decl_result
370399
|> add_type ident_promise decl_promise
371400
|> add_type ident_array decl_array
401+
|> add_type ident_iterable decl_iterable
402+
|> add_type ident_async_iterable decl_async_iterable
372403
|> add_type ident_list decl_list
373404
|> add_type ident_dict decl_dict
374405
|> add_type ident_unknown decl_unknown

compiler/ml/predef.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ val type_bool : type_expr
2525
val type_unit : type_expr
2626
val type_exn : type_expr
2727
val type_array : type_expr -> type_expr
28+
val type_iterable : type_expr -> type_expr
29+
val type_async_iterable : type_expr -> type_expr
2830
val type_list : type_expr -> type_expr
2931
val type_option : type_expr -> type_expr
3032
val type_result : type_expr -> type_expr -> type_expr
@@ -41,6 +43,8 @@ val path_bool : Path.t
4143
val path_unit : Path.t
4244
val path_exn : Path.t
4345
val path_array : Path.t
46+
val path_iterable : Path.t
47+
val path_async_iterable : Path.t
4448
val path_list : Path.t
4549
val path_option : Path.t
4650
val path_result : Path.t

packages/@rescript/runtime/Stdlib.res

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@ module String = Stdlib_String
3131
module Symbol = Stdlib_Symbol
3232
module Type = Stdlib_Type
3333

34+
module Iterable = Stdlib_Iterable
3435
module Iterator = Stdlib_Iterator
36+
module IteratorObject = Stdlib_IteratorObject
37+
module IterableIterator = Stdlib_IterableIterator
38+
module Generator = Stdlib_Generator
39+
module AsyncIterable = Stdlib_AsyncIterable
3540
module AsyncIterator = Stdlib_AsyncIterator
41+
module AsyncIterableIterator = Stdlib_AsyncIterableIterator
42+
module AsyncGenerator = Stdlib_AsyncGenerator
3643
module Map = Stdlib_Map
3744
module WeakMap = Stdlib_WeakMap
3845
module Set = Stdlib_Set

packages/@rescript/runtime/Stdlib_Array.res

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ external setUnsafe: (array<'a>, int, 'a) => unit = "%array_unsafe_set"
88

99
external unsafe_get: (array<'a>, int) => 'a = "%array_unsafe_get"
1010

11-
@val external fromIterator: Stdlib_Iterator.t<'a> => array<'a> = "Array.from"
11+
external asIterable: array<'a> => Stdlib_Iterable.t<'a> = "%identity"
12+
13+
@val
14+
external fromIterable: Stdlib_Iterable.t<'a> => array<'a> = "Array.from"
1215
@val external fromArrayLike: arrayLike<'a> => array<'a> = "Array.from"
1316
@val
1417
external fromArrayLikeWithMap: (arrayLike<'a>, 'a => 'b) => array<'b> = "Array.from"
@@ -406,7 +409,7 @@ let last = a => a->get(a->length - 1)
406409
external ignore: array<'a> => unit = "%ignore"
407410

408411
@send
409-
external entries: array<'a> => Stdlib_Iterator.t<(int, 'a)> = "entries"
412+
external entries: array<'a> => Stdlib_IteratorObject.t<(int, 'a), unit, unknown> = "entries"
410413

411414
@send
412-
external values: array<'a> => Stdlib_Iterator.t<'a> = "values"
415+
external values: array<'a> => Stdlib_IteratorObject.t<'a, unit, unknown> = "values"

packages/@rescript/runtime/Stdlib_Array.resi

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,27 @@ type t<'a> = array<'a>
1111
type arrayLike<'a>
1212

1313
/**
14-
`fromIterator(iterator)` creates an array from the provided `iterator`
14+
`asIterable(array)` views `array` as an `Iterable.t`.
15+
16+
This is useful when passing an array to APIs that consume iterables, such as
17+
`Array.from` or `for...of` in JavaScript.
18+
*/
19+
external asIterable: array<'a> => Stdlib_Iterable.t<'a> = "%identity"
20+
21+
/**
22+
`fromIterable(iterable)` creates an array from the provided `iterable`
1523
1624
## Examples
1725
1826
```rescript
1927
Map.fromArray([("foo", 1), ("bar", 2)])
2028
->Map.values
21-
->Array.fromIterator == [1, 2]
29+
->IteratorObject.asIterable
30+
->Array.fromIterable == [1, 2]
2231
```
2332
*/
2433
@val
25-
external fromIterator: Stdlib_Iterator.t<'a> => array<'a> = "Array.from"
34+
external fromIterable: Stdlib_Iterable.t<'a> => array<'a> = "Array.from"
2635

2736
/**
2837
`fromArrayLike(source)` converts an array-like value (anything with indexed items and a `length`) into a regular array.
@@ -1661,13 +1670,12 @@ See [Array.prototype.entries](https://developer.mozilla.org/en-US/docs/Web/JavaS
16611670
16621671
```rescript
16631672
let array = [5, 6, 7]
1664-
let iterator: Iterator.t<(int, int)> = array->Array.entries
1665-
iterator->Iterator.next == {done: false, value: Some((0, 5))}
1666-
iterator->Iterator.next == {done: false, value: Some((1, 6))}
1673+
let iterator: IteratorObject.t<(int, int), unit, unknown> = array->Array.entries
1674+
iterator->IteratorObject.toArray == [(0, 5), (1, 6), (2, 7)]
16671675
```
16681676
*/
16691677
@send
1670-
external entries: array<'a> => Stdlib_Iterator.t<(int, 'a)> = "entries"
1678+
external entries: array<'a> => Stdlib_IteratorObject.t<(int, 'a), unit, unknown> = "entries"
16711679

16721680
/**
16731681
`values(array)` returns a new array iterator object that contains the values for each index in the array.
@@ -1678,10 +1686,9 @@ See [Array.prototype.values](https://developer.mozilla.org/en-US/docs/Web/JavaSc
16781686
16791687
```rescript
16801688
let array = [5, 6, 7]
1681-
let iterator: Iterator.t<int> = array->Array.values
1682-
iterator->Iterator.next == {done: false, value: Some(5)}
1683-
iterator->Iterator.next == {done: false, value: Some(6)}
1689+
let iterator: IteratorObject.t<int, unit, unknown> = array->Array.values
1690+
iterator->IteratorObject.toArray == [5, 6, 7]
16841691
```
16851692
*/
16861693
@send
1687-
external values: array<'a> => Stdlib_Iterator.t<'a> = "values"
1694+
external values: array<'a> => Stdlib_IteratorObject.t<'a, unit, unknown> = "values"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
type t<'yield, 'return, 'next> = Stdlib_AsyncIterable.t<'yield>
2+
3+
external asAsyncIterable: t<'yield, 'return, 'next> => Stdlib_AsyncIterable.t<'yield> = "%identity"
4+
external asAsyncIterableIterator: t<'yield, 'return, 'next> => Stdlib_AsyncIterableIterator.t<
5+
'yield,
6+
'return,
7+
'next,
8+
> = "%identity"
9+
external asAsyncIterator: t<'yield, 'return, 'next> => Stdlib_AsyncIterator.t<
10+
'yield,
11+
'return,
12+
'next,
13+
> = "%identity"
14+
15+
let next = generator => generator->asAsyncIterator->Stdlib_AsyncIterator.next
16+
17+
let nextValue = (generator, value) =>
18+
generator->asAsyncIterator->Stdlib_AsyncIterator.nextValue(value)
19+
20+
@send
21+
external returnValueRaw: (
22+
t<'yield, 'return, 'next>,
23+
'return,
24+
) => promise<Stdlib_AsyncIterator.rawResult<'yield, 'return>> = "return"
25+
26+
let returnValue = async (generator, value) =>
27+
Stdlib_AsyncIterator.normalizeResult(await generator->returnValueRaw(value))
28+
29+
@send
30+
external throwErrorRaw: (
31+
t<'yield, 'return, 'next>,
32+
exn,
33+
) => promise<Stdlib_AsyncIterator.rawResult<'yield, 'return>> = "throw"
34+
35+
let throwError = async (generator, error) =>
36+
Stdlib_AsyncIterator.normalizeResult(await generator->throwErrorRaw(error))

0 commit comments

Comments
 (0)