refs #22 @35m 2 shorter forms for catch block, fixed catch class instance type checks
This commit is contained in:
parent
6c71f0a2e6
commit
5ed8b2f123
@ -778,7 +778,32 @@ Very much like in Kotlin. Try block returns its body block result, if no excepti
|
||||
assertEquals( "OK", result)
|
||||
>>> void
|
||||
|
||||
It is possible to catch several exceptions in the same block (TBD)
|
||||
There is shorter form of catch block when you want to catch any exception:
|
||||
|
||||
var caught = null
|
||||
try {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
catch(t) { // same as catch(t: Exception), but simpler
|
||||
caught = t
|
||||
}
|
||||
assert( caught is IllegalArgumentException )
|
||||
>>> void
|
||||
|
||||
And even shortest, for the Lying lang tradition, missing var is `it`:
|
||||
|
||||
var caught = null
|
||||
try {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
catch { // same as catch(it: Exception), but simpler
|
||||
caught = it
|
||||
}
|
||||
assert( caught is IllegalArgumentException )
|
||||
>>> void
|
||||
|
||||
It is possible to catch several exceptions in the same block too, use
|
||||
`catch( varName: ExceptionClass1, ExceptionClass2)`, etc.
|
||||
|
||||
|
||||
# Self-assignments in expression
|
||||
|
@ -744,33 +744,49 @@ class Compiler(
|
||||
cc.skipTokens(Token.Type.NEWLINE)
|
||||
var t = cc.next()
|
||||
while( t.value == "catch" ) {
|
||||
ensureLparen(cc)
|
||||
t = cc.next()
|
||||
if( t.type != Token.Type.ID ) throw ScriptError(t.pos, "expected catch variable")
|
||||
val catchVar = t
|
||||
cc.skipTokenOfType(Token.Type.COLON)
|
||||
// load list of exception classes
|
||||
val exClassNames = mutableListOf<String>()
|
||||
do {
|
||||
|
||||
if (cc.skipTokenOfType(Token.Type.LPAREN, isOptional = true)) {
|
||||
t = cc.next()
|
||||
if( t.type != Token.Type.ID )
|
||||
throw ScriptError(t.pos, "expected exception class name")
|
||||
exClassNames += t.value
|
||||
t = cc.next()
|
||||
when(t.type) {
|
||||
Token.Type.COMMA -> {
|
||||
continue
|
||||
}
|
||||
Token.Type.RPAREN -> {
|
||||
break
|
||||
}
|
||||
else -> throw ScriptError(t.pos, "syntax error: expected ',' or ')'")
|
||||
if (t.type != Token.Type.ID) throw ScriptError(t.pos, "expected catch variable")
|
||||
val catchVar = t
|
||||
|
||||
val exClassNames = mutableListOf<String>()
|
||||
if (cc.skipTokenOfType(Token.Type.COLON, isOptional = true)) {
|
||||
// load list of exception classes
|
||||
do {
|
||||
t = cc.next()
|
||||
if (t.type != Token.Type.ID)
|
||||
throw ScriptError(t.pos, "expected exception class name")
|
||||
exClassNames += t.value
|
||||
t = cc.next()
|
||||
when (t.type) {
|
||||
Token.Type.COMMA -> {
|
||||
continue
|
||||
}
|
||||
|
||||
Token.Type.RPAREN -> {
|
||||
break
|
||||
}
|
||||
|
||||
else -> throw ScriptError(t.pos, "syntax error: expected ',' or ')'")
|
||||
}
|
||||
} while (true)
|
||||
} else {
|
||||
// no type!
|
||||
exClassNames += "Exception"
|
||||
cc.skipTokenOfType(Token.Type.RPAREN)
|
||||
}
|
||||
} while(true)
|
||||
val block = parseBlock(cc)
|
||||
catches += CatchBlockData(catchVar, exClassNames, block)
|
||||
cc.skipTokens(Token.Type.NEWLINE)
|
||||
t = cc.next()
|
||||
val block = parseBlock(cc)
|
||||
catches += CatchBlockData(catchVar, exClassNames, block)
|
||||
cc.skipTokens(Token.Type.NEWLINE)
|
||||
t = cc.next()
|
||||
} else {
|
||||
// no (e: Exception) block: should be shortest variant `catch { ... }`
|
||||
cc.skipTokenOfType(Token.Type.LBRACE, "expected catch(...) or catch { ... } here")
|
||||
catches += CatchBlockData(Token("it", cc.currentPos(), Token.Type.ID), listOf("Exception"),
|
||||
parseBlock(cc,true))
|
||||
t = cc.next()
|
||||
}
|
||||
}
|
||||
if( catches.isEmpty() )
|
||||
throw ScriptError(cc.currentPos(), "try block must have at least one catch clause")
|
||||
@ -802,7 +818,7 @@ class Compiler(
|
||||
?: raiseSymbolNotFound("error clas not exists: $exceptionClassName")
|
||||
println("exObj: $exObj")
|
||||
println("objException: ${objException.objClass}")
|
||||
if( objException.objClass == exObj )
|
||||
if( objException.isInstanceOf(exObj) )
|
||||
exceptionObject = objException
|
||||
break
|
||||
}
|
||||
|
@ -1753,12 +1753,7 @@ class ScriptTest {
|
||||
fun testThrowExisting()= runTest {
|
||||
eval("""
|
||||
val x = IllegalArgumentException("test")
|
||||
println("instance class",x::class)
|
||||
println("instance", x)
|
||||
println("Exception object",Exception)
|
||||
println("... and it's class",Exception::class)
|
||||
assert( x is Exception )
|
||||
println(x)
|
||||
|
||||
var t = 0
|
||||
var finallyCaught = false
|
||||
@ -1780,4 +1775,42 @@ class ScriptTest {
|
||||
assert(finallyCaught)
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCatchShort1()= runTest {
|
||||
eval("""
|
||||
val x = IllegalArgumentException("test")
|
||||
var t = 0
|
||||
var finallyCaught = false
|
||||
try {
|
||||
t = 1
|
||||
throw x
|
||||
t = 2
|
||||
}
|
||||
catch(e) {
|
||||
t = 31
|
||||
}
|
||||
finally {
|
||||
finallyCaught = true
|
||||
}
|
||||
assertEquals(31, t)
|
||||
assert(finallyCaught)
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCatchShort2()= runTest {
|
||||
eval("""
|
||||
val x = IllegalArgumentException("test")
|
||||
var caught = null
|
||||
try {
|
||||
throw x
|
||||
}
|
||||
catch {
|
||||
caught = it
|
||||
}
|
||||
assert( caught is IllegalArgumentException )
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user