Here is an example for the consumption of a generator:
module Gen = {
type jsYield('v);
type t('i, 'o, 'r);
type yield('p, 'd) =
| Pending('p)
| Done('d);
[@bs.get] external value: jsYield('v) => 'v = "";
[@bs.get] external done_: jsYield('v) => bool = "done";
[@bs.send] external next_: (t('i, 'o, 'r), 'i) => jsYield('o) = "next";
let castYield: (t('i, 'o, 'r), jsYield('o)) => jsYield('r) =
(g, y) => Obj.magic(y);
[@bs.send] external return: (t('i, 'o, 'r), 'r) => jsYield('r) = "";
let next = (g, i) => {
let jsYield = next_(g, i);
let d = done_(jsYield);
if (d) {
let jsYield = castYield(g, jsYield);
Done(value(jsYield));
} else {
let v = value(jsYield);
Pending(v);
};
};
let rec toList = gen => {
let n = next(gen, ());
switch (n) {
| Done(d) => [Done(d)]
| Pending(p) => [Pending(p), ...toList(gen)]
};
};
};
let makeGenWithInput: unit => Gen.t(int, int, string) = [%raw
"function*() {
var a = yield 1;
var b = yield 2 * a;
var c = yield 3 * b;
return 'OK';
}"
];
let makeGen: unit => Gen.t(unit, int, string) = [%raw
"function*() {
yield 1;
yield 2;
yield 3;
return 'OK';
}"
];
let print = v =>
switch (v) {
| Gen.Done(d) => "done: " ++ d
| Pending(v) => "pending: " ++ string_of_int(v)
};
let g = makeGenWithInput();
Js.log(Gen.(g->next(10)->print));
Js.log(Gen.(g->next(20)->print));
Js.log(Gen.(g->next(30)->print));
Js.log(Gen.(g->next(40)->print));
let g = makeGen();
let l = Gen.toList(g);
Belt.List.(map(l, print)->forEach(Js.log));