Support new coroutine convention in JVM backend

This commit is contained in:
Denis Zharkov
2016-12-14 20:11:27 +03:00
committed by Stanislav Erokhin
parent 5a6b4a3224
commit 6649f64e9f
97 changed files with 1021 additions and 1373 deletions
+4 -10
View File
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
// NO_INTERCEPT_RESUME_TESTS
// FILE: promise.kt
class Promise<T>(private val executor: ((T) -> Unit) -> Unit) {
@@ -48,12 +49,6 @@ fun processQueue() {
// FILE: await.kt
private var log = ""
class Controller<T>(private val resolve: (T) -> Unit) {
operator fun handleResult(result: T, c: Continuation<Nothing>) {
resolve(result)
}
}
private var inAwait = false
suspend fun <S> await(value: Promise<S>): S = suspendWithCurrentContinuation { continuation: Continuation<S> ->
@@ -67,7 +62,7 @@ suspend fun <S> await(value: Promise<S>): S = suspendWithCurrentContinuation { c
}
}
inAwait = false
Suspend
SUSPENDED
}
suspend fun <S> awaitAndLog(value: Promise<S>): S {
@@ -78,10 +73,9 @@ suspend fun <S> awaitAndLog(value: Promise<S>): S {
})
}
fun <T> async(coroutine c: Controller<T>.() -> Continuation<Unit>): Promise<T> {
fun <T> async(c: @Suspend() (() -> T)): Promise<T> {
return Promise { resolve ->
val controller = Controller<T> { resolve(it) }
c(controller).resume(Unit)
c.startCoroutine(handleResultContinuation(resolve))
}
}
@@ -1,22 +1,22 @@
// WITH_RUNTIME
class Controller {
// WITH_COROUTINES
suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x -> }
fun builder(c: @Suspend() (() -> Unit)) {
var exception: Throwable? = null
operator fun handleException(t: Throwable, c: Continuation<Nothing>) {
exception = t
}
c.createCoroutine(object : Continuation<Unit> {
override fun resume(data: Unit) {
}
suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x -> }
override fun resumeWithException(e: Throwable) {
exception = e
}
}).resumeWithException(RuntimeException("OK"))
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
val controller = Controller()
c(controller).resumeWithException(RuntimeException("OK"))
if (controller.exception?.message != "OK") {
throw RuntimeException("Unexpected result: ${controller.exception?.message}")
if (exception?.message != "OK") {
throw RuntimeException("Unexpected result: ${exception?.message}")
}
}
@@ -1,14 +1,10 @@
// WITH_RUNTIME
class Controller {
suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x ->}
// WITH_COROUTINES
suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x ->}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(c: @Suspend() (() -> Unit)) {
try {
val controller = Controller()
c(controller).resumeWithException(RuntimeException("OK"))
c.createCoroutine(EmptyContinuation).resumeWithException(RuntimeException("OK"))
}
catch(e: Exception) {
if (e?.message != "OK") {
+11 -15
View File
@@ -1,21 +1,17 @@
class Controller {
var result = "fail"
operator fun handleResult(u: Unit, c: Continuation<Nothing>) {
result = "OK"
}
// WITH_RUNTIME
// WITH_COROUTINES
suspend fun <T> await(t: T): T = suspendWithCurrentContinuation { c ->
c.resume(t)
Suspend
}
// INTERCEPT_RESUME_PLACEHOLDER
suspend fun <T> await(t: T): T = suspendWithCurrentContinuation { c ->
c.resume(t)
SUSPENDED
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
val controller = Controller()
c(controller).resume(Unit)
return controller.result
fun builder(c: @Suspend() (() -> Unit)): String {
var result = "fail"
c.startCoroutine(handleResultContinuation {
result = "OK"
})
return result
}
var TRUE = true
@@ -1,18 +1,18 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
c.resume(value)
Suspend
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
@@ -1,18 +1,18 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
c.resume(value)
Suspend
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
@@ -1,18 +1,18 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
c.resume(value)
Suspend
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
@@ -1,18 +1,18 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
c.resume(value)
Suspend
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
@@ -1,18 +1,18 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
c.resume(value)
Suspend
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
@@ -1,18 +1,18 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
c.resume(value)
Suspend
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
@@ -1,5 +1,5 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
// Does not work in JVM backend, probably due to bug. It's not clear which behaviour is right.
// TODO: fix the bug and enable for JVM backend
@@ -11,17 +11,15 @@ class Controller {
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
result += "suspend($value);"
c.resume(value)
Suspend
}
operator fun handleResult(value: String, c: Continuation<Nothing>) {
result += "return($value);"
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(coroutine c: () -> String): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(handleResult {
controller.result += "return($value);"
})
return controller.result
}
@@ -1,5 +1,5 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
@@ -7,13 +7,13 @@ class Controller {
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
result += "["
c.resume(value)
Suspend
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
@@ -1,5 +1,5 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
@@ -7,24 +7,29 @@ class Controller {
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
result += "suspend($value);"
c.resume(value)
Suspend
SUSPENDED
}
// Tail calls are not allowed to be Nothing typed. See KT-15051
suspend fun suspendLogAndThrow(exception: Throwable): Any? = suspendWithCurrentContinuation { c ->
result += "throw(${exception.message});"
c.resumeWithException(exception)
Suspend
}
operator fun handleException(exception: Throwable, c: Continuation<Nothing>) {
result += "caught(${exception.message});"
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, object : Continuation<Unit> {
override fun resume(data: Unit) {
}
override fun resumeWithException(exception: Throwable) {
controller.result += "caught(${exception.message});"
}
})
return controller.result
}
@@ -1,5 +1,5 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
@@ -7,17 +7,19 @@ class Controller {
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
result += "suspend($value);"
c.resume(value)
Suspend
}
operator fun handleException(exception: Throwable, c: Continuation<Nothing>) {
result += "ignoreCaught(${exception.message});"
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, object : Continuation<Unit> {
override fun resume(data: Unit) {}
override fun resumeWithException(exception: Throwable) {
controller.result += "ignoreCaught(${exception.message});"
}
})
return controller.result
}
@@ -1,18 +1,18 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// WITH_COROUTINES
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
c.resume(value)
Suspend
SUSPENDED
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
@@ -1,8 +1,10 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var result = false
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
SUSPENDED
}
fun foo() {
@@ -12,9 +14,9 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(c: @Suspend() (Controller.() -> Unit)) {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation)
if (!controller.result) throw RuntimeException("fail")
}
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(a: String = "abc", i: Int = 2): String = suspendWithCurrentContinuation { x ->
x.resume(a + "#" + (i + 1))
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
+5 -3
View File
@@ -1,18 +1,20 @@
// WITH_RUNTIME
// WITH_COROUTINES
var result = 0
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
result++
x.resume("OK")
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun <T> suspendHere(v: T): T = suspendWithCurrentContinuation { x ->
x.resume(v)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
var result: Any = ""
+22 -22
View File
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
// FULL_JDK
fun box(): String {
@@ -24,35 +25,34 @@ fun gen() = generate<Int> {
}
// 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
}
interface Generator<in T> {
suspend fun yield(value: T)
}
class GeneratorController<T>() : AbstractIterator<T>() {
private lateinit var nextStep: Continuation<Unit>
fun <T> generate(block: @Suspend() (Generator<T>.() -> Unit)): Sequence<T> = GeneratedSequence(block)
class GeneratedSequence<out T>(private val block: @Suspend() (Generator<T>.() -> Unit)) : Sequence<T> {
override fun iterator(): Iterator<T> = GeneratedIterator(block)
}
class GeneratedIterator<T>(block: @Suspend() (Generator<T>.() -> Unit)) : AbstractIterator<T>(), Generator<T> {
private var nextStep: Continuation<Unit> = block.createCoroutine(this, object : Continuation<Unit> {
override fun resume(data: Unit) {
done()
}
override fun resumeWithException(exception: Throwable) {
throw exception
}
})
override fun computeNext() {
nextStep.resume(Unit)
}
fun setNextStep(step: Continuation<Unit>) {
this.nextStep = step
}
suspend fun yield(value: T): Unit = suspendWithCurrentContinuation { c ->
suspend override fun yield(value: T) = suspendWithCurrentContinuation<Unit> { c ->
setNext(value)
setNextStep(c)
nextStep = c
Suspend
SUSPENDED
}
operator fun handleResult(result: Unit, c: Continuation<Nothing>) {
done()
}
// INTERCEPT_RESUME_PLACEHOLDER
}
+8 -11
View File
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var exception: Throwable? = null
val postponedActions = ArrayList<() -> Unit>()
@@ -8,7 +9,7 @@ class Controller {
x.resume(v)
}
Suspend
SUSPENDED
}
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
@@ -16,25 +17,21 @@ class Controller {
x.resumeWithException(e)
}
Suspend
SUSPENDED
}
operator fun handleException(t: Throwable, c: Continuation<Nothing>) {
exception = t
}
fun run(c: Controller.() -> Continuation<Unit>) {
c(this).resume(Unit)
fun run(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(this, handleExceptionContinuation {
exception = it
})
while (postponedActions.isNotEmpty()) {
postponedActions[0]()
postponedActions.removeAt(0)
}
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(c: @Suspend() (Controller.() -> Unit)) {
val controller = Controller()
controller.run(c)
@@ -1,17 +1,12 @@
class Controller {
// WITH_RUNTIME
// WITH_COROUTINES
fun builder(c: @Suspend() (() -> Unit)): String {
var ok = false
operator fun handleResult(u: Unit, v: Continuation<Nothing>) {
c.startCoroutine(handleResultContinuation {
ok = true
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
val controller = Controller()
c(controller).resume(Unit)
if (!controller.ok) throw RuntimeException("Was not called")
})
if (!ok) throw RuntimeException("Was not called")
return "OK"
}
@@ -1,21 +1,17 @@
class Controller {
var isCompleted = false
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
}
// WITH_RUNTIME
// WITH_COROUTINES
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
isCompleted = true
}
// INTERCEPT_RESUME_PLACEHOLDER
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
SUSPENDED
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
val controller = Controller()
c(controller).resume(Unit)
if (!controller.isCompleted) throw RuntimeException("fail")
fun builder(c: @Suspend() (() -> Unit)) {
var isCompleted = false
c.startCoroutine(handleResultContinuation {
isCompleted = true
})
if (!isCompleted) throw RuntimeException("fail")
}
fun box(): String {
@@ -1,22 +1,20 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var log = ""
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { x ->
log += "suspend($value);"
x.resume(value)
Suspend
SUSPENDED
}
operator fun handleResult(value: String, y: Continuation<Nothing>) {
log += "return($value);"
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> String)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, handleResultContinuation {
controller.log += "return($it);"
})
return controller.log
}
+10 -13
View File
@@ -1,20 +1,19 @@
// WITH_RUNTIME
// WITH_COROUTINES
// TARGET_BACKEND: JVM
// NO_INTERCEPT_RESUME_TESTS
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
}
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
SUSPENDED
}
fun builder1(coroutine c: Controller.() -> Continuation<Unit>) {
fun builder1(c: @Suspend() (() -> Unit)) {
(c as Continuation<Unit>).resume(Unit)
}
fun builder2(coroutine c: Controller.() -> Continuation<Unit>) {
val continuation = c(Controller())
val declaredField = continuation.javaClass.superclass.getDeclaredField("label")
fun builder2(c: @Suspend() (() -> Unit)) {
val continuation = c.createCoroutine(EmptyContinuation)
val declaredField = continuation.javaClass.superclass.superclass.getDeclaredField("label")
declaredField.setAccessible(true)
declaredField.set(continuation, -3)
continuation.resume(Unit)
@@ -27,8 +26,7 @@ fun box(): String {
suspendHere()
}
return "fail 1"
} catch (e: java.lang.IllegalStateException) {
if (e.message != "call to 'resume' before 'invoke' with coroutine") return "fail 2: ${e.message!!}"
} catch (e: kotlin.KotlinNullPointerException) {
}
try {
@@ -47,8 +45,7 @@ fun box(): String {
result = "fail 5"
}
return "fail 6"
} catch (e: java.lang.IllegalStateException) {
if (e.message != "call to 'resume' before 'invoke' with coroutine") return "fail 7: ${e.message!!}"
} catch (e: kotlin.KotlinNullPointerException) {
}
try {
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
// WITH_REFLECT
// CHECK_NOT_CALLED: suspendInline_61zpoe$
// CHECK_NOT_CALLED: suspendInline_6r51u9$
@@ -10,7 +11,7 @@ class Controller {
suspend inline fun suspendInline(v: String): String = suspendWithCurrentContinuation { x ->
withValue(v, x)
Suspend
SUSPENDED
}
suspend inline fun suspendInline(crossinline b: () -> String): String = suspendInline(b())
@@ -20,8 +21,8 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
class OK
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
var globalResult = ""
var wasCalled = false
class Controller {
@@ -9,7 +10,7 @@ class Controller {
x.resume(v)
}
Suspend
SUSPENDED
}
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
@@ -17,25 +18,21 @@ class Controller {
x.resumeWithException(e)
}
Suspend
SUSPENDED
}
operator fun handleResult(x: String, c: Continuation<Nothing>) {
globalResult = x
}
fun run(c: Controller.() -> Continuation<Unit>) {
c(this).resume(Unit)
fun run(c: @Suspend() (Controller.() -> String)) {
c.startCoroutine(this, handleResultContinuation {
globalResult = it
})
while (postponedActions.isNotEmpty()) {
postponedActions[0]()
postponedActions.removeAt(0)
}
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(expectException: Boolean = false, coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(expectException: Boolean = false, c: @Suspend() (Controller.() -> String)) {
val controller = Controller()
globalResult = "#"
@@ -1,15 +1,17 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var i = 0
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume((i++).toString())
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,24 +1,25 @@
// WITH_RUNTIME
// WITH_COROUTINES
// WITH_REFLECT
class Controller {
suspend fun runInstanceOf(): Boolean = suspendWithCurrentContinuation { x ->
val y: Any = x
x.resume(x is Continuation<*>)
Suspend
SUSPENDED
}
suspend fun runCast(): Boolean = suspendWithCurrentContinuation { x ->
val y: Any = x
x.resume(Continuation::class.isInstance(y as Continuation<*>))
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun foo() = true
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
private var byteResult: Byte = 0
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
private var booleanResult = false
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
private var byteResult: Byte = 0
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
private var booleanResult = false
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
private var result: String = ""
@@ -1,16 +1,17 @@
// WITH_RUNTIME
// WITH_COROUTINES
// TARGET_BACKEND: JVM
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
@JvmField
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
private var booleanResult = false
@@ -1,16 +1,17 @@
// WITH_RUNTIME
// WITH_COROUTINES
// TARGET_BACKEND: JVM
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
@JvmField
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
x.resume(Unit)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
+28 -12
View File
@@ -1,3 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
// NO_INTERCEPT_RESUME_TESTS
class Controller {
@@ -7,26 +9,40 @@ class Controller {
suspend fun <T> suspendWithValue(value: T): T = suspendWithCurrentContinuation { continuation ->
log += "suspend($value);"
continuation.resume(value)
Suspend
SUSPENDED
}
suspend fun suspendWithException(value: String): Unit = suspendWithCurrentContinuation { continuation ->
log += "error($value);"
continuation.resumeWithException(RuntimeException(value))
Suspend
}
operator fun interceptResume(block: () -> Unit) {
var id = resumeIndex++
log += "before $id;"
block()
log += "after $id;"
SUSPENDED
}
}
fun test(coroutine c: Controller.() -> Continuation<Unit>): String {
fun test(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, EmptyContinuation, object: ResumeInterceptor {
private fun interceptResume(block: () -> Unit) {
val id = controller.resumeIndex++
controller.log += "before $id;"
block()
controller.log += "after $id;"
}
override fun <P> interceptResume(data: P, continuation: Continuation<P>): Boolean {
interceptResume {
continuation.resume(data)
}
return true
}
override fun interceptResumeWithException(exception: Throwable, continuation: Continuation<*>): Boolean {
interceptResume {
continuation.resumeWithException(exception)
}
return true
}
})
return controller.log
}
@@ -50,4 +66,4 @@ fun box(): String {
if (result != "before 0;error(OK);before 1;OK;after 1;after 0;") return "fail2: $result"
return "OK"
}
}
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
+12 -16
View File
@@ -1,22 +1,18 @@
class Controller {
var result = "fail"
suspend fun <V> suspendHere(v: V): V = suspendWithCurrentContinuation { x ->
x.resume(v)
Suspend
}
operator fun handleResult(x: String, c: Continuation<Nothing>) {
result = x
}
// INTERCEPT_RESUME_PLACEHOLDER
// WITH_RUNTIME
// WITH_COROUTINES
// WITH_CONTINUATION
suspend fun <V> suspendHere(v: V): V = suspendWithCurrentContinuation { x ->
x.resume(v)
SUSPENDED
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
val controller = Controller()
c(controller).resume(Unit)
fun builder(c: @Suspend() (() -> String)): String {
var result = "fail"
c.startCoroutine(handleResultContinuation {
result = it
})
return controller.result
return result
}
fun foo(): String = builder {
@@ -1,43 +0,0 @@
class Controller {
suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x ->
x.resume(v)
Suspend
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
c(Controller(), 56L, "OK").resume(Unit)
}
fun noinline(l: () -> String) = l()
inline fun inline(l: () -> String) = l()
fun box(): String {
var result = ""
builder { l, s ->
result = suspendHere(s + "#" + l)
}
if (result != "OK#56") return "fail 1: $result"
builder { l, s ->
result = suspendHere(noinline {
s + "#" + l
})
}
if (result != "OK#56") return "fail 2: $result"
builder { l, s ->
result = suspendHere(inline {
s + "#" + l
})
}
if (result != "OK#56") return "fail 3: $result"
return "OK"
}
@@ -1,22 +1,20 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var result = ""
var ok = false
suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x ->
result += v
x.resume(Unit)
Suspend
SUSPENDED
}
operator fun handleResult(u: Unit, v: Continuation<Nothing>) {
ok = true
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, handleResultContinuation {
controller.ok = true
})
if (!controller.ok) throw RuntimeException("Fail ok")
return controller.result
}
+11 -16
View File
@@ -1,22 +1,17 @@
class Controller {
var wasHandleResultCalled = false
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
}
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
wasHandleResultCalled = true
}
// INTERCEPT_RESUME_PLACEHOLDER
// WITH_RUNTIME
// WITH_COROUTINES
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
SUSPENDED
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
val controller = Controller()
c(controller).resume(Unit)
fun builder(c: @Suspend() (() -> Unit)) {
var wasHandleResultCalled = false
c.startCoroutine(handleResultContinuation {
wasHandleResultCalled = true
})
if (!controller.wasHandleResultCalled) throw RuntimeException("fail 1")
if (!wasHandleResultCalled) throw RuntimeException("fail 1")
}
fun box(): String {
@@ -1,22 +1,17 @@
class Controller {
var wasHandleResultCalled = false
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
}
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
wasHandleResultCalled = true
}
// INTERCEPT_RESUME_PLACEHOLDER
// WITH_RUNTIME
// WITH_COROUTINES
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
SUSPENDED
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
val controller = Controller()
c(controller).resume(Unit)
fun builder(c: @Suspend() (() -> Unit)) {
var wasHandleResultCalled = false
c.startCoroutine(handleResultContinuation {
wasHandleResultCalled = true
})
if (!controller.wasHandleResultCalled) throw RuntimeException("fail 1")
if (!wasHandleResultCalled) throw RuntimeException("fail 1")
}
var varWithCustomSetter: String = ""
@@ -1,22 +1,20 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var ok = false
var v = "fail"
suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x ->
this.v = v
x.resume(Unit)
Suspend
SUSPENDED
}
operator fun handleResult(u: Unit, v: Continuation<Nothing>) {
ok = true
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
fun builder(c: @Suspend() (Controller.() -> Unit)): String {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, handleResultContinuation {
controller.ok = true
})
if (!controller.ok) throw RuntimeException("Fail 1")
return controller.v
}
@@ -1,41 +0,0 @@
// IGNORE_BACKEND: JS
// WITH_RUNTIME
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
}
fun box(): String {
var result = "fail"
val lambda: Controller.() -> Continuation<Unit> = l1@{
object : Continuation<Any?> {
override fun resume(data: Any?) {
if (data == Unit) {
this@l1.javaClass.getMethod("suspendHere", Continuation::class.java).invoke(this@l1, this)
return
}
if (data != "OK") {
throw RuntimeException("fail: $data")
}
result = "OK"
}
override fun resumeWithException(exception: Throwable) = throw exception
}
}
builder(lambda)
return result
}
@@ -1,3 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
// MODULE: controller
// FILE: controller.kt
package lib
@@ -5,7 +7,7 @@ package lib
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
@@ -15,8 +17,8 @@ class Controller {
// FILE: main.kt
import lib.*
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,3 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
// MODULE: controller
// FILE: controller.kt
package lib
@@ -6,7 +8,7 @@ package lib
class Controller {
suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume(this)
Suspend
SUSPENDED
}
inline suspend fun String.inlineSuspendHere(): String = suspendHere()
@@ -26,8 +28,8 @@ suspend fun Controller.localSuspendExtension(v: String) = v.suspendHere()
inline suspend fun Controller.localInlineSuspendExtension(v: String) = v.inlineSuspendHere()
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,9 +1,11 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var lastSuspension: Continuation<String>? = null
var result = "fail"
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
lastSuspension = x
Suspend
SUSPENDED
}
fun hasNext() = lastSuspension != null
@@ -16,26 +18,26 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(c: @Suspend() (Controller.() -> Unit)) {
val controller1 = Controller()
val controller2 = Controller()
c(controller1).resume(Unit)
c(controller2).resume(Unit)
runControllers(controller1, controller2)
}
fun builder2(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
val controller1 = Controller()
val controller2 = Controller()
c(controller1, 1234567890123456789L, "Q").resume(Unit)
c(controller2, 1234567890123456789L, "Q").resume(Unit)
c.startCoroutine(controller1, EmptyContinuation)
c.startCoroutine(controller2, EmptyContinuation)
runControllers(controller1, controller2)
}
// TODO: additional parameters are not supported yet
//fun builder2(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
// val controller1 = Controller()
// val controller2 = Controller()
//
// c(controller1, 1234567890123456789L, "Q").resume(Unit)
// c(controller2, 1234567890123456789L, "Q").resume(Unit)
//
// runControllers(controller1, controller2)
//}
private fun runControllers(controller1: Controller, controller2: Controller) {
while (controller1.hasNext()) {
@@ -72,28 +74,25 @@ fun box(): String {
result = "OK"
}
// with capture and params
// with capture
var x = "O"
var y = "K"
// no suspension
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
builder {
result = x + y
}
// 1 suspension
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
if (suspendHere() != "56") return@builder2
builder {
if (suspendHere() != "56") return@builder
result = x + y
}
// 2 suspensions
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
if (suspendHere() != "56") return@builder2
builder {
if (suspendHere() != "56") return@builder
suspendHere()
result = x + y
}
@@ -1,9 +1,11 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var lastSuspension: Continuation<String>? = null
var result = "fail"
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
lastSuspension = x
Suspend
SUSPENDED
}
fun hasNext() = lastSuspension != null
@@ -16,26 +18,26 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(c: @Suspend() (Controller.() -> Unit)) {
val controller1 = Controller()
val controller2 = Controller()
c(controller1).resume(Unit)
c(controller2).resume(Unit)
runControllers(controller1, controller2)
}
fun builder2(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
val controller1 = Controller()
val controller2 = Controller()
c(controller1, 1234567890123456789L, "Q").resume(Unit)
c(controller2, 1234567890123456789L, "Q").resume(Unit)
c.startCoroutine(controller1, EmptyContinuation)
c.startCoroutine(controller2, EmptyContinuation)
runControllers(controller1, controller2)
}
// TODO: additional parameters are not supported yet
//fun builder2(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
// val controller1 = Controller()
// val controller2 = Controller()
//
// c(controller1, 1234567890123456789L, "Q").resume(Unit)
// c(controller2, 1234567890123456789L, "Q").resume(Unit)
//
// runControllers(controller1, controller2)
//}
private fun runControllers(controller1: Controller, controller2: Controller) {
while (controller1.hasNext()) {
@@ -66,22 +68,19 @@ fun box(): String {
// inlined
run {
// no suspension
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
builder {
result = x + y
}
// 1 suspension
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
if (suspendHere() != "56") return@builder2
builder {
if (suspendHere() != "56") return@builder
result = x + y
}
// 2 suspensions
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
if (suspendHere() != "56") return@builder2
builder {
if (suspendHere() != "56") return@builder
suspendHere()
result = x + y
}
@@ -1,9 +1,11 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var lastSuspension: Continuation<String>? = null
var result = "fail"
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
lastSuspension = x
Suspend
SUSPENDED
}
fun hasNext() = lastSuspension != null
@@ -16,26 +18,26 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(c: @Suspend() (Controller.() -> Unit)) {
val controller1 = Controller()
val controller2 = Controller()
c(controller1).resume(Unit)
c(controller2).resume(Unit)
runControllers(controller1, controller2)
}
fun builder2(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
val controller1 = Controller()
val controller2 = Controller()
c(controller1, 1234567890123456789L, "Q").resume(Unit)
c(controller2, 1234567890123456789L, "Q").resume(Unit)
c.startCoroutine(controller1, EmptyContinuation)
c.startCoroutine(controller2, EmptyContinuation)
runControllers(controller1, controller2)
}
// TODO: additional parameters are not supported yet
//fun builder2(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
// val controller1 = Controller()
// val controller2 = Controller()
//
// c(controller1, 1234567890123456789L, "Q").resume(Unit)
// c(controller2, 1234567890123456789L, "Q").resume(Unit)
//
// runControllers(controller1, controller2)
//}
private fun runControllers(controller1: Controller, controller2: Controller) {
while (controller1.hasNext()) {
@@ -83,28 +85,6 @@ fun box(): String {
suspendHere()
result = "OK"
}
// no suspension
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
result = x + y
}
// 1 suspension
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
if (suspendHere() != "56") return@builder2
result = x + y
}
// 2 suspensions
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
if (suspendHere() != "56") return@builder2
suspendHere()
result = x + y
}
}()
}
@@ -1,9 +1,11 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var lastSuspension: Continuation<String>? = null
var result = "fail"
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
lastSuspension = x
Suspend
SUSPENDED
}
fun hasNext() = lastSuspension != null
@@ -16,26 +18,26 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(c: @Suspend() (Controller.() -> Unit)) {
val controller1 = Controller()
val controller2 = Controller()
c(controller1).resume(Unit)
c(controller2).resume(Unit)
runControllers(controller1, controller2)
}
fun builder2(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
val controller1 = Controller()
val controller2 = Controller()
c(controller1, 1234567890123456789L, "Q").resume(Unit)
c(controller2, 1234567890123456789L, "Q").resume(Unit)
c.startCoroutine(controller1, EmptyContinuation)
c.startCoroutine(controller2, EmptyContinuation)
runControllers(controller1, controller2)
}
// TODO: additional parameters are not supported yet
//fun builder2(coroutine c: Controller.(Long, String) -> Continuation<Unit>) {
// val controller1 = Controller()
// val controller2 = Controller()
//
// c(controller1, 1234567890123456789L, "Q").resume(Unit)
// c(controller2, 1234567890123456789L, "Q").resume(Unit)
//
// runControllers(controller1, controller2)
//}
private fun runControllers(controller1: Controller, controller2: Controller) {
while (controller1.hasNext()) {
@@ -81,28 +83,6 @@ fun box(): String {
suspendHere()
result = "OK"
}
// no suspension
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
result = x + y
}
// 1 suspension
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
if (suspendHere() != "56") return@builder2
result = x + y
}
// 2 suspensions
builder2 { a, b ->
if (a != 1234567890123456789L || b != "Q" ) return@builder2
if (suspendHere() != "56") return@builder2
suspendHere()
result = x + y
}
}
} ()
+8 -9
View File
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
var globalResult = ""
var wasCalled = false
class Controller {
@@ -9,7 +10,7 @@ class Controller {
x.resume(v)
}
Suspend
SUSPENDED
}
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
@@ -17,15 +18,13 @@ class Controller {
x.resumeWithException(e)
}
Suspend
SUSPENDED
}
operator fun handleResult(x: String, c: Continuation<Nothing>) {
globalResult = x
}
fun run(c: Controller.() -> Continuation<Unit>) {
c(this).resume(Unit)
fun run(c: @Suspend() (Controller.() -> String)) {
c.startCoroutine(this, handleResultContinuation {
globalResult = it
})
while (postponedActions.isNotEmpty()) {
postponedActions[0]()
postponedActions.removeAt(0)
@@ -35,7 +34,7 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(expectException: Boolean = false, coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(expectException: Boolean = false, c: @Suspend() (Controller.() -> String)) {
val controller = Controller()
globalResult = "#"
@@ -1,17 +1,13 @@
class Controller {
// WITH_RUNTIME
// WITH_COROUTINES
fun builder(c: @Suspend() (() -> Int)): Int {
var res = 0
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
res = x
}
c.startCoroutine(handleResultContinuation {
res = it
})
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Int {
val controller = Controller()
c(controller).resume(Unit)
return controller.res
return res
}
fun box(): String {
@@ -1,20 +1,18 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var cResult = 0
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
x.resume(v * 2)
Suspend
SUSPENDED
}
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
cResult = x
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Controller {
fun builder(c: @Suspend() (Controller.() -> Int)): Controller {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, handleResultContinuation {
controller.cResult = it
})
return controller
}
@@ -1,22 +1,19 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var cResult = 0
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
x.resume(v * 2)
Suspend
SUSPENDED
}
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
cResult = x
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Controller {
fun builder(c: @Suspend() (Controller.() -> Int)): Controller {
val controller = Controller()
c(controller).resume(Unit)
c.startCoroutine(controller, handleResultContinuation {
controller.cResult = it
})
return controller
}
+11 -16
View File
@@ -1,22 +1,17 @@
class Controller {
var res = 0
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
}
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
res = x
}
// INTERCEPT_RESUME_PLACEHOLDER
// WITH_RUNTIME
// WITH_COROUTINES
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
SUSPENDED
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Int {
val controller = Controller()
c(controller).resume(Unit)
fun builder(c: @Suspend() (() -> Int)): Int {
var res = 0
c.startCoroutine(handleResultContinuation {
res = it
})
return controller.res
return res
}
fun box(): String {
+8 -8
View File
@@ -1,14 +1,14 @@
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
}
// IGNORE_BACKEND: JS
// WITH_RUNTIME
// WITH_COROUTINES
// INTERCEPT_RESUME_PLACEHOLDER
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
SUSPENDED
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resumeWithException(RuntimeException("OK"))
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,23 +1,27 @@
class Controller {
// WITH_RUNTIME
// WITH_COROUTINES
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
SUSPENDED
}
fun builder(c: @Suspend() () -> Int): Int {
var res = 0
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
}
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
res = x
}
c.createCoroutine(object : Continuation<Int> {
override fun resume(data: Int) {
res = data
}
// INTERCEPT_RESUME_PLACEHOLDER
override fun resumeWithException(exception: Throwable) {
throw exception
}
}).resume(Unit)
return res
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>): Int {
val controller = Controller()
c(controller).resume(Unit)
return controller.res
}
fun box(): String {
var result = ""
@@ -1,11 +1,13 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): String = throw RuntimeException("OK")
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
// WITH_REFLECT
// CHECK_NOT_CALLED: suspendInline_61zpoe$
// CHECK_NOT_CALLED: suspendInline_6r51u9$
@@ -13,8 +14,8 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
class OK
@@ -1,11 +1,13 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere() = "OK"
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,3 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x ->
1
@@ -9,8 +11,8 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,19 +1,15 @@
// WITH_RUNTIME
// WITH_COROUTINES
var globalResult = ""
class Controller {
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
x.resume(v)
Suspend
}
operator fun handleResult(x: String, c: Continuation<Nothing>) {
globalResult = x
}
// INTERCEPT_RESUME_PLACEHOLDER
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
x.resume(v)
SUSPENDED
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (() -> String)) {
c.startCoroutine(handleResultContinuation {
globalResult = it
})
}
fun box(): String {
@@ -1,16 +1,18 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): String = suspendThere()
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,8 +1,10 @@
// WITH_RUNTIME
// WITH_COROUTINES
@AllowSuspendExtensions
class Controller {
suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume(this)
Suspend
SUSPENDED
}
inline suspend fun String.inlineSuspendHere(): String = suspendHere()
@@ -14,8 +16,8 @@ suspend fun Controller.suspendExtension(v: String): String = v.suspendHere()
inline suspend fun Controller.inlineSuspendExtension(v: String): String = v.inlineSuspendHere()
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
x.resume(v * 2)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
inline fun foo(x: (Int) -> Unit) {
+6 -4
View File
@@ -1,19 +1,21 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
var i = 0
suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x ->
x.resume(i++)
Suspend
SUSPENDED
}
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
x.resume("?")
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,24 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("K")
Suspend
SUSPENDED
}
suspend fun suspendWithArgument(v: String): String = suspendWithCurrentContinuation { x ->
x.resume(v)
Suspend
SUSPENDED
}
suspend fun suspendWithDouble(v: Double): Double = suspendWithCurrentContinuation { x ->
x.resume(v)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
class A(val first: String, val second: String) {
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
var globalResult = ""
var wasCalled = false
class Controller {
@@ -9,7 +10,7 @@ class Controller {
x.resume(v)
}
Suspend
SUSPENDED
}
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
@@ -17,15 +18,13 @@ class Controller {
x.resumeWithException(e)
}
Suspend
SUSPENDED
}
operator fun handleResult(x: String, c: Continuation<Nothing>) {
globalResult = x
}
fun run(c: Controller.() -> Continuation<Unit>) {
c(this).resume(Unit)
fun run(c: @Suspend() (Controller.() -> String)) {
c.startCoroutine(this, handleResultContinuation {
globalResult = it
})
while (postponedActions.isNotEmpty()) {
postponedActions[0]()
postponedActions.removeAt(0)
@@ -35,7 +34,7 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(expectException: Boolean = false, coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(expectException: Boolean = false, c: @Suspend() (Controller.() -> String)) {
val controller = Controller()
globalResult = "#"
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
var globalResult = ""
var wasCalled = false
class Controller {
@@ -9,7 +10,7 @@ class Controller {
x.resume(v)
}
Suspend
SUSPENDED
}
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
@@ -17,25 +18,21 @@ class Controller {
x.resumeWithException(e)
}
Suspend
SUSPENDED
}
operator fun handleResult(x: String, c: Continuation<Nothing>) {
globalResult = x
}
fun run(c: Controller.() -> Continuation<Unit>) {
c(this).resume(Unit)
fun run(c: @Suspend() (Controller.() -> String)) {
c.startCoroutine(this, handleResultContinuation {
globalResult = it
})
while (postponedActions.isNotEmpty()) {
postponedActions[0]()
postponedActions.removeAt(0)
}
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(expectException: Boolean = false, coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(expectException: Boolean = false, c: @Suspend() (Controller.() -> String)) {
val controller = Controller()
globalResult = "#"
@@ -1,15 +1,17 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x ->
x.resume(v)
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
inline fun run(block: () -> Unit) {
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
var globalResult = ""
var wasCalled = false
class Controller {
@@ -9,7 +10,7 @@ class Controller {
x.resume(v)
}
Suspend
SUSPENDED
}
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
@@ -17,15 +18,13 @@ class Controller {
x.resumeWithException(e)
}
Suspend
SUSPENDED
}
operator fun handleResult(x: String, c: Continuation<Nothing>) {
globalResult = x
}
fun run(c: Controller.() -> Continuation<Unit>) {
c(this).resume(Unit)
fun run(c: @Suspend() (Controller.() -> String)) {
c.startCoroutine(this, handleResultContinuation {
globalResult = it
})
while (postponedActions.isNotEmpty()) {
postponedActions[0]()
postponedActions.removeAt(0)
@@ -35,7 +34,7 @@ class Controller {
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(expectException: Boolean = false, coroutine c: Controller.() -> Continuation<Unit>) {
fun builder(expectException: Boolean = false, c: @Suspend() (Controller.() -> String)) {
val controller = Controller()
globalResult = "#"
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
@@ -1,14 +1,16 @@
// WITH_RUNTIME
// WITH_COROUTINES
class Controller {
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
x.resume("OK")
Suspend
SUSPENDED
}
// INTERCEPT_RESUME_PLACEHOLDER
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
c(Controller()).resume(Unit)
fun builder(c: @Suspend() (Controller.() -> Unit)) {
c.startCoroutine(Controller(), EmptyContinuation)
}
fun box(): String {
+19 -25
View File
@@ -43,32 +43,26 @@ fun box(): String {
// LIBRARY CODE
fun <T> async(coroutine c: FutureController<T>.() -> Continuation<Unit>): CompletableFuture<T> {
val controller = FutureController<T>()
c(controller).resume(Unit)
return controller.future
}
class FutureController<T> {
fun <T> async(c: @Suspend() (() -> T)): CompletableFuture<T> {
val future = CompletableFuture<T>()
suspend fun <V> await(f: CompletableFuture<V>) = suspendWithCurrentContinuation<V> { machine ->
f.whenComplete { value, throwable ->
if (throwable == null)
machine.resume(value)
else
machine.resumeWithException(throwable)
c.startCoroutine(object : Continuation<T> {
override fun resume(data: T) {
future.complete(data)
}
Suspend
}
operator fun handleResult(value: T, c: Continuation<Nothing>) {
future.complete(value)
}
fun handleException(t: Throwable, c: Continuation<Nothing>) {
future.completeExceptionally(t)
}
override fun resumeWithException(exception: Throwable) {
future.completeExceptionally(exception)
}
})
return future
}
suspend fun <V> await(f: CompletableFuture<V>) = suspendWithCurrentContinuation<V> { machine ->
f.whenComplete { value, throwable ->
if (throwable == null)
machine.resume(value)
else
machine.resumeWithException(throwable)
}
SUSPENDED
}
+19 -24
View File
@@ -40,31 +40,26 @@ fun box(): String {
return "No exception"
}
fun <T> async(coroutine c: FutureController<T>.() -> Continuation<Unit>): CompletableFuture<T> {
val controller = FutureController<T>()
c(controller).resume(Unit)
return controller.future
}
class FutureController<T> {
fun <T> async(c: @Suspend() (() -> T)): CompletableFuture<T> {
val future = CompletableFuture<T>()
suspend fun <V> await(f: CompletableFuture<V>) = suspendWithCurrentContinuation<V> { machine ->
f.whenComplete { value, throwable ->
if (throwable == null)
machine.resume(value)
else
machine.resumeWithException(throwable)
c.startContinuation(object : Continuation<T> {
override fun resume(data: T) {
future.complete(data)
}
Suspend
}
operator fun handleResult(value: T, c: Continuation<Nothing>) {
future.complete(value)
}
operator fun handleException(t: Throwable, c: Continuation<Nothing>) {
future.completeExceptionally(t)
}
override fun resumeWithException(exception: Throwable) {
future.completeExceptionally(exception)
}
})
return future
}
suspend fun <V> await(f: CompletableFuture<V>) = suspendWithCurrentContinuation<V> { machine ->
f.whenComplete { value, throwable ->
if (throwable == null)
machine.resume(value)
else
machine.resumeWithException(throwable)
}
SUSPENDED
}