Updated exception table generation: support new exception table in non-local returns

This commit is contained in:
Michael Bogdanov
2015-06-10 15:38:09 +03:00
parent 93c5a52d13
commit a018e4e12a
40 changed files with 1586 additions and 138 deletions
@@ -0,0 +1,94 @@
import test.*
import Kind.*
enum class Kind {
LOCAL
EXTERNAL
GLOBAL
}
val FINALLY_CHAIN = "in local finally, in doCall finally, in external finally, in doCall finally, in global finally"
class Internal(val value: String)
class External(val value: String)
class Global(val value: String)
fun test1(intKind: Kind, extKind: Kind, holder: Holder): Global {
holder.value = ""
try {
var externalResult = doCall (ext@ {
try {
val internalResult = doCall (int@ {
try {
if (intKind == Kind.GLOBAL) {
return@test1 Global("internal -> global")
}
else if (intKind == EXTERNAL) {
return@ext External("internal -> external")
}
return@int Internal("internal -> local")
}
finally {
holder.value += "in local finally"
}
}, holder)
if (extKind == GLOBAL || extKind == EXTERNAL) {
return Global("external -> global")
}
External(internalResult.value + ": external -> local");
}
finally {
holder.value += ", in external finally"
}
}, holder)
return Global(externalResult.value + ": exit")
}
finally {
holder.value += ", in global finally"
}
}
fun box(): String {
var holder = Holder()
var test1 = test1(LOCAL, LOCAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "internal -> local: external -> local: exit") return "test1: ${test1}, finally = ${holder.value}"
test1 = test1(EXTERNAL, LOCAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "internal -> external: exit") return "test2: ${test1}, finally = ${holder.value}"
test1 = test1(GLOBAL, LOCAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "internal -> global") return "test3: ${test1}, finally = ${holder.value}"
test1 = test1(LOCAL, EXTERNAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "external -> global") return "test4: ${test1}, finally = ${holder.value}"
test1 = test1(EXTERNAL, EXTERNAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "internal -> external: exit") return "test5: ${test1}, finally = ${holder.value}"
test1 = test1(GLOBAL, EXTERNAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "internal -> global") return "test6: ${test1}, finally = ${holder.value}"
test1 = test1(LOCAL, GLOBAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "external -> global") return "test7: ${test1}, finally = ${holder.value}"
test1 = test1(EXTERNAL, GLOBAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "internal -> external: exit") return "test8: ${test1}, finally = ${holder.value}"
test1 = test1(GLOBAL, GLOBAL, holder).value
if (holder.value != FINALLY_CHAIN || test1 != "internal -> global") return "test9: ${test1}, finally = ${holder.value}"
return "OK"
}
@@ -0,0 +1,13 @@
package test
class Holder {
var value: String = ""
}
inline fun <R> doCall(block: ()-> R, h: Holder) : R {
try {
return block()
} finally {
h.value += ", in doCall finally"
}
}
@@ -0,0 +1,69 @@
import test.*
class Holder {
var value: String = ""
}
fun test1(h: Holder, doReturn: Int): String {
doCall (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
{
h.value += ", OF_FINALLY1"
return "OF_FINALLY1"
}
)
return "LOCAL";
}
fun test2(h: Holder, doReturn: Int): String {
doCall (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
{
try {
h.value += ", OF_FINALLY1"
return "OF_FINALLY1"
} finally {
h.value += ", OF_FINALLY1_FINALLY"
}
}
)
return "FAIL";
}
fun box(): String {
var h = Holder()
val test10 = test1(h, 0)
if (test10 != "OF_FINALLY1" || h.value != "OK_NONLOCAL, OF_FINALLY1") return "test10: ${test10}, holder: ${h.value}"
h = Holder()
val test11 = test1(h, 1)
if (test11 != "OF_FINALLY1" || h.value != "LOCAL, OF_FINALLY1") return "test11: ${test11}, holder: ${h.value}"
h = Holder()
val test2 = test2(h, 0)
if (test2 != "OF_FINALLY1" || h.value != "OK_NONLOCAL, OF_FINALLY1, OF_FINALLY1_FINALLY") return "test20: ${test2}, holder: ${h.value}"
h = Holder()
val test21 = test2(h, 1)
if (test21 != "OF_FINALLY1" || h.value != "LOCAL, OF_FINALLY1, OF_FINALLY1_FINALLY") return "test21: ${test21}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,9 @@
package test
public inline fun doCall(block: ()-> Unit, finallyBlock1: ()-> Unit) {
try {
block()
} finally {
finallyBlock1()
}
}
@@ -0,0 +1,53 @@
import test.*
fun test1(h: Holder, doReturn: Int): String {
doCall_1 (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
h
)
return "TEST1";
}
fun test2(h: Holder, doReturn: Int): String {
doCall_2 (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
h
)
return "TEST2";
}
fun box(): String {
var h = Holder()
val test10 = test1(h, 0)
if (test10 != "TEST1" || h.value != "OK_NONLOCAL, OF_FINALLY1, DO_CALL_1_FINALLY") return "test10: ${test10}, holder: ${h.value}"
h = Holder()
val test11 = test1(h, 1)
if (test11 != "TEST1" || h.value != "LOCAL, OF_FINALLY1, DO_CALL_1_FINALLY") return "test11: ${test11}, holder: ${h.value}"
h = Holder()
val test2 = test2(h, 0)
if (test2 != "TEST2" || h.value != "OK_NONLOCAL, OF_FINALLY1, OF_FINALLY1_FINALLY, DO_CALL_1_FINALLY") return "test20: ${test2}, holder: ${h.value}"
h = Holder()
val test21 = test2(h, 1)
if (test21 != "TEST2" || h.value != "LOCAL, OF_FINALLY1, OF_FINALLY1_FINALLY, DO_CALL_1_FINALLY") return "test21: ${test21}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,40 @@
package test
class Holder {
var value: String = ""
}
inline fun doCall_1(block: ()-> Unit, h: Holder) {
try {
doCall(block) {
h.value += ", OF_FINALLY1"
return
}
} finally {
h.value += ", DO_CALL_1_FINALLY"
}
}
inline fun doCall_2(block: ()-> Unit, h: Holder) {
try {
doCall(block) {
try {
h.value += ", OF_FINALLY1"
return
}
finally {
h.value += ", OF_FINALLY1_FINALLY"
}
}
} finally {
h.value += ", DO_CALL_1_FINALLY"
}
}
inline fun doCall(block: ()-> Unit, finallyBlock1: ()-> Unit) {
try {
block()
} finally {
finallyBlock1()
}
}
@@ -0,0 +1,53 @@
import test.*
fun test1(h: Holder, doReturn: Int): String {
doCall_1 (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
h
)
return "TEST1";
}
fun test2(h: Holder, doReturn: Int): String {
doCall_2 (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
h
)
return "TEST2";
}
fun box(): String {
var h = Holder()
val test10 = test1(h, 0)
if (test10 != "OK_NONLOCAL" || h.value != "OK_NONLOCAL, OF_FINALLY1, DO_CALL_1_FINALLY") return "test10: ${test10}, holder: ${h.value}"
h = Holder()
val test11 = test1(h, 1)
if (test11 != "TEST1" || h.value != "LOCAL, OF_FINALLY1, DO_CALL_1_FINALLY") return "test11: ${test11}, holder: ${h.value}"
h = Holder()
val test2 = test2(h, 0)
if (test2 != "OK_NONLOCAL" || h.value != "OK_NONLOCAL, OF_FINALLY1, OF_FINALLY1_FINALLY, DO_CALL_1_FINALLY") return "test20: ${test2}, holder: ${h.value}"
h = Holder()
val test21 = test2(h, 1)
if (test21 != "TEST2" || h.value != "LOCAL, OF_FINALLY1, OF_FINALLY1_FINALLY, DO_CALL_1_FINALLY") return "test21: ${test21}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,38 @@
package test
class Holder {
var value: String = ""
}
inline fun doCall_1(block: ()-> Unit, h: Holder) {
try {
doCall(block) {
h.value += ", OF_FINALLY1"
}
} finally {
h.value += ", DO_CALL_1_FINALLY"
}
}
inline fun doCall_2(block: ()-> Unit, h: Holder) {
try {
doCall(block) {
try {
h.value += ", OF_FINALLY1"
}
finally {
h.value += ", OF_FINALLY1_FINALLY"
}
}
} finally {
h.value += ", DO_CALL_1_FINALLY"
}
}
inline fun doCall(block: ()-> Unit, finallyBlock1: ()-> Unit) {
try {
block()
} finally {
finallyBlock1()
}
}
@@ -0,0 +1,30 @@
import test.*
fun test0(h: Holder, throwException: Boolean): Int {
val localResult = doCall2_2 (
{
h.value += "OK_NONLOCAL"
if (throwException) {
throw java.lang.RuntimeException()
}
return 1
},
"FAIL",
h
)
return -1;
}
fun box(): String {
var h = Holder()
val test0 = test0(h, true)
if (test0 != -1 || h.value != "OK_NONLOCAL, OK_EXCEPTION, OK_FINALLY") return "test0: ${test0}, holder: ${h.value}"
h = Holder()
val test1 = test0(h, false)
if (test1 != 1 || h.value != "OK_NONLOCAL, OK_FINALLY") return "test1: ${test1}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,32 @@
package test
public class Holder {
public var value: String = ""
}
public inline fun <R> doCall2_2(block: () -> R, res: R, h: Holder): R {
return doCall2_1(block, {
h.value += ", OK_EXCEPTION"
"OK_EXCEPTION"
}, res, h)
}
public inline fun <R> doCall2_1(block: () -> R, exception: (e: Exception) -> Unit, res: R, h: Holder): R {
return doCall2<R>(block, exception, {
h.value += ", OK_FINALLY"
"OK_FINALLY"
}, res)
}
public inline fun <R> doCall2(block: () -> R, exception: (e: Exception) -> Unit, finallyBlock: () -> Unit, res: R): R {
try {
return block()
}
catch (e: Exception) {
exception(e)
}
finally {
finallyBlock()
}
return res
}
@@ -0,0 +1,30 @@
import test.*
fun test0(h: Holder, throwException: Boolean): Int {
val localResult = doCall2_2 (
{
h.value += "OK_NONLOCAL"
if (throwException) {
throw java.lang.RuntimeException()
}
return 1
},
"FAIL",
h
)
return -1;
}
fun box(): String {
var h = Holder()
val test0 = test0(h, true)
if (test0 != -1 || h.value != "OK_NONLOCAL, OK_EXCEPTION, OK_FINALLY, DO_CALL_2_FINALLY") return "test0: ${test0}, holder: ${h.value}"
h = Holder()
val test1 = test0(h, false)
if (test1 != 1 || h.value != "OK_NONLOCAL, OK_FINALLY, DO_CALL_2_FINALLY") return "test1: ${test1}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,36 @@
package test
public class Holder {
public var value: String = ""
}
public inline fun <R> doCall2_2(block: () -> R, res: R, h: Holder): R {
return doCall2_1(block, {
h.value += ", OK_EXCEPTION"
"OK_EXCEPTION"
}, res, h)
}
public inline fun <R> doCall2_1(block: () -> R, exception: (e: Exception) -> Unit, res: R, h: Holder): R {
return doCall2<R>(block, exception, {
h.value += ", OK_FINALLY"
"OK_FINALLY"
}, res, h)
}
public inline fun <R> doCall2(block: () -> R, exception: (e: Exception) -> Unit, finallyBlock: () -> Unit, res: R, h: Holder): R {
try {
try {
return block()
}
catch (e: Exception) {
exception(e)
}
finally {
finallyBlock()
}
} finally {
h.value += ", DO_CALL_2_FINALLY"
}
return res
}
@@ -0,0 +1,30 @@
import test.*
fun test0(h: Holder, throwException: Boolean): Int {
val localResult = doCall2_2 (
{
h.value += "OK_NONLOCAL"
if (throwException) {
throw java.lang.RuntimeException()
}
return 1
},
"FAIL",
h
)
return -1;
}
fun box(): String {
var h = Holder()
val test0 = test0(h, true)
if (test0 != -1 || h.value != "OK_NONLOCAL, OK_EXCEPTION, OK_FINALLY, DO_CALL_2_FINALLY, DO_CALL_2_1_FINALLY, DO_CALL_2_2_FINALLY") return "test0: ${test0}, holder: ${h.value}"
h = Holder()
val test1 = test0(h, false)
if (test1 != 1 || h.value != "OK_NONLOCAL, OK_FINALLY, DO_CALL_2_FINALLY, DO_CALL_2_1_FINALLY, DO_CALL_2_2_FINALLY") return "test1: ${test1}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,44 @@
package test
public class Holder {
public var value: String = ""
}
public inline fun <R> doCall2_2(block: () -> R, res: R, h: Holder): R {
try {
return doCall2_1(block, {
h.value += ", OK_EXCEPTION"
"OK_EXCEPTION"
}, res, h)
} finally{
h.value += ", DO_CALL_2_2_FINALLY"
}
}
public inline fun <R> doCall2_1(block: () -> R, exception: (e: Exception) -> Unit, res: R, h: Holder): R {
try {
return doCall2<R>(block, exception, {
h.value += ", OK_FINALLY"
"OK_FINALLY"
}, res, h)
} finally {
h.value += ", DO_CALL_2_1_FINALLY"
}
}
public inline fun <R> doCall2(block: () -> R, exception: (e: Exception) -> Unit, finallyBlock: () -> Unit, res: R, h: Holder): R {
try {
try {
return block()
}
catch (e: Exception) {
exception(e)
}
finally {
finallyBlock()
}
} finally {
h.value += ", DO_CALL_2_FINALLY"
}
return res
}
@@ -0,0 +1,34 @@
import test.*
fun test0(h: Holder, throwException: Boolean): Int {
val localResult = doCall2_2 (
{
h.value += "OK_NONLOCAL"
if (throwException) {
throw java.lang.RuntimeException()
}
return 1
},
"FAIL",
h
)
return -1;
}
fun box(): String {
var h = Holder()
val test0 = test0(h, true)
if (test0 != -1 || h.value != "OK_NONLOCAL, OK_EXCEPTION, OK_FINALLY, DO_CALL_2_FINALLY, DO_CALL_2_1_FINALLY, DO_CALL_2_2_FINALLY")
return "test0: ${test0}, holder: ${h.value}"
h = Holder()
val test1 = test0(h, false)
if (test1 != 1 || h.value != "OK_NONLOCAL, OK_FINALLY, DO_CALL_2_FINALLY, DO_CALL_2_1_FINALLY, DO_CALL_2_2_FINALLY")
return "test1: ${test1}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,44 @@
package test
public class Holder {
public var value: String = ""
}
public inline fun doCall2_2(block: () -> String, res: String, h: Holder): String {
try {
return doCall2_1(block, {
h.value += ", OK_EXCEPTION"
return "OK_EXCEPTION"
}, res, h)
} finally{
h.value += ", DO_CALL_2_2_FINALLY"
}
}
public inline fun <R> doCall2_1(block: () -> R, exception: (e: Exception) -> Unit, res: R, h: Holder): R {
try {
return doCall2<R>(block, exception, {
h.value += ", OK_FINALLY"
"OK_FINALLY"
}, res, h)
} finally {
h.value += ", DO_CALL_2_1_FINALLY"
}
}
public inline fun <R> doCall2(block: () -> R, exception: (e: Exception) -> Unit, finallyBlock: () -> Unit, res: R, h: Holder): R {
try {
try {
return block()
}
catch (e: Exception) {
exception(e)
}
finally {
finallyBlock()
}
} finally {
h.value += ", DO_CALL_2_FINALLY"
}
return res
}
@@ -0,0 +1,34 @@
import test.*
fun test0(h: Holder, throwException: Boolean): Int {
val localResult = doCall2_2 (
{
h.value += "OK_NONLOCAL"
if (throwException) {
throw java.lang.RuntimeException()
}
return 1
},
"FAIL",
h
)
return -1;
}
fun box(): String {
var h = Holder()
val test0 = test0(h, true)
if (test0 != -1 || h.value != "OK_NONLOCAL, OK_EXCEPTION, OK_FINALLY, OK_FINALLY_NESTED, DO_CALL_2_FINALLY, DO_CALL_2_1_FINALLY, DO_CALL_2_2_FINALLY") return "test0: ${test0}, holder: ${h.value}"
h = Holder()
val test1 = test0(h, false)
if (test1 != 1 || h.value != "OK_NONLOCAL, OK_FINALLY, OK_FINALLY_NESTED, DO_CALL_2_FINALLY, DO_CALL_2_1_FINALLY, DO_CALL_2_2_FINALLY") return "test1: ${test1}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,48 @@
package test
public class Holder {
public var value: String = ""
}
public inline fun doCall2_2(block: () -> String, res: String, h: Holder): String {
try {
return doCall2_1(block, {
h.value += ", OK_EXCEPTION"
return "OK_EXCEPTION"
}, res, h)
} finally{
h.value += ", DO_CALL_2_2_FINALLY"
}
}
public inline fun <R> doCall2_1(block: () -> R, exception: (e: Exception) -> Unit, res: R, h: Holder): R {
try {
return doCall2<R>(block, exception, {
try {
h.value += ", OK_FINALLY"
"OK_FINALLY"
} finally {
h.value += ", OK_FINALLY_NESTED"
}
}, res, h)
} finally {
h.value += ", DO_CALL_2_1_FINALLY"
}
}
public inline fun <R> doCall2(block: () -> R, exception: (e: Exception) -> Unit, finallyBlock: () -> Unit, res: R, h: Holder): R {
try {
try {
return block()
}
catch (e: Exception) {
exception(e)
}
finally {
finallyBlock()
}
} finally {
h.value += ", DO_CALL_2_FINALLY"
}
return res
}
@@ -0,0 +1,68 @@
import test.*
val FINALLY_CHAIN = "in local finally, in doCall finally, in external finally, in doCall finally, in global finally"
fun test1(holder: Holder, p: Int): String {
holder.value = "start"
return test2(holder) { i ->
if (p == i) {
return "call $i"
}
}
}
inline fun test2(holder: Holder, l: (s: Int) -> Unit): String {
try {
l(0)
var externalResult = doCall (ext@ {
l(1)
try {
l(2)
val internalResult = doCall (int@ {
l(3)
try {
l(4)
return "fail"
}
finally {
holder.value += ", in local finally"
}
}, holder)
}
finally {
holder.value += ", in external finally"
}
}, holder)
return "fail"
}
finally {
holder.value += ", in global finally"
}
}
fun box(): String {
var holder = Holder()
var test1 = test1(holder, 0)
if (holder.value != "start, in global finally" || test1 != "call 0") return "test1: ${test1}, finally = ${holder.value}"
test1 = test1(holder, 1)
if (holder.value != "start, in doCall finally, in global finally" || test1 != "call 1")
return "test2: ${test1}, finally = ${holder.value}"
test1 = test1(holder, 2)
if (holder.value != "start, in external finally, in doCall finally, in global finally" || test1 != "call 2")
return "test3: ${test1}, finally = ${holder.value}"
test1 = test1(holder, 3)
if (holder.value != "start, in doCall finally, in external finally, in doCall finally, in global finally" || test1 != "call 3")
return "test4: ${test1}, finally = ${holder.value}"
test1 = test1(holder, 4)
if (holder.value != "start, in local finally, in doCall finally, in external finally, in doCall finally, in global finally" || test1 != "call 4")
return "test5: ${test1}, finally = ${holder.value}"
return "OK"
}
@@ -0,0 +1,13 @@
package test
class Holder {
var value: String = ""
}
inline fun <R> doCall(block: ()-> R, h: Holder) : R {
try {
return block()
} finally {
h.value += ", in doCall finally"
}
}
@@ -0,0 +1,127 @@
import test.*
fun test0(h: Holder): Int {
val localResult = doCall2 (
{
h.value += "OK_NONLOCAL"
if (true) {
throw java.lang.RuntimeException()
}
return 1
},
{
h.value += ", OK_EXCEPTION"
return 2
},
{
h.value += ", OK_FINALLY"
"OK_FINALLY"
}, "FAIL", h)
return -1;
}
fun test1(h: Holder): Int {
val localResult = doCall2 (
{
h.value += "OK_NONLOCAL"
return 1
},
{
h.value += ", OK_EXCEPTION"
"OK_EXCEPTION"
},
{
h.value += ", OK_FINALLY"
"OK_FINALLY"
}, "FAIL", h)
return -1;
}
fun test2(h: Holder): String {
val localResult = doCall (
{
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
},
{
h.value += ", OK_EXCEPTION"
2
},
{
h.value += ", OK_FINALLY"
3
}, h)
return "" + localResult;
}
fun test3(h: Holder): String {
val localResult = doCall (
{
h.value += "OK_NONLOCAL"
if (true) {
throw java.lang.RuntimeException()
}
return "OK_NONLOCAL"
},
{
h.value += ", OK_EXCEPTION"
return "OK_EXCEPTION"
},
{
h.value += ", OK_FINALLY"
3
}, h)
return "" + localResult;
}
fun test4(h: Holder): String {
val localResult = doCall (
{
h.value += "OK_NONLOCAL"
if (true) {
throw java.lang.RuntimeException()
}
h.value += "fail"
return "OK_NONLOCAL"
},
{
h.value += ", OK_EXCEPTION"
return "OK_EXCEPTION"
},
{
h.value += ", OK_FINALLY"
return "OK_FINALLY"
}, h)
return "" + localResult;
}
fun box(): String {
var h = Holder()
val test0 = test0(h)
if (test0 != 2 || h.value != "OK_NONLOCAL, OK_EXCEPTION, OK_FINALLY, INLINE_CALL_FINALLY") return "test0: ${test0}, holder: ${h.value}"
h = Holder()
val test1 = test1(h)
if (test1 != 1 || h.value != "OK_NONLOCAL, OK_FINALLY, INLINE_CALL_FINALLY") return "test1: ${test1}, holder: ${h.value}"
h = Holder()
val test2 = test2(h)
if (test2 != "OK_NONLOCAL" || h.value != "OK_NONLOCAL, OK_FINALLY, INLINE_CALL_FINALLY") return "test2: ${test2}, holder: ${h.value}"
h = Holder()
val test3 = test3(h)
if (test3 != "OK_EXCEPTION" || h.value != "OK_NONLOCAL, OK_EXCEPTION, OK_FINALLY, INLINE_CALL_FINALLY") return "test3: ${test3}, holder: ${h.value}"
h = Holder()
val test4 = test4(h)
if (test4 != "OK_FINALLY" || h.value != "OK_NONLOCAL, OK_EXCEPTION, OK_FINALLY, INLINE_CALL_FINALLY") return "test4: ${test4}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,39 @@
package test
public class Holder {
public var value: String = ""
}
public inline fun doCall(block: ()-> Int, exception: (e: Exception)-> Unit, finallyBlock: ()-> Int, h : Holder, res: Int = -111) : Int {
try {
try {
return block()
}
catch (e: Exception) {
exception(e)
}
finally {
finallyBlock()
}
} finally {
h.value += ", INLINE_CALL_FINALLY"
}
return res
}
public inline fun <R> doCall2(block: ()-> R, exception: (e: Exception)-> Unit, finallyBlock: ()-> R, res: R, h : Holder) : R {
try {
try {
return block()
}
catch (e: Exception) {
exception(e)
}
finally {
finallyBlock()
}
} finally {
h.value += ", INLINE_CALL_FINALLY"
}
return res
}
@@ -0,0 +1,75 @@
import test.*
class Holder {
var value: String = ""
}
fun test1(h: Holder, doReturn: Int): String {
doCall (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
{
h.value += ", OK_NONLOCAL2"
return "OK_NONLOCAL2"
},
{
h.value += ", OK_FINALLY"
}
)
return "LOCAL";
}
fun test2(h: Holder, doReturn: Int): String {
doCall (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
{
try {
h.value += ", OK_NONLOCAL2"
return "OK_NONLOCAL2"
} finally {
h.value += ", OK_NONLOCAL2_FINALLY"
}
},
{
h.value += ", OK_FINALLY"
}
)
return "FAIL";
}
fun box(): String {
var h = Holder()
val test10 = test1(h, 0)
if (test10 != "OK_NONLOCAL" || h.value != "OK_NONLOCAL, OK_FINALLY") return "test10: ${test10}, holder: ${h.value}"
h = Holder()
val test11 = test1(h, 1)
if (test11 != "OK_NONLOCAL2" || h.value != "LOCAL, OK_NONLOCAL2, OK_FINALLY") return "test11: ${test11}, holder: ${h.value}"
h = Holder()
val test2 = test2(h, 0)
if (test2 != "OK_NONLOCAL" || h.value != "OK_NONLOCAL, OK_FINALLY") return "test20: ${test2}, holder: ${h.value}"
h = Holder()
val test21 = test2(h, 1)
if (test21 != "OK_NONLOCAL2" || h.value != "LOCAL, OK_NONLOCAL2, OK_NONLOCAL2_FINALLY, OK_FINALLY") return "test21: ${test21}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,10 @@
package test
public inline fun doCall(block: ()-> Unit, block2: ()-> Unit, finallyBlock2: ()-> Unit) {
try {
block()
block2()
} finally {
finallyBlock2()
}
}
@@ -0,0 +1,72 @@
import test.*
fun test1(h: Holder, doReturn: Int): String {
doCall (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
{
h.value += ", OK_NONLOCAL2"
return "OK_NONLOCAL2"
},
{
h.value += ", OK_FINALLY"
},
h
)
return "LOCAL";
}
fun test2(h: Holder, doReturn: Int): String {
doCall (
{
if (doReturn < 1) {
h.value += "OK_NONLOCAL"
return "OK_NONLOCAL"
}
h.value += "LOCAL"
"OK_LOCAL"
},
{
try {
h.value += ", OK_NONLOCAL2"
return "OK_NONLOCAL2"
} finally {
h.value += ", OK_NONLOCAL2_FINALLY"
}
},
{
h.value += ", OK_FINALLY"
},
h
)
return "FAIL";
}
fun box(): String {
var h = Holder()
val test10 = test1(h, 0)
if (test10 != "OK_NONLOCAL" || h.value != "OK_NONLOCAL, OK_FINALLY, DO_CALL_EXT_FINALLY") return "test10: ${test10}, holder: ${h.value}"
h = Holder()
val test11 = test1(h, 1)
if (test11 != "OK_NONLOCAL2" || h.value != "LOCAL, OK_NONLOCAL2, OK_FINALLY, DO_CALL_EXT_FINALLY") return "test11: ${test11}, holder: ${h.value}"
h = Holder()
val test2 = test2(h, 0)
if (test2 != "OK_NONLOCAL" || h.value != "OK_NONLOCAL, OK_FINALLY, DO_CALL_EXT_FINALLY") return "test20: ${test2}, holder: ${h.value}"
h = Holder()
val test21 = test2(h, 1)
if (test21 != "OK_NONLOCAL2" || h.value != "LOCAL, OK_NONLOCAL2, OK_NONLOCAL2_FINALLY, OK_FINALLY, DO_CALL_EXT_FINALLY") return "test21: ${test21}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,19 @@
package test
class Holder {
var value: String = ""
}
inline fun doCall(block: ()-> Unit, block2: ()-> Unit, finallyBlock2: ()-> Unit, res: Holder) {
try {
try {
block()
block2()
}
finally {
finallyBlock2()
}
} finally {
res.value += ", DO_CALL_EXT_FINALLY"
}
}
@@ -0,0 +1,19 @@
import test.*
inline fun <T> bar(arg: String, action: () -> T) {
try {
action()
} finally {
arg.length()
}
}
fun box(): String {
foo() {
bar("") {
return "OK"
}
}
return "fail"
}
@@ -0,0 +1,13 @@
package test
inline fun baz(x: Int) {}
inline fun <T> foo(action: () -> T): T {
baz(0)
try {
return action()
} finally {
baz(1)
}
}
@@ -25,4 +25,4 @@ fun box() : String {
return "fail"
}
// 10 TRYCATCHBLOCK
// 8 TRYCATCHBLOCK
@@ -24,6 +24,5 @@ fun box() : String {
}
return "fail"
}
// maybe we should check test data
// 13 TRYCATCHBLOCK
/* 8 + 1 see notSplitedExceptionTable.kt*/
// 9 TRYCATCHBLOCK