Implement basic support for coroutines in JVM backend

This commit is contained in:
Denis Zharkov
2016-05-25 14:46:38 +03:00
parent 077fc528d1
commit 75e112e752
30 changed files with 1151 additions and 45 deletions
+54
View File
@@ -0,0 +1,54 @@
// WITH_RUNTIME
// FULL_JDK
fun box(): String {
val x = gen().joinToString()
if (x != "1, 2") return "fail1: $x"
val y = gen().joinToString()
if (y != "-1") return "fail2: $y"
return "OK"
}
var was = false
fun gen() = generate<Int> {
if (was) {
yield(-1)
return@generate
}
for (i in 1..2) {
yield(i)
}
was = true
}
// LIBRARY CODE
fun <T> generate(coroutine c: GeneratorController<T>.() -> Continuation<Unit>): Sequence<T> = object : Sequence<T> {
override fun iterator(): Iterator<T> {
val iterator = GeneratorController<T>()
iterator.setNextStep(c(iterator))
return iterator
}
}
class GeneratorController<T>() : AbstractIterator<T>() {
private lateinit var nextStep: Continuation<Unit>
override fun computeNext() {
nextStep.resume(Unit)
}
fun setNextStep(step: Continuation<Unit>) {
this.nextStep = step
}
suspend fun yield(value: T, c: Continuation<Unit>) {
setNext(value)
setNextStep(c)
}
fun handleResult(result: Unit, c: Continuation<Nothing>) {
done()
}
}
@@ -0,0 +1,35 @@
class Controller {
var i = 0
suspend fun suspendHere(x: Continuation<String>) {
x.resume((i++).toString())
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
}
fun box(): String {
var result = ""
builder {
result += "-"
result += suspendHere()
if (result == "-0") {
builder {
result += "+"
result += suspendHere()
result += suspendHere()
result += "#"
}
result += suspendHere()
result += "&"
}
}
if (result != "-0+01#1&") return "fail: $result"
return "OK"
}
@@ -0,0 +1,30 @@
class Controller {
var res = 0
suspend fun suspendHere(x: Continuation<String>) {
x.resume("OK")
}
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
res = x
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Int {
val controller = Controller()
c(controller).resume(Unit)
return controller.res
}
fun box(): String {
var result = ""
val handledResult = builder {
result = suspendHere()
return@builder 56
}
if (handledResult != 56) return "fail 1: $handledResult"
return result
}
+19
View File
@@ -0,0 +1,19 @@
class Controller {
suspend fun suspendHere(x: Continuation<String>) {
x.resume("OK")
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
}
fun box(): String {
var result = ""
builder {
result = suspendHere()
}
return result
}
@@ -0,0 +1,24 @@
class Controller {
suspend fun suspendHere(x: Continuation<String>) {
x.resumeWithException(RuntimeException("OK"))
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
}
fun box(): String {
var result = ""
builder {
try {
suspendHere()
result = "fail"
} catch (e: RuntimeException) {
result = "OK"
}
}
return result
}
@@ -0,0 +1,30 @@
class Controller {
var res = 0
suspend fun suspendHere(x: Continuation<String>) {
x.resume("OK")
}
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
res = x
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Int {
val controller = Controller()
c(controller).resume(Unit)
return controller.res
}
fun box(): String {
var result = ""
val handledResult = builder {
result = suspendHere()
56
}
if (handledResult != 56) return "fail 1: $handledResult"
return result
}
@@ -0,0 +1,34 @@
class Controller {
var i = 0
suspend fun suspendHere(x: Continuation<Int>) {
x.resume(i++)
}
suspend fun suspendThere(x: Continuation<String>) {
x.resume("?")
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
}
fun box(): String {
var result = ""
builder {
result += "-"
for (i in 0..5) {
if (i % 2 == 0) {
result += suspendHere().toString()
}
else if (i == 3) {
result += suspendThere()
}
}
result += "+"
}
if (result != "-01?2+") return "fail: $result"
return "OK"
}