[JS IR BE] Fix state machine generation in case of composition of loops, inline functions and finally blocks
* lower finally blocks in any cases * do not optimize exit blocks for if-statements
This commit is contained in:
+53
@@ -0,0 +1,53 @@
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
|
||||
class Controller {
|
||||
var result = ""
|
||||
|
||||
suspend fun <T> suspendWithResult(value: T): T = suspendCoroutineUninterceptedOrReturn { c ->
|
||||
c.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun lock(owner: Controller) {
|
||||
owner.result += "L"
|
||||
}
|
||||
|
||||
fun unlock(owner: Controller) {
|
||||
owner.result += "U"
|
||||
}
|
||||
|
||||
public suspend inline fun doInline(owner: Controller, action: () -> Unit): Unit {
|
||||
lock(owner)
|
||||
try {
|
||||
return action()
|
||||
} finally {
|
||||
unlock(owner)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun builder(c: suspend Controller.() -> Unit): String {
|
||||
val controller = Controller()
|
||||
c.startCoroutine(controller, EmptyContinuation)
|
||||
return controller.result
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val value = builder {
|
||||
doInline(this) {
|
||||
result += "X"
|
||||
}
|
||||
}
|
||||
if (value != "LXU") return "fail: $value"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
|
||||
class Controller {
|
||||
var result = ""
|
||||
|
||||
suspend fun <T> suspendWithResult(value: T): T = suspendCoroutineUninterceptedOrReturn { c ->
|
||||
c.resume(value)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
fun Controller.consumeCancel(c: Throwable?) {
|
||||
result += if (c == null) "?" else "!"
|
||||
}
|
||||
|
||||
fun newIterator() = Iterator()
|
||||
|
||||
class Iterator() {
|
||||
var hasNextX = true
|
||||
public suspend fun hasNext(): Boolean {
|
||||
val tmp = hasNextX
|
||||
hasNextX = false
|
||||
return tmp
|
||||
}
|
||||
public suspend fun next(): String = "OK"
|
||||
}
|
||||
|
||||
public inline fun Controller.consume(action: Controller.() -> String?): String? {
|
||||
var cause: Throwable? = null
|
||||
try {
|
||||
return action()
|
||||
} catch(x: Exception) {
|
||||
cause = x
|
||||
throw x
|
||||
} finally {
|
||||
consumeCancel(cause)
|
||||
}
|
||||
}
|
||||
|
||||
public suspend fun Controller.doTest(): String? {
|
||||
return consume {
|
||||
val iterator = newIterator()
|
||||
if (!iterator.hasNext())
|
||||
return null
|
||||
return iterator.next()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun builder(c: suspend Controller.() -> Unit): String {
|
||||
val controller = Controller()
|
||||
c.startCoroutine(controller, EmptyContinuation)
|
||||
return controller.result
|
||||
}
|
||||
|
||||
fun Controller.add(s: String?) {
|
||||
result += s
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val value = builder {
|
||||
add(doTest())
|
||||
}
|
||||
return if (value != "?OK") return "Fail: $value" else "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user