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