Rewrite exceptions handler in ir interpreter
For now there are 2 types of exceptions: 1. UserExceptions - express user and jvm like exceptions 2. InterpreterError - thrown only if something is wrong with interpreter
This commit is contained in:
committed by
TeamCityServer
parent
c3b0c9c6b2
commit
f3d7dc5f22
+33
-35
@@ -14,9 +14,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||||
import org.jetbrains.kotlin.ir.interpreter.builtins.*
|
import org.jetbrains.kotlin.ir.interpreter.builtins.*
|
||||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterException
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.*
|
||||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundException
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterTimeOutException
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.intrinsics.IntrinsicEvaluator
|
import org.jetbrains.kotlin.ir.interpreter.intrinsics.IntrinsicEvaluator
|
||||||
import org.jetbrains.kotlin.ir.interpreter.stack.StackImpl
|
import org.jetbrains.kotlin.ir.interpreter.stack.StackImpl
|
||||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||||
@@ -70,7 +68,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
|
|
||||||
private fun incrementAndCheckCommands() {
|
private fun incrementAndCheckCommands() {
|
||||||
commandCount++
|
commandCount++
|
||||||
if (commandCount >= MAX_COMMANDS) throw InterpreterTimeOutException()
|
if (commandCount >= MAX_COMMANDS) throw InterpreterTimeOutError()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun interpret(expression: IrExpression): IrExpression {
|
fun interpret(expression: IrExpression): IrExpression {
|
||||||
@@ -133,13 +131,11 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
}
|
}
|
||||||
|
|
||||||
return executionResult.getNextLabel(this) { this@getNextLabel.interpret() }
|
return executionResult.getNextLabel(this) { this@getNextLabel.interpret() }
|
||||||
} catch (e: InterpreterException) {
|
} catch (e: UserException) {
|
||||||
throw e
|
// can handle only user exceptions, all others must be rethrown
|
||||||
} catch (e: Throwable) {
|
val exceptionName = e.exception::class.java.simpleName
|
||||||
// catch exception from JVM such as: ArithmeticException, StackOverflowError and others
|
|
||||||
val exceptionName = e::class.java.simpleName
|
|
||||||
val irExceptionClass = irExceptions.firstOrNull { it.name.asString() == exceptionName } ?: irBuiltIns.throwableClass.owner
|
val irExceptionClass = irExceptions.firstOrNull { it.name.asString() == exceptionName } ?: irBuiltIns.throwableClass.owner
|
||||||
stack.pushReturnValue(ExceptionState(e, irExceptionClass, stack.getStackTrace()))
|
stack.pushReturnValue(ExceptionState(e.exception, irExceptionClass, stack.getStackTrace()))
|
||||||
return Exception
|
return Exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,12 +145,12 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
if (irFunction.fileOrNull != null) stack.setCurrentFrameName(irFunction)
|
if (irFunction.fileOrNull != null) stack.setCurrentFrameName(irFunction)
|
||||||
|
|
||||||
if (irFunction.body is IrSyntheticBody) return handleIntrinsicMethods(irFunction)
|
if (irFunction.body is IrSyntheticBody) return handleIntrinsicMethods(irFunction)
|
||||||
return irFunction.body?.interpret() ?: throw InterpreterException("Ir function must be with body")
|
return irFunction.body?.interpret() ?: throw InterpreterError("Ir function must be with body")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MethodHandle?.invokeMethod(irFunction: IrFunction): ExecutionResult {
|
private fun MethodHandle?.invokeMethod(irFunction: IrFunction): ExecutionResult {
|
||||||
this ?: return handleIntrinsicMethods(irFunction)
|
this ?: return handleIntrinsicMethods(irFunction)
|
||||||
val result = this.invokeWithArguments(irFunction.getArgsForMethodInvocation(stack.getAll()))
|
val result = withExceptionHandler { this.invokeWithArguments(irFunction.getArgsForMethodInvocation(stack.getAll())) }
|
||||||
stack.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
stack.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
|
|
||||||
return Next
|
return Next
|
||||||
@@ -197,26 +193,28 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
val signature = CompileTimeFunction(methodName, argsType.map { it.getOnlyName() })
|
val signature = CompileTimeFunction(methodName, argsType.map { it.getOnlyName() })
|
||||||
|
|
||||||
// TODO replace unary, binary, ternary functions with vararg
|
// TODO replace unary, binary, ternary functions with vararg
|
||||||
val result = when (argsType.size) {
|
val result = withExceptionHandler {
|
||||||
1 -> {
|
when (argsType.size) {
|
||||||
val function = unaryFunctions[signature]
|
1 -> {
|
||||||
?: throw InterpreterMethodNotFoundException("For given function $signature there is no entry in unary map")
|
val function = unaryFunctions[signature]
|
||||||
function.invoke(argsValues.first())
|
?: throw InterpreterMethodNotFoundError("For given function $signature there is no entry in unary map")
|
||||||
}
|
function.invoke(argsValues.first())
|
||||||
2 -> {
|
|
||||||
val function = binaryFunctions[signature]
|
|
||||||
?: throw InterpreterMethodNotFoundException("For given function $signature there is no entry in binary map")
|
|
||||||
when (methodName) {
|
|
||||||
"rangeTo" -> return calculateRangeTo(irFunction.returnType)
|
|
||||||
else -> function.invoke(argsValues[0], argsValues[1])
|
|
||||||
}
|
}
|
||||||
|
2 -> {
|
||||||
|
val function = binaryFunctions[signature]
|
||||||
|
?: throw InterpreterMethodNotFoundError("For given function $signature there is no entry in binary map")
|
||||||
|
when (methodName) {
|
||||||
|
"rangeTo" -> return calculateRangeTo(irFunction.returnType)
|
||||||
|
else -> function.invoke(argsValues[0], argsValues[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
val function = ternaryFunctions[signature]
|
||||||
|
?: throw InterpreterMethodNotFoundError("For given function $signature there is no entry in ternary map")
|
||||||
|
function.invoke(argsValues[0], argsValues[1], argsValues[2])
|
||||||
|
}
|
||||||
|
else -> throw InterpreterError("Unsupported number of arguments for invocation as builtin functions")
|
||||||
}
|
}
|
||||||
3 -> {
|
|
||||||
val function = ternaryFunctions[signature]
|
|
||||||
?: throw InterpreterMethodNotFoundException("For given function $signature there is no entry in ternary map")
|
|
||||||
function.invoke(argsValues[0], argsValues[1], argsValues[2])
|
|
||||||
}
|
|
||||||
else -> throw InterpreterException("Unsupported number of arguments")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
stack.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
@@ -259,7 +257,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
stack.peekReturnValue().checkNullability(valueParametersSymbols[i].owner.type) {
|
stack.peekReturnValue().checkNullability(valueParametersSymbols[i].owner.type) {
|
||||||
val method = irFunction.getCapitalizedFileName() + "." + irFunction.fqNameWhenAvailable
|
val method = irFunction.getCapitalizedFileName() + "." + irFunction.fqNameWhenAvailable
|
||||||
val parameter = valueParametersSymbols[i].owner.name
|
val parameter = valueParametersSymbols[i].owner.name
|
||||||
throw IllegalArgumentException("Parameter specified as non-null is null: method $method, parameter $parameter")
|
IllegalArgumentException("Parameter specified as non-null is null: method $method, parameter $parameter").throwAsUserException()
|
||||||
}
|
}
|
||||||
|
|
||||||
with(Variable(valueParametersSymbols[i], stack.popReturnValue())) {
|
with(Variable(valueParametersSymbols[i], stack.popReturnValue())) {
|
||||||
@@ -637,7 +635,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
|
|
||||||
val executionResult = enumEntry.initializerExpression?.interpret()?.check { return it }
|
val executionResult = enumEntry.initializerExpression?.interpret()?.check { return it }
|
||||||
enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null
|
enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null
|
||||||
return executionResult ?: throw InterpreterException("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
|
return executionResult ?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult {
|
private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult {
|
||||||
@@ -653,7 +651,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST -> {
|
IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST -> {
|
||||||
if (!isErased && !stack.peekReturnValue().isSubtypeOf(typeOperand)) {
|
if (!isErased && !stack.peekReturnValue().isSubtypeOf(typeOperand)) {
|
||||||
val convertibleClassName = stack.popReturnValue().irClass.fqNameWhenAvailable
|
val convertibleClassName = stack.popReturnValue().irClass.fqNameWhenAvailable
|
||||||
throw ClassCastException("$convertibleClassName cannot be cast to ${typeOperand.render()}")
|
ClassCastException("$convertibleClassName cannot be cast to ${typeOperand.render()}").throwAsUserException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IrTypeOperator.SAFE_CAST -> {
|
IrTypeOperator.SAFE_CAST -> {
|
||||||
@@ -750,7 +748,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
is Common -> stack.pushReturnValue(ExceptionState(exception, stack.getStackTrace()))
|
is Common -> stack.pushReturnValue(ExceptionState(exception, stack.getStackTrace()))
|
||||||
is Wrapper -> stack.pushReturnValue(ExceptionState(exception, stack.getStackTrace()))
|
is Wrapper -> stack.pushReturnValue(ExceptionState(exception, stack.getStackTrace()))
|
||||||
is ExceptionState -> stack.pushReturnValue(exception)
|
is ExceptionState -> stack.pushReturnValue(exception)
|
||||||
else -> throw InterpreterException("${exception::class} cannot be used as exception state")
|
else -> throw InterpreterError("${exception::class} cannot be used as exception state")
|
||||||
}
|
}
|
||||||
return Exception
|
return Exception
|
||||||
}
|
}
|
||||||
@@ -778,7 +776,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Lambda -> state.toString()
|
is Lambda -> state.toString()
|
||||||
else -> throw InterpreterException("${state::class.java} cannot be used in StringConcatenation expression")
|
else -> throw InterpreterError("${state::class.java} cannot be used in StringConcatenation expression")
|
||||||
}
|
}
|
||||||
stack.pushReturnValue(result.toState(irBuiltIns.stringType))
|
stack.pushReturnValue(result.toState(irBuiltIns.stringType))
|
||||||
return Next
|
return Next
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
|
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrWhen
|
import org.jetbrains.kotlin.ir.expressions.IrWhen
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrWhileLoop
|
import org.jetbrains.kotlin.ir.expressions.IrWhileLoop
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||||
@@ -72,7 +73,7 @@ internal fun ExecutionResult.implicitCastIfNeeded(expectedType: IrType, actualTy
|
|||||||
|
|
||||||
if (!actualState.isSubtypeOf(expectedType)) {
|
if (!actualState.isSubtypeOf(expectedType)) {
|
||||||
val convertibleClassName = stack.popReturnValue().irClass.fqNameWhenAvailable
|
val convertibleClassName = stack.popReturnValue().irClass.fqNameWhenAvailable
|
||||||
throw ClassCastException("$convertibleClassName cannot be cast to ${expectedType.render()}")
|
ClassCastException("$convertibleClassName cannot be cast to ${expectedType.render()}").throwAsUserException()
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,10 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.interpreter.builtins.evaluateIntrinsicAnnotation
|
import org.jetbrains.kotlin.ir.interpreter.builtins.evaluateIntrinsicAnnotation
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException
|
||||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -240,3 +238,11 @@ fun IrClass.internalName(): String {
|
|||||||
}
|
}
|
||||||
return internalName.toString()
|
return internalName.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun withExceptionHandler(block: () -> Any?): Any? {
|
||||||
|
try {
|
||||||
|
return block()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
e.throwAsUserException()
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.interpreter.exceptions
|
||||||
|
|
||||||
|
open class InterpreterError(override val message: String) : InterpreterException()
|
||||||
|
|
||||||
|
class InterpreterMethodNotFoundError(override val message: String) : InterpreterError(message)
|
||||||
|
|
||||||
|
class InterpreterTimeOutError : InterpreterError("Exceeded execution limit of constexpr expression")
|
||||||
|
|
||||||
|
class InterpreterEmptyReturnStackError : InterpreterError("Return values stack is empty")
|
||||||
+1
-2
@@ -5,5 +5,4 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.exceptions
|
package org.jetbrains.kotlin.ir.interpreter.exceptions
|
||||||
|
|
||||||
open class InterpreterException(override val message: String) : Exception(message) {
|
abstract class InterpreterException : Exception()
|
||||||
}
|
|
||||||
-9
@@ -1,9 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.exceptions
|
|
||||||
|
|
||||||
class InterpreterMethodNotFoundException(override val message: String) : InterpreterException(message) {
|
|
||||||
}
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.exceptions
|
|
||||||
|
|
||||||
class InterpreterTimeOutException : InterpreterException("Exceeded execution limit of constexpr expression") {
|
|
||||||
|
|
||||||
}
|
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.interpreter.exceptions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class used to wrap 2 types of exceptions:
|
||||||
|
* 1. exceptions from JVM such as: ArithmeticException, StackOverflowError and others
|
||||||
|
* 2. exceptions defined by user
|
||||||
|
*/
|
||||||
|
class UserException(val exception: Throwable) : InterpreterException() {
|
||||||
|
override fun fillInStackTrace(): Throwable = this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Throwable.throwAsUserException(): Nothing {
|
||||||
|
throw UserException(this)
|
||||||
|
}
|
||||||
+2
-2
@@ -6,7 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.ir.interpreter.intrinsics
|
package org.jetbrains.kotlin.ir.interpreter.intrinsics
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.ExecutionResult
|
import org.jetbrains.kotlin.ir.interpreter.ExecutionResult
|
||||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundException
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundError
|
||||||
import org.jetbrains.kotlin.ir.interpreter.stack.Stack
|
import org.jetbrains.kotlin.ir.interpreter.stack.Stack
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
@@ -23,7 +23,7 @@ internal class IntrinsicEvaluator {
|
|||||||
EnumHashCode.equalTo(irFunction) -> EnumHashCode.evaluate(irFunction, stack, interpret)
|
EnumHashCode.equalTo(irFunction) -> EnumHashCode.evaluate(irFunction, stack, interpret)
|
||||||
JsPrimitives.equalTo(irFunction) -> JsPrimitives.evaluate(irFunction, stack, interpret)
|
JsPrimitives.equalTo(irFunction) -> JsPrimitives.evaluate(irFunction, stack, interpret)
|
||||||
ArrayConstructor.equalTo(irFunction) -> ArrayConstructor.evaluate(irFunction, stack, interpret)
|
ArrayConstructor.equalTo(irFunction) -> ArrayConstructor.evaluate(irFunction, stack, interpret)
|
||||||
else -> throw InterpreterMethodNotFoundException("Method ${irFunction.name} hasn't implemented")
|
else -> throw InterpreterMethodNotFoundError("Method ${irFunction.name} hasn't implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-1
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.IrElement
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ internal object EnumValueOf : IntrinsicBase() {
|
|||||||
val enumEntryName = stack.getVariable(irFunction.valueParameters.first().symbol).state.asString()
|
val enumEntryName = stack.getVariable(irFunction.valueParameters.first().symbol).state.asString()
|
||||||
val enumEntry = enumClass.declarations.filterIsInstance<IrEnumEntry>().singleOrNull { it.name.asString() == enumEntryName }
|
val enumEntry = enumClass.declarations.filterIsInstance<IrEnumEntry>().singleOrNull { it.name.asString() == enumEntryName }
|
||||||
enumEntry?.interpret()?.check { return it }
|
enumEntry?.interpret()?.check { return it }
|
||||||
?: throw IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName")
|
?: IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName").throwAsUserException()
|
||||||
|
|
||||||
return Next
|
return Next
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.stack
|
package org.jetbrains.kotlin.ir.interpreter.stack
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterEmptyReturnStackError
|
||||||
import org.jetbrains.kotlin.ir.interpreter.state.State
|
import org.jetbrains.kotlin.ir.interpreter.state.State
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
@@ -65,7 +66,7 @@ internal class InterpreterFrame(
|
|||||||
if (returnStack.isNotEmpty()) {
|
if (returnStack.isNotEmpty()) {
|
||||||
return returnStack.last()
|
return returnStack.last()
|
||||||
}
|
}
|
||||||
throw NoSuchElementException("Return values stack is empty")
|
throw InterpreterEmptyReturnStackError()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popReturnValue(): State {
|
override fun popReturnValue(): State {
|
||||||
@@ -74,6 +75,6 @@ internal class InterpreterFrame(
|
|||||||
returnStack.removeAt(returnStack.size - 1)
|
returnStack.removeAt(returnStack.size - 1)
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
throw NoSuchElementException("Return values stack is empty")
|
throw InterpreterEmptyReturnStackError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
package org.jetbrains.kotlin.ir.interpreter.stack
|
package org.jetbrains.kotlin.ir.interpreter.stack
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.ExecutionResult
|
import org.jetbrains.kotlin.ir.interpreter.ExecutionResult
|
||||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterException
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.getCapitalizedFileName
|
import org.jetbrains.kotlin.ir.interpreter.getCapitalizedFileName
|
||||||
import org.jetbrains.kotlin.ir.interpreter.state.State
|
import org.jetbrains.kotlin.ir.interpreter.state.State
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.name
|
import org.jetbrains.kotlin.ir.declarations.name
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.file
|
import org.jetbrains.kotlin.ir.util.file
|
||||||
@@ -132,7 +132,7 @@ private class FrameContainer(current: Frame = InterpreterFrame()) {
|
|||||||
fun getAll() = innerStack.flatMap { it.getAll() }
|
fun getAll() = innerStack.flatMap { it.getAll() }
|
||||||
fun getVariable(symbol: IrSymbol): Variable {
|
fun getVariable(symbol: IrSymbol): Variable {
|
||||||
return innerStack.firstNotNullOfOrNull { it.getVariable(symbol) }
|
return innerStack.firstNotNullOfOrNull { it.getVariable(symbol) }
|
||||||
?: throw InterpreterException("$symbol not found") // TODO better message
|
?: throw InterpreterError("$symbol not found") // TODO better message
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contains(symbol: IrSymbol) = innerStack.any { it.contains(symbol) }
|
fun contains(symbol: IrSymbol) = innerStack.any { it.contains(symbol) }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
@@ -60,7 +61,9 @@ internal fun State.isSubtypeOf(other: IrType): Boolean {
|
|||||||
/**
|
/**
|
||||||
* This method used to check if for not null parameter there was passed null argument.
|
* This method used to check if for not null parameter there was passed null argument.
|
||||||
*/
|
*/
|
||||||
internal fun State.checkNullability(irType: IrType?, throwException: () -> Nothing = { throw NullPointerException() }): State {
|
internal fun State.checkNullability(
|
||||||
|
irType: IrType?, throwException: () -> Nothing = { NullPointerException().throwAsUserException() }
|
||||||
|
): State {
|
||||||
if (irType !is IrSimpleType) return this
|
if (irType !is IrSimpleType) return this
|
||||||
if (this.isNull() && !irType.isNullable()) {
|
if (this.isNull() && !irType.isNullable()) {
|
||||||
throwException()
|
throwException()
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex(
|
|||||||
|
|
||||||
fun getCompanionObject(irClass: IrClass): Wrapper {
|
fun getCompanionObject(irClass: IrClass): Wrapper {
|
||||||
val objectName = irClass.getEvaluateIntrinsicValue()!!
|
val objectName = irClass.getEvaluateIntrinsicValue()!!
|
||||||
val objectValue = companionObjectValue[objectName] ?: throw AssertionError("Companion object $objectName cannot be interpreted")
|
val objectValue = companionObjectValue[objectName] ?: throw InternalError("Companion object $objectName cannot be interpreted")
|
||||||
return Wrapper(objectValue, irClass)
|
return Wrapper(objectValue, irClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user