Fixes for call site finally generation before non-local returns

This commit is contained in:
Michael Bogdanov
2014-10-28 14:16:47 +03:00
parent dd8c3f0e49
commit d0f6f03380
12 changed files with 625 additions and 233 deletions
@@ -0,0 +1,101 @@
import test.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
fun test1(): Holder {
val h = Holder("")
try {
val internalResult = doCall(h) {
h += "in lambda body"
return h
}
}
finally {
h += "in call site finally"
}
h += "local"
return h
}
fun test1Lambda(): Holder {
val h = Holder("")
val internalResult = doCall(h) {
try {
h += "in lambda body"
return h
}
finally {
h += "in lambda finally"
}
}
h += "local"
return h
}
fun test2(h: Holder): Holder {
try {
val internalResult = doCallWithException(h) {
h += "in lambda body"
return h
}
}
finally {
h += "in call site finally"
}
h += "local"
return h
}
fun test2Lambda(h: Holder): Holder {
val internalResult = doCallWithException(h) {
try {
h += "in lambda body"
return h
}
finally {
h += "in lambda finally"
}
}
h += "local"
return h
}
fun box(): String {
val test = test1()
if (test.value != "in lambda body -> inline fun finally -> in call site finally") return "fail 1: $test"
val testLambda = test1Lambda()
if (testLambda.value != "in lambda body -> in lambda finally -> inline fun finally") return "fail 1 lambda: $testLambda"
var h = Holder()
assertError(2, h, "in lambda body -> inline fun finally -> in call site finally") {
test2(h)
}
h = Holder()
assertError(22, h, "in lambda body -> in lambda finally -> inline fun finally") {
test2Lambda(h)
}
return "OK"
}
public fun assertError(index: Int, h: Holder, expected: String, l: (h: Holder) -> Holder) {
try {
l(h)
fail("fail $index: no error")
}
catch (e: Exception) {
assertEquals(expected, h.value, "failed on $index")
}
}
@@ -0,0 +1,33 @@
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 inline fun <R> doCall(h: Holder, block: ()-> R) : R {
try {
return block()
} finally {
h += "inline fun finally"
}
}
public inline fun <R> doCallWithException(h: Holder, block: ()-> R) : R {
try {
return block()
} finally {
h += "inline fun finally"
throw RuntimeException("fail");
}
}
@@ -0,0 +1,101 @@
import test.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
fun test1(): Holder {
val h = Holder("")
try {
doCall(h) {
h += "in lambda body"
return h
}
}
finally {
h += "in call site finally"
}
h += "local"
return h
}
fun test1Lambda(): Holder {
val h = Holder("")
doCall(h) {
try {
h += "in lambda body"
return h
}
finally {
h += "in lambda finally"
}
}
h += "local"
return h
}
fun test2(h: Holder): Holder {
try {
doCallWithException(h) {
h += "in lambda body"
return h
}
}
finally {
h += "in call site finally"
}
h += "local"
return h
}
fun test2Lambda(h: Holder): Holder {
doCallWithException(h) {
try {
h += "in lambda body"
return h
}
finally {
h += "in lambda finally"
}
}
h += "local"
return h
}
fun box(): String {
val test = test1()
if (test.value != "in lambda body -> inline fun finally -> in call site finally") return "fail 1: $test"
val testLambda = test1Lambda()
if (testLambda.value != "in lambda body -> in lambda finally -> inline fun finally") return "fail 1 lambda: $testLambda"
var h = Holder()
assertError(2, h, "in lambda body -> inline fun finally -> in call site finally") {
test2(h)
}
h = Holder()
assertError(22, h, "in lambda body -> in lambda finally -> inline fun finally") {
test2Lambda(h)
}
return "OK"
}
public fun assertError(index: Int, h: Holder, expected: String, l: (h: Holder) -> Holder) {
try {
l(h)
fail("fail $index: no error")
}
catch (e: Exception) {
assertEquals(expected, h.value, "failed on $index")
}
}
@@ -0,0 +1,33 @@
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 inline fun <R> doCall(h: Holder, block: ()-> R) {
try {
block()
} finally {
h += "inline fun finally"
}
}
public inline fun <R> doCallWithException(h: Holder, block: ()-> R) {
try {
block()
} finally {
h += "inline fun finally"
throw RuntimeException("fail");
}
}