Add callback to methods of CallInterceptor to specify default behaviour
This commit is contained in:
committed by
TeamCityServer
parent
285929ad07
commit
0e8ca12499
+20
-22
@@ -37,10 +37,10 @@ internal interface CallInterceptor {
|
||||
val interpreter: IrInterpreter
|
||||
|
||||
fun interceptProxy(irFunction: IrFunction, valueArguments: List<Variable>, expectedResultClass: Class<*> = Any::class.java): Any?
|
||||
fun interceptCall(call: IrCall, irFunction: IrFunction, receiver: State?, args: List<State>)
|
||||
fun interceptConstructor(constructorCall: IrFunctionAccessExpression, receiver: State, args: List<State>)
|
||||
fun interceptGetObjectValue(expression: IrGetObjectValue)
|
||||
fun interceptEnumEntry(enumEntry: IrEnumEntry)
|
||||
fun interceptCall(call: IrCall, irFunction: IrFunction, receiver: State?, args: List<State>, defaultAction: () -> Unit)
|
||||
fun interceptConstructor(constructorCall: IrFunctionAccessExpression, receiver: State, args: List<State>, defaultAction: () -> Unit)
|
||||
fun interceptGetObjectValue(expression: IrGetObjectValue, defaultAction: () -> Unit)
|
||||
fun interceptEnumEntry(enumEntry: IrEnumEntry, defaultAction: () -> Unit)
|
||||
fun interceptJavaStaticField(expression: IrGetField)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
}.wrap(this@DefaultCallInterceptor, expectedResultClass)
|
||||
}
|
||||
|
||||
override fun interceptCall(call: IrCall, irFunction: IrFunction, receiver: State?, args: List<State>) {
|
||||
override fun interceptCall(call: IrCall, irFunction: IrFunction, receiver: State?, args: List<State>, defaultAction: () -> Unit) {
|
||||
val isInlineOnly = irFunction.hasAnnotation(FqName("kotlin.internal.InlineOnly"))
|
||||
val originalCallName = call.symbol.owner.name.asString()
|
||||
when {
|
||||
@@ -69,11 +69,13 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
irFunction.body is IrSyntheticBody -> handleIntrinsicMethods(irFunction)
|
||||
irFunction.body == null ->
|
||||
irFunction.trySubstituteFunctionBody() ?: irFunction.tryCalculateLazyConst() ?: calculateBuiltIns(irFunction, args)
|
||||
else -> callStack.addInstruction(CompoundInstruction(irFunction))
|
||||
else -> defaultAction()
|
||||
}
|
||||
}
|
||||
|
||||
override fun interceptConstructor(constructorCall: IrFunctionAccessExpression, receiver: State, args: List<State>) {
|
||||
override fun interceptConstructor(
|
||||
constructorCall: IrFunctionAccessExpression, receiver: State, args: List<State>, defaultAction: () -> Unit
|
||||
) {
|
||||
val constructor = constructorCall.symbol.owner
|
||||
val irClass = constructor.parentAsClass
|
||||
when {
|
||||
@@ -90,23 +92,23 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
val propertySymbol = irClass.declarations.single { it is IrProperty }.symbol
|
||||
callStack.pushState(receiver.apply { fields += Variable(propertySymbol, args.single()) })
|
||||
}
|
||||
else -> {
|
||||
callStack.pushState(receiver)
|
||||
callStack.addInstruction(CompoundInstruction(constructor))
|
||||
}
|
||||
else -> defaultAction()
|
||||
}
|
||||
}
|
||||
|
||||
override fun interceptGetObjectValue(expression: IrGetObjectValue) {
|
||||
override fun interceptGetObjectValue(expression: IrGetObjectValue, defaultAction: () -> Unit) {
|
||||
val objectClass = expression.symbol.owner
|
||||
if (objectClass.hasAnnotation(evaluateIntrinsicAnnotation)) {
|
||||
val result = Wrapper.getCompanionObject(objectClass)
|
||||
environment.mapOfObjects[expression.symbol] = result
|
||||
callStack.pushState(result)
|
||||
when {
|
||||
objectClass.hasAnnotation(evaluateIntrinsicAnnotation) -> {
|
||||
val result = Wrapper.getCompanionObject(objectClass)
|
||||
environment.mapOfObjects[expression.symbol] = result
|
||||
callStack.pushState(result)
|
||||
}
|
||||
else -> defaultAction()
|
||||
}
|
||||
}
|
||||
|
||||
override fun interceptEnumEntry(enumEntry: IrEnumEntry) {
|
||||
override fun interceptEnumEntry(enumEntry: IrEnumEntry, defaultAction: () -> Unit) {
|
||||
val enumClass = enumEntry.symbol.owner.parentAsClass
|
||||
|
||||
when {
|
||||
@@ -116,11 +118,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
Wrapper.getEnumEntry(enumClass)!!.invokeMethod(valueOfFun, listOf(enumEntryName))
|
||||
environment.mapOfEnums[enumEntry.symbol] = callStack.popState() as Complex
|
||||
}
|
||||
else -> {
|
||||
val enumSuperCall = (enumClass.primaryConstructor?.body?.statements?.firstOrNull() as? IrEnumConstructorCall)
|
||||
enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null
|
||||
callStack.dropSubFrame()
|
||||
}
|
||||
else -> defaultAction()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-40
@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.builtins.evaluateIntrinsicAnnotation
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
@@ -22,7 +20,6 @@ import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
|
||||
internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEnvironment) {
|
||||
val callStack = environment.callStack
|
||||
@@ -44,7 +41,6 @@ internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEn
|
||||
is IrGetValue -> unfoldGetValue(element, environment)
|
||||
is IrGetObjectValue -> unfoldGetObjectValue(element, environment)
|
||||
is IrGetEnumValue -> unfoldGetEnumValue(element, environment)
|
||||
is IrEnumEntry -> unfoldEnumEntry(element, environment)
|
||||
is IrConst<*> -> callStack.addInstruction(SimpleInstruction(element))
|
||||
is IrVariable -> unfoldVariable(element, callStack)
|
||||
is IrSetValue -> unfoldSetValue(element, callStack)
|
||||
@@ -235,18 +231,7 @@ private fun unfoldGetObjectValue(expression: IrGetObjectValue, environment: IrIn
|
||||
val objectClass = expression.symbol.owner
|
||||
environment.mapOfObjects[objectClass.symbol]?.let { return callStack.pushState(it) }
|
||||
|
||||
callStack.newSubFrame(expression, listOf(SimpleInstruction(expression)))
|
||||
when {
|
||||
!objectClass.hasAnnotation(evaluateIntrinsicAnnotation) -> {
|
||||
val state = Common(objectClass)
|
||||
environment.mapOfObjects[objectClass.symbol] = state // must set object's state here to avoid cyclic evaluation
|
||||
callStack.addVariable(Variable(objectClass.thisReceiver!!.symbol, state))
|
||||
|
||||
val constructor = objectClass.constructors.first()
|
||||
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
|
||||
callStack.addInstruction(CompoundInstruction(constructorCall))
|
||||
}
|
||||
}
|
||||
callStack.addInstruction(SimpleInstruction(expression))
|
||||
}
|
||||
|
||||
private fun unfoldGetEnumValue(expression: IrGetEnumValue, environment: IrInterpreterEnvironment) {
|
||||
@@ -257,33 +242,10 @@ private fun unfoldGetEnumValue(expression: IrGetEnumValue, environment: IrInterp
|
||||
val enumEntry = expression.symbol.owner
|
||||
val enumClass = enumEntry.symbol.owner.parentAsClass
|
||||
enumClass.declarations.filterIsInstance<IrEnumEntry>().forEach {
|
||||
if (enumClass.hasAnnotation(evaluateIntrinsicAnnotation)) return@forEach callStack.addInstruction(SimpleInstruction(it))
|
||||
callStack.addInstruction(CompoundInstruction(it))
|
||||
callStack.addInstruction(SimpleInstruction(it))
|
||||
}
|
||||
}
|
||||
|
||||
private fun unfoldEnumEntry(enumEntry: IrEnumEntry, environment: IrInterpreterEnvironment) {
|
||||
val enumClass = enumEntry.symbol.owner.parentAsClass
|
||||
val enumEntries = enumClass.declarations.filterIsInstance<IrEnumEntry>()
|
||||
|
||||
val enumSuperCall = (enumClass.primaryConstructor?.body?.statements?.firstOrNull() as? IrEnumConstructorCall)
|
||||
if (enumEntries.isNotEmpty() && enumSuperCall != null) {
|
||||
val valueArguments = listOf(
|
||||
enumEntry.name.asString().toIrConst(environment.irBuiltIns.stringType),
|
||||
enumEntries.indexOf(enumEntry).toIrConst(environment.irBuiltIns.intType)
|
||||
)
|
||||
valueArguments.forEachIndexed { index, irConst -> enumSuperCall.putValueArgument(index, irConst) }
|
||||
}
|
||||
|
||||
val enumConstructorCall = enumEntry.initializerExpression?.expression as? IrEnumConstructorCall
|
||||
?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
|
||||
val enumClassObject = Variable(enumConstructorCall.getThisReceiver(), Common(enumEntry.correspondingClass ?: enumClass))
|
||||
environment.mapOfEnums[enumEntry.symbol] = enumClassObject.state as Complex
|
||||
|
||||
environment.callStack.newSubFrame(enumEntry, listOf(CompoundInstruction(enumConstructorCall), SimpleInstruction(enumEntry)))
|
||||
environment.callStack.addVariable(enumClassObject)
|
||||
}
|
||||
|
||||
private fun unfoldVariable(variable: IrVariable, callStack: CallStack) {
|
||||
when (variable.initializer) {
|
||||
null -> callStack.addVariable(Variable(variable.symbol))
|
||||
|
||||
+43
-5
@@ -211,7 +211,9 @@ class IrInterpreter private constructor(
|
||||
generateSequence(dispatchReceiver.outerClass) { (it.state as? Complex)?.outerClass }.forEach { callStack.addVariable(it) }
|
||||
}
|
||||
|
||||
callInterceptor.interceptCall(call, irFunction, dispatchReceiver, args.map { it.state })
|
||||
callInterceptor.interceptCall(call, irFunction, dispatchReceiver, args.map { it.state }) {
|
||||
callStack.addInstruction(CompoundInstruction(irFunction))
|
||||
}
|
||||
}
|
||||
|
||||
private fun interpretInstanceInitializerCall(call: IrInstanceInitializerCall) {
|
||||
@@ -273,7 +275,10 @@ class IrInterpreter private constructor(
|
||||
}
|
||||
superReceiver?.let { callStack.addVariable(Variable(it, objectVar.state)) }
|
||||
|
||||
callInterceptor.interceptConstructor(constructorCall, objectVar.state, valueArguments)
|
||||
callInterceptor.interceptConstructor(constructorCall, objectVar.state, valueArguments) {
|
||||
callStack.pushState(objectVar.state)
|
||||
callStack.addInstruction(CompoundInstruction(constructor))
|
||||
}
|
||||
}
|
||||
|
||||
private fun interpretDelegatingConstructorCall(constructorCall: IrDelegatingConstructorCall) {
|
||||
@@ -379,8 +384,16 @@ class IrInterpreter private constructor(
|
||||
}
|
||||
|
||||
private fun interpretGetObjectValue(expression: IrGetObjectValue) {
|
||||
callStack.dropSubFrame()
|
||||
callInterceptor.interceptGetObjectValue(expression)
|
||||
callInterceptor.interceptGetObjectValue(expression) {
|
||||
val objectClass = expression.symbol.owner
|
||||
val state = Common(objectClass)
|
||||
environment.mapOfObjects[objectClass.symbol] = state // must set object's state here to avoid cyclic evaluation
|
||||
callStack.addVariable(Variable(objectClass.thisReceiver!!.symbol, state))
|
||||
|
||||
val constructor = objectClass.constructors.first()
|
||||
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
|
||||
callStack.newSubFrame(constructorCall, listOf(SimpleInstruction(constructorCall)))
|
||||
}
|
||||
}
|
||||
|
||||
private fun interpretGetEnumValue(expression: IrGetEnumValue) {
|
||||
@@ -388,7 +401,32 @@ class IrInterpreter private constructor(
|
||||
}
|
||||
|
||||
private fun interpretEnumEntry(enumEntry: IrEnumEntry) {
|
||||
callInterceptor.interceptEnumEntry(enumEntry)
|
||||
callInterceptor.interceptEnumEntry(enumEntry) {
|
||||
val enumClass = enumEntry.symbol.owner.parentAsClass
|
||||
val enumEntries = enumClass.declarations.filterIsInstance<IrEnumEntry>()
|
||||
val enumSuperCall = (enumClass.primaryConstructor?.body?.statements?.firstOrNull() as? IrEnumConstructorCall)
|
||||
|
||||
val cleanEnumSuperCall = fun() {
|
||||
enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null
|
||||
callStack.dropSubFrame()
|
||||
}
|
||||
|
||||
if (enumEntries.isNotEmpty() && enumSuperCall != null) {
|
||||
val valueArguments = listOf(
|
||||
enumEntry.name.asString().toIrConst(irBuiltIns.stringType),
|
||||
enumEntries.indexOf(enumEntry).toIrConst(irBuiltIns.intType)
|
||||
)
|
||||
valueArguments.forEachIndexed { index, irConst -> enumSuperCall.putValueArgument(index, irConst) }
|
||||
}
|
||||
|
||||
val enumConstructorCall = enumEntry.initializerExpression?.expression as? IrEnumConstructorCall
|
||||
?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
|
||||
val enumClassObject = Variable(enumConstructorCall.getThisReceiver(), Common(enumEntry.correspondingClass ?: enumClass))
|
||||
environment.mapOfEnums[enumEntry.symbol] = enumClassObject.state as Complex
|
||||
|
||||
callStack.newSubFrame(enumEntry, listOf(CompoundInstruction(enumConstructorCall), CustomInstruction(cleanEnumSuperCall)))
|
||||
callStack.addVariable(enumClassObject)
|
||||
}
|
||||
}
|
||||
|
||||
private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall) {
|
||||
|
||||
+2
-2
@@ -112,7 +112,7 @@ internal object EnumValues : IntrinsicBase() {
|
||||
val enumClass = getEnumClass(irFunction, environment)
|
||||
val enumEntries = enumClass.declarations.filterIsInstance<IrEnumEntry>()
|
||||
|
||||
return listOf(customEvaluateInstruction(irFunction, environment)) + enumEntries.reversed().map { CompoundInstruction(it) }
|
||||
return listOf(customEvaluateInstruction(irFunction, environment)) + enumEntries.reversed().map { SimpleInstruction(it) }
|
||||
}
|
||||
|
||||
override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) {
|
||||
@@ -151,7 +151,7 @@ internal object EnumValueOf : IntrinsicBase() {
|
||||
|
||||
override fun unwind(irFunction: IrFunction, environment: IrInterpreterEnvironment): List<Instruction> {
|
||||
val enumEntry = getEnumEntryByName(irFunction, environment) ?: return emptyList()
|
||||
return listOf(customEvaluateInstruction(irFunction, environment), CompoundInstruction(enumEntry))
|
||||
return listOf(customEvaluateInstruction(irFunction, environment), SimpleInstruction(enumEntry))
|
||||
}
|
||||
|
||||
override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) {
|
||||
|
||||
Reference in New Issue
Block a user