Fixes for inline fun finally block generation before lambda non-local returns

This commit is contained in:
Michael Bogdanov
2014-10-23 11:27:53 +04:00
parent 25d7c9f20a
commit dd8c3f0e49
10 changed files with 462 additions and 40 deletions
@@ -0,0 +1,64 @@
import test.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
class MyException(message: String) : Exception(message)
class Holder(var value: String) {
public fun plusAssign(s: String?) {
value += s
if (s != "closed") {
value += "->"
}
}
}
class Test() : MCloseable {
val status = Holder("")
private fun jobFun() {
status += "called"
}
fun nonLocalWithExceptionAndFinally(): Holder {
muse {
try {
jobFun()
throw MyException("exception")
}
catch (e: MyException) {
status += e.getMessage()
return status
}
finally {
status += "finally"
}
}
return Holder("fail")
}
override fun close() {
status += "closed"
throw MyException("error")
}
}
fun box() : String {
assertError(1, "called->exception->finally->closed") {
nonLocalWithExceptionAndFinally()
}
return "OK"
}
public fun assertError(index: Int, expected: String, l: Test.()->Unit) {
val testLocal = Test()
try {
testLocal.l()
fail("fail $index: no error")
} catch (e: Exception) {
assertEquals(expected, testLocal.status.value, "failed on $index")
}
}
@@ -0,0 +1,15 @@
package test
public trait MCloseable {
public open fun close()
}
public inline fun <T : MCloseable, R> T.muse(block: (T) -> R): R {
try {
return block(this)
} finally {
this.close()
}
}
@@ -0,0 +1,49 @@
import test.*
fun test0(
h: Holder,
throwExternalFinEx1: Boolean = false,
res: String = "Fail"
): String {
try {
val localResult = doCall (
{
h += "OK_NON_LOCAL"
return "OK_NON_LOCAL"
},
{
h += "OK_FINALLY1"
"OK_FINALLY1"
},
{
h += "innerTryBlock"
if (throwExternalFinEx1) {
throw Exception1("EXCEPTION_IN_EXTERNAL_FINALLY")
}
"innerTryBlock"
},
{
h += "CATCHBLOCK"
"CATCHBLOCK"
},
res)
return localResult;
} catch(e: Exception1) {
return e.getMessage()!!
} catch(e: Exception2) {
return e.getMessage()!!
}
}
fun box(): String {
var h = Holder()
var test0 = test0(h, res = "OK")
if (test0 != "OK_NON_LOCAL" || h.value != "OK_NON_LOCAL -> OK_FINALLY1 -> innerTryBlock") return "test0_1: ${test0}, holder: ${h.value}"
h = Holder()
test0 = test0(h, throwExternalFinEx1 = true, res = "OK")
if (test0 != "OK_NON_LOCAL" || h.value != "OK_NON_LOCAL -> OK_FINALLY1 -> innerTryBlock -> CATCHBLOCK") return "test0_2: ${test0}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,36 @@
package test
public class Holder(var value: String = "") {
public fun plusAssign(s: String?) {
if (value.length != 0) {
value += " -> "
}
value += s
}
override fun toString(): String {
return value
}
}
public class Exception1(message: String) : java.lang.RuntimeException(message)
public class Exception2(message: String) : java.lang.RuntimeException(message)
public inline fun doCall(block: ()-> String, finallyBlock: ()-> String,
tryBlock2: ()-> String, catchBlock2: ()-> String, res: String = "Fail") : String {
try {
block()
}
finally {
finallyBlock()
try {
tryBlock2()
} catch (e: Exception) {
catchBlock2()
}
}
return res
}