1
1
package kotlinx.coroutines
2
2
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
5
7
6
8
/* *
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.
11
10
*/
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())
15
27
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
+ }
17
33
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
+ }
20
43
}
21
44
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
26
56
}
57
+ return nextStep != null
58
+ }
27
59
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
30
81
}
31
- })
82
+ }
32
83
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
+ }
35
91
}
36
- suspend override fun yield (value : T ) = CoroutineIntrinsics .suspendCoroutineOrReturn <Unit > { c ->
37
- setNext(value)
38
- nextStep = c
39
92
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
+ }
41
106
}
42
- }
107
+ }
0 commit comments