[K/JS] Compile Kotlin coroutines as JS generator ^KT-63038 Fixed

This commit is contained in:
Artem Kobzar
2023-12-18 17:13:07 +00:00
committed by Space Team
parent 4d07fdf97e
commit 2530cba82a
73 changed files with 2240 additions and 144 deletions
@@ -0,0 +1,57 @@
import kotlin.coroutines.*
abstract class Generator<T> {
private var generatorContinuation: Continuation<Unit>? = null
private var callerContinuation: Continuation<T>? = null
fun resetGenerator() {
this::initGenerator.startCoroutine(object: Continuation<Unit> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<Unit>) {
result.getOrThrow()
}
})
}
suspend fun yieldValue(x: T) {
suspendCoroutine { continuation ->
generatorContinuation = continuation
callerContinuation?.resume(x)
}
}
private suspend fun initGenerator() {
suspendCoroutine { continuation ->
generatorContinuation = continuation
}
generatorBody()
generatorContinuation = null
}
protected abstract suspend fun generatorBody()
fun hasNext(): Boolean {
return generatorContinuation != null
}
suspend fun nextValue(): T {
return suspendCoroutine { continuation ->
callerContinuation = continuation
generatorContinuation?.resume(Unit)
}
}
}
class ClosedRangeGenerator(
private val rangeStart: Int,
private val rangeEnd: Int,
private val step: Int
) : Generator<Int>() {
override suspend fun generatorBody() {
for (i in IntProgression.fromClosedRange(rangeStart, rangeEnd, step)) {
yieldValue(i)
}
}
}
@@ -0,0 +1,5 @@
STEP 0:
modifications:
U : generator.0.kt -> generator.kt
added file: generator.kt
STEP 1:
@@ -0,0 +1,10 @@
STEP 0:
dependencies: lib1
modifications:
U : test.0.kt -> test.kt
added file: test.kt
STEP 1:
dependencies: lib1
modifications:
U : test.1.kt -> test.kt
modified ir: test.kt
@@ -0,0 +1,22 @@
import kotlin.coroutines.*
private fun runCoroutine(c: suspend () -> Unit) {
c.startCoroutine(object: Continuation<Unit> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<Unit>) {
result.getOrThrow()
}
})
}
fun test(): Int {
val generator = ClosedRangeGenerator(0, 0, 1)
generator.resetGenerator()
var s = 0
runCoroutine {
while(generator.hasNext()) {
s += generator.nextValue()
}
}
return s
}
@@ -0,0 +1,22 @@
import kotlin.coroutines.*
private fun runCoroutine(c: suspend () -> Unit) {
c.startCoroutine(object: Continuation<Unit> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<Unit>) {
result.getOrThrow()
}
})
}
fun test(): Int {
val generator = ClosedRangeGenerator(0, 1, 1)
generator.resetGenerator()
var s = 0
runCoroutine {
while(generator.hasNext()) {
s += generator.nextValue()
}
}
return s
}
@@ -0,0 +1,7 @@
fun box(stepId: Int): String {
val got = test()
if (got != stepId) {
return "Fail: $got != $stepId"
}
return "OK"
}
@@ -0,0 +1,5 @@
STEP 0:
dependencies: lib1, lib2
added file: m.kt
STEP 1:
dependencies: lib1, lib2
@@ -0,0 +1,10 @@
MODULES: lib1, lib2, main
STEP 0:
libs: lib1, lib2, main
dirty js modules: lib1, lib2, main
dirty js files: lib1/generator, lib2/test, main/m, main/m.export, main
STEP 1:
libs: lib1, lib2, main
dirty js modules: lib2
dirty js files: lib2/test
@@ -1,3 +1,5 @@
import kotlin.coroutines.*
internal suspend fun testDefaltParam(stepId: Int): Int {
return callFun(ClassA2())
}
@@ -8,9 +10,22 @@ private suspend fun callFun(a: InterfaceA): Int {
return a.functionA(0, "", false)
}
suspend fun box(stepId: Int): String {
suspend fun suspendBox(stepId: Int): String {
if (testDefaltParam(stepId) != stepId) {
return "Fail"
}
return "OK"
}
fun runCoroutine(coroutine: suspend () -> String): String {
var result: String = "Uninitialized"
coroutine.startCoroutine(object : Continuation<String> {
override val context = EmptyCoroutineContext
override fun resumeWith(r: Result<String>) {
result = r.getOrThrow()
}
})
return result
}
fun box(stepId: Int) = runCoroutine { suspendBox(stepId) }