Skip to content

Commit c0321a5

Browse files
committed
generalize
1 parent 24976ef commit c0321a5

File tree

2 files changed

+36
-20
lines changed

2 files changed

+36
-20
lines changed
Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package hxcoro.generators;
22

3+
import haxe.Unit;
34
import haxe.Exception;
45
import haxe.coro.Coroutine;
56
import haxe.coro.IContinuation;
@@ -10,21 +11,21 @@ import haxe.exceptions.CoroutineException;
1011
import hxcoro.Coro.*;
1112

1213
@:coroutine.restrictedSuspension
13-
typedef Yield<T> = Coroutine<T -> Void>;
14+
typedef Yield<T, R> = Coroutine<T -> R>;
1415

15-
private class GeneratorImpl<T> extends Dispatcher implements IContinuation<Any> {
16+
private class GeneratorImpl<T, R> extends Dispatcher implements IContinuation<Unit> {
1617
public var context(get, null):Context;
1718

18-
final f:Coroutine<Yield<T> -> Void>;
19+
final f:Coroutine<Yield<T, R> -> Void>;
1920
var nextValue:Null<T>;
20-
var nextStep:Null<IContinuation<T>>;
21+
var nextStep:Null<IContinuation<R>>;
2122
var raisedException:Null<Exception>;
2223
var resumed:Bool;
2324

24-
public function new(f:Coroutine<Yield<T> -> Void>) {
25+
public function new(f:Coroutine<Yield<T, R> -> Void>) {
2526
this.context = Context.create(this);
2627
this.f = f;
27-
resumed = true;
28+
resumed = false;
2829
}
2930

3031
function get_context() {
@@ -38,21 +39,21 @@ private class GeneratorImpl<T> extends Dispatcher implements IContinuation<Any>
3839
public function hasNext() {
3940
if (nextStep == null) {
4041
f(this, yield);
41-
} else if (!resumed) {
42-
nextStep.resume(null, null);
4342
}
4443
return !resumed;
4544
}
4645

47-
public function next() {
46+
public function next(value:R) {
4847
if (raisedException != null) {
4948
resumed = true;
5049
throw raisedException;
5150
}
52-
return nextValue;
51+
var current = nextValue;
52+
nextStep.resume(value, null);
53+
return current;
5354
}
5455

55-
public function resume(result:Null<Any>, error:Null<Exception>) {
56+
public function resume(result:Null<Unit>, error:Null<Exception>) {
5657
if (error != null) {
5758
raisedException = error;
5859
} else {
@@ -64,10 +65,10 @@ private class GeneratorImpl<T> extends Dispatcher implements IContinuation<Any>
6465
obj.onDispatch();
6566
}
6667

67-
@:coroutine function yield(value:T) {
68+
@:coroutine function yield(value:T):R {
6869
resumed = false;
6970
nextValue = value;
70-
suspend(cont -> {
71+
return suspend(cont -> {
7172
nextStep = cont;
7273
});
7374
}
@@ -76,19 +77,19 @@ private class GeneratorImpl<T> extends Dispatcher implements IContinuation<Any>
7677
/**
7778
A synchronous generator that can be used as an `Iterator`.
7879
**/
79-
abstract SyncGenerator<T>(GeneratorImpl<T>) {
80+
abstract SyncGenerator<T>(GeneratorImpl<T, Unit>) from GeneratorImpl<T, Unit> {
8081
/**
8182
@see `Iterator.hasNext`
8283
**/
83-
public inline function hasNext() {
84+
public inline function hasNext():Bool {
8485
return this.hasNext();
8586
}
8687

8788
/**
8889
@see `Iterator.next`
8990
**/
90-
public inline function next() {
91-
return this.next();
91+
public inline function next():Null<T> {
92+
return this.next(Unit);
9293
}
9394

9495
/**
@@ -97,7 +98,21 @@ abstract SyncGenerator<T>(GeneratorImpl<T>) {
9798
The coroutine `f` is executed in a restricted suspension scope, which means
9899
that it cannot call arbitrary coroutines that might suspend.
99100
**/
100-
static public function create<T>(f:Coroutine<Yield<T> -> Void>) {
101+
static public function create<T>(f:Coroutine<Yield<T, Unit> -> Void>):SyncGenerator<T> {
102+
return new GeneratorImpl(f);
103+
}
104+
}
105+
106+
abstract SyncValueGenerator<T, R>(GeneratorImpl<T, R>) from GeneratorImpl<T, R> {
107+
public inline function hasNext() {
108+
return this.hasNext();
109+
}
110+
111+
public inline function next(value:R) {
112+
return this.next(value);
113+
}
114+
115+
static public function create<T, R>(f:Coroutine<Yield<T, R> -> Void>):SyncValueGenerator<T, R> {
101116
return new GeneratorImpl(f);
102117
}
103118
}

tests/src/TestGenerator.hx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import haxe.Unit;
12
import hxcoro.dispatchers.TrampolineDispatcher;
23
import hxcoro.task.CoroTask;
34
import haxe.coro.context.Context;
@@ -15,13 +16,13 @@ class TestGenerator extends utest.Test {
1516
}
1617

1718
function testTreeIter() {
18-
@:coroutine function iterTreeRec<T>(yield:Yield<T>, tree:Tree<T>) {
19+
@:coroutine function iterTreeRec<T>(yield:Yield<T, Unit>, tree:Tree<T>) {
1920
yield(tree.leaf);
2021
if (tree.left != null) iterTreeRec(yield, tree.left);
2122
if (tree.right != null) iterTreeRec(yield, tree.right);
2223
}
2324

24-
function iterTree<T>(tree:Tree<T>):Iterator<T> {
25+
function iterTree<T>(tree:Tree<T>) {
2526
return SyncGenerator.create(yield -> iterTreeRec(yield, tree));
2627
}
2728

0 commit comments

Comments
 (0)