11package hxcoro .generators ;
22
3+ import haxe .Unit ;
34import haxe .Exception ;
45import haxe .coro .Coroutine ;
56import haxe .coro .IContinuation ;
@@ -10,21 +11,21 @@ import haxe.exceptions.CoroutineException;
1011import 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}
0 commit comments