Support 'handleException' operator in JVM backend

This commit is contained in:
Denis Zharkov
2016-06-09 20:56:03 +03:00
parent 6795393989
commit 07dcc6c616
7 changed files with 207 additions and 18 deletions
@@ -0,0 +1,75 @@
// WITH_RUNTIME
class Controller {
var exception: Throwable? = null
val postponedActions = java.util.ArrayList<() -> Unit>()
suspend fun suspendWithValue(v: String, x: Continuation<String>) {
postponedActions.add {
x.resume(v)
}
}
suspend fun suspendWithException(e: Exception, x: Continuation<String>) {
postponedActions.add {
x.resumeWithException(e)
}
}
operator fun handleException(t: Throwable, c: Continuation<Nothing>) {
exception = t
}
fun run(c: Controller.() -> Continuation<Unit>) {
c(this).resume(Unit)
while (postponedActions.isNotEmpty()) {
postponedActions[0]()
postponedActions.removeAt(0)
}
}
}
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
val controller = Controller()
controller.run(c)
if (controller.exception?.message != "OK") {
throw RuntimeException("Unexpected result: ${controller.exception?.message}")
}
}
fun commonThrow(t: Throwable) {
throw t
}
fun box(): String {
builder {
throw RuntimeException("OK")
}
builder {
commonThrow(RuntimeException("OK"))
}
builder {
suspendWithException(RuntimeException("OK"))
}
builder {
try {
suspendWithException(RuntimeException("fail 1"))
} catch (e: RuntimeException) {
suspendWithException(RuntimeException("OK"))
}
}
builder {
try {
suspendWithException(Exception("OK"))
} catch (e: RuntimeException) {
suspendWithException(RuntimeException("fail 3"))
throw RuntimeException("fail 4")
}
}
return "OK"
}
+20 -11
View File
@@ -25,7 +25,21 @@ fun box(): String {
java.lang.Thread.sleep(1000)
return result
if (result != "OK") return "fail notOk"
val future2 = async<String>() {
await(exception("OK"))
"fail"
}
try {
future2.get()
} catch (e: Exception) {
if (e.cause!!.message != "OK") return "fail message: ${e.cause!!.message}"
return "OK"
}
return "No exception"
}
fun <T> async(coroutine c: FutureController<T>.() -> Continuation<Unit>): CompletableFuture<T> {
@@ -37,17 +51,12 @@ fun <T> async(coroutine c: FutureController<T>.() -> Continuation<Unit>): Comple
class FutureController<T> {
val future = CompletableFuture<T>()
suspend fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>) {
f.whenComplete { value, throwable ->
try {
if (throwable == null)
machine.resume(value)
else
machine.resumeWithException(throwable)
} catch (e: Exception) {
future.completeExceptionally(e)
}
if (throwable == null)
machine.resume(value)
else
machine.resumeWithException(throwable)
}
}
@@ -55,7 +64,7 @@ class FutureController<T> {
future.complete(value)
}
fun handleException(t: Throwable, c: Continuation<Nothing>) {
operator fun handleException(t: Throwable, c: Continuation<Nothing>) {
future.completeExceptionally(t)
}
}