Support non-local returns to coroutine label from inline lambda

- Use proper class descriptor when retreiving continuation object (see previous commit)
- Use return type as VOID for such cases
- Load correct labels related to coroutine lambda from outer context
This commit is contained in:
Denis Zharkov
2016-05-25 15:28:44 +03:00
parent 94bd6dcc82
commit 611490e080
8 changed files with 167 additions and 7 deletions
@@ -0,0 +1,43 @@
class Controller {
var cResult = 0
suspend fun suspendHere(v: Int, x: Continuation<Int>) {
x.resume(v * 2)
}
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
cResult = x
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Controller {
val controller = Controller()
c(controller).resume(Unit)
return controller
}
inline fun foo(x: (Int) -> Unit) {
for (i in 1..2) {
x(i)
}
}
fun box(): String {
var result = ""
val controllerResult = builder {
result += "-"
foo {
result += suspendHere(it).toString()
if (it == 2) return@builder 56
}
// Should be unreachable
result += "+"
1
}.cResult
if (result != "-24") return "fail 1: $result"
if (controllerResult != 56) return "fail 2: $controllerResult"
return "OK"
}
@@ -0,0 +1,49 @@
// WITH_RUNTIME
class Controller {
var cResult = 0
suspend fun suspendHere(v: Int, x: Continuation<Int>) {
x.resume(v * 2)
}
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
cResult = x
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Controller {
val controller = Controller()
c(controller).resume(Unit)
return controller
}
inline fun foo(x: (Int) -> Unit) {
for (i in 1..2) {
run {
x(i)
}
}
}
fun box(): String {
var result = ""
val controllerResult = builder {
result += "-"
foo {
run {
result += suspendHere(it).toString()
if (it == 2) return@builder 56
}
}
// Should be unreachable
result += "+"
1
}.cResult
if (result != "-24") return "fail 1: $result"
if (controllerResult != 56) return "fail 2: $controllerResult"
return "OK"
}