Updated exception table generation: support new exception table in non-local returns
This commit is contained in:
Vendored
+94
@@ -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"
|
||||
}
|
||||
Vendored
+13
@@ -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"
|
||||
}
|
||||
}
|
||||
Vendored
+69
@@ -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"
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
public inline fun doCall(block: ()-> Unit, finallyBlock1: ()-> Unit) {
|
||||
try {
|
||||
block()
|
||||
} finally {
|
||||
finallyBlock1()
|
||||
}
|
||||
}
|
||||
Vendored
+53
@@ -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"
|
||||
}
|
||||
Vendored
+40
@@ -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()
|
||||
}
|
||||
}
|
||||
Vendored
+53
@@ -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"
|
||||
}
|
||||
Vendored
+38
@@ -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()
|
||||
}
|
||||
}
|
||||
+30
@@ -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"
|
||||
}
|
||||
+32
@@ -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
|
||||
}
|
||||
Vendored
+30
@@ -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"
|
||||
}
|
||||
Vendored
+36
@@ -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
|
||||
}
|
||||
Vendored
+30
@@ -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"
|
||||
}
|
||||
Vendored
+44
@@ -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
|
||||
}
|
||||
Vendored
+34
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
Vendored
+44
@@ -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
|
||||
}
|
||||
Vendored
+34
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
Vendored
+48
@@ -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
|
||||
}
|
||||
+68
@@ -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"
|
||||
}
|
||||
+13
@@ -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"
|
||||
}
|
||||
}
|
||||
Vendored
+127
@@ -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"
|
||||
}
|
||||
Vendored
+39
@@ -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
|
||||
}
|
||||
+75
@@ -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"
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
public inline fun doCall(block: ()-> Unit, block2: ()-> Unit, finallyBlock2: ()-> Unit) {
|
||||
try {
|
||||
block()
|
||||
block2()
|
||||
} finally {
|
||||
finallyBlock2()
|
||||
}
|
||||
}
|
||||
Vendored
+72
@@ -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"
|
||||
}
|
||||
Vendored
+19
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user