11package kotlinx.coroutines
22
3- import kotlin.coroutines.*
4- import kotlin.coroutines.CoroutineIntrinsics.SUSPENDED
3+ import kotlin.coroutines.Continuation
4+ import kotlin.coroutines.CoroutineIntrinsics
5+ import kotlin.coroutines.RestrictsSuspension
6+ import kotlin.coroutines.createCoroutine
57
68/* *
7- * Creates a Sequence object based on received coroutine [c].
8- *
9- * Each call of 'yield' suspend function within the coroutine lambda generates
10- * next element of resulting sequence.
9+ * Scope of [generate] block.
1110 */
12- interface Generator <in T > {
13- suspend fun yield (value : T )
14- }
11+ @RestrictsSuspension
12+ public abstract class Generator <in T > internal constructor() {
13+ /* *
14+ * Yields a value in [generate] block.
15+ */
16+ public abstract suspend fun yield (value : T )
17+
18+ /* *
19+ * Yields potentially infinite sequence of iterator values in [generate] block.
20+ */
21+ public abstract suspend fun yieldAll (iterator : Iterator <T >)
22+
23+ /* *
24+ * Yields a collections of values in [generate] block.
25+ */
26+ public suspend fun yieldAll (elements : Iterable <T >) = yieldAll(elements.iterator())
1527
16- fun <T > generate (block : suspend Generator <T >.() -> Unit ): Sequence <T > = GeneratedSequence (block)
28+ /* *
29+ * Yields potentially infinite sequence of values in [generate] block.
30+ */
31+ public suspend fun yieldAll (sequence : Sequence <T >) = yieldAll(sequence.iterator())
32+ }
1733
18- private class GeneratedSequence <out T >(private val block : suspend Generator <T >.() -> Unit ) : Sequence<T> {
19- override fun iterator (): Iterator <T > = GeneratedIterator (block)
34+ /* *
35+ * Generates lazy sequence.
36+ */
37+ public fun <T > generate (block : suspend Generator <T >.() -> Unit ): Sequence <T > = object : Sequence <T > {
38+ override fun iterator (): Iterator <T > {
39+ val iterator = GeneratorIterator <T >()
40+ iterator.nextStep = block.createCoroutine(receiver = iterator, completion = iterator)
41+ return iterator
42+ }
2043}
2144
22- private class GeneratedIterator <T >(block : suspend Generator <T >.() -> Unit ) : AbstractIterator<T>(), Generator<T> {
23- private var nextStep: Continuation <Unit > = block.createCoroutine(this , object : Continuation <Unit > {
24- override fun resume (data : Unit ) {
25- done()
45+ private class GeneratorIterator <T >: Generator <T >(), Iterator<T>, Continuation<Unit> {
46+ var computedNext = false
47+ var nextStep: Continuation <Unit >? = null
48+ var nextValue: T ? = null
49+
50+ override fun hasNext (): Boolean {
51+ if (! computedNext) {
52+ val step = nextStep!!
53+ computedNext = true
54+ nextStep = null
55+ step.resume(Unit ) // leaves it in "done" state if crashes
2656 }
57+ return nextStep != null
58+ }
2759
28- override fun resumeWithException (exception : Throwable ) {
29- throw exception
60+ override fun next (): T {
61+ if (! hasNext()) throw NoSuchElementException ()
62+ computedNext = false
63+ return nextValue as T
64+ }
65+
66+ // Completion continuation implementation
67+ override fun resume (value : Unit ) {
68+ // nothing to do here -- leave null in nextStep
69+ }
70+
71+ override fun resumeWithException (exception : Throwable ) {
72+ throw exception // just rethrow
73+ }
74+
75+ // Generator implementation
76+ override suspend fun yield (value : T ) {
77+ nextValue = value
78+ return CoroutineIntrinsics .suspendCoroutineOrReturn { c ->
79+ nextStep = c
80+ CoroutineIntrinsics .SUSPENDED
3081 }
31- })
82+ }
3283
33- override fun computeNext () {
34- nextStep.resume(Unit )
84+ override suspend fun yieldAll (iterator : Iterator <T >) {
85+ if (! iterator.hasNext()) return
86+ nextValue = iterator.next()
87+ return CoroutineIntrinsics .suspendCoroutineOrReturn { c ->
88+ nextStep = IteratorContinuation (c, iterator)
89+ CoroutineIntrinsics .SUSPENDED
90+ }
3591 }
36- suspend override fun yield (value : T ) = CoroutineIntrinsics .suspendCoroutineOrReturn <Unit > { c ->
37- setNext(value)
38- nextStep = c
3992
40- SUSPENDED
93+ inner class IteratorContinuation (val completion : Continuation <Unit >, val iterator : Iterator <T >) : Continuation<Unit> {
94+ override fun resume (value : Unit ) {
95+ if (! iterator.hasNext()) {
96+ completion.resume(Unit )
97+ return
98+ }
99+ nextValue = iterator.next()
100+ nextStep = this
101+ }
102+
103+ override fun resumeWithException (exception : Throwable ) {
104+ throw exception // just rethrow
105+ }
41106 }
42- }
107+ }
0 commit comments