Fix property rendering in interpreter

This commit is contained in:
Ivan Kylchik
2021-06-01 14:26:02 +03:00
committed by TeamCityServer
parent af67e950c4
commit 59fefb6214
6 changed files with 51 additions and 17 deletions
@@ -94,9 +94,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
val function = when (val symbol = invokedFunction.symbol) {
is IrSimpleFunctionSymbol -> {
val irCall = IrCallImpl.fromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, invokedFunction.returnType, invokedFunction.symbol as IrSimpleFunctionSymbol
)
val irCall = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, invokedFunction.returnType, symbol)
val actualFunction = dispatchReceiver?.getIrFunctionByIrCall(irCall) ?: invokedFunction
callStack.newFrame(actualFunction)
callStack.addInstruction(SimpleInstruction(actualFunction))
@@ -118,6 +116,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
function.dispatchReceiverParameter?.let { callStack.addVariable(Variable(it.symbol, dispatchReceiver!!)) }
function.extensionReceiverParameter?.let { callStack.addVariable(Variable(it.symbol, extensionReceiver!!)) }
function.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) }
if (invokedFunction.symbol is IrConstructorSymbol) return
callStack.loadUpValues(functionState)
if (extensionReceiver is StateWithClosure) callStack.loadUpValues(extensionReceiver)
@@ -125,7 +124,6 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
generateSequence(dispatchReceiver.outerClass) { (it.state as? Complex)?.outerClass }.forEach { callStack.addVariable(it) }
}
if (invokedFunction.symbol is IrConstructorSymbol) return
this.interceptCall(call, function, listOfNotNull(dispatchReceiver, extensionReceiver) + valueArguments) {
callStack.addInstruction(CompoundInstruction(function))
}
@@ -426,6 +426,7 @@ class IrInterpreter private constructor(
val cleanEnumSuperCall = fun() {
enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null
callStack.popState() // result of constructor must be dropped, because next instruction will be `IrGetEnumValue`
callStack.dropSubFrame()
}
@@ -606,6 +607,16 @@ class IrInterpreter private constructor(
callStack.dropSubFrame()
val propertyState = KPropertyState(propertyReference, receiver)
fun List<IrTypeParameter>.addToFields() {
(0 until propertyReference.typeArgumentsCount).forEach { index ->
val kTypeState = KTypeState(propertyReference.getTypeArgument(index)!!, irBuiltIns.anyClass.owner)
propertyState.fields += Variable(this[index].symbol, kTypeState)
}
}
propertyReference.getter?.owner?.typeParameters?.addToFields()
propertyReference.setter?.owner?.typeParameters?.addToFields()
callStack.pushState(propertyState)
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.isNull
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.toState
import org.jetbrains.kotlin.ir.util.isObject
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
import kotlin.reflect.*
@@ -66,6 +67,7 @@ internal class KMutableProperty0Proxy(
checkArguments(1, args.size)
// null receiver <=> property is on top level
verify(state.receiver != null) { "Cannot interpret set method on top level properties" }
verify(state.receiver?.irClass?.isObject != true) { "Cannot interpret set method on property of object" }
val receiver = state.receiver!!
val newValue = args.single().toState(propertyType)
setter.getExtensionReceiver()
@@ -5,23 +5,35 @@
package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState
import org.jetbrains.kotlin.ir.interpreter.toState
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.classifierOrFail
import kotlin.reflect.*
internal open class KProperty1Proxy(
override val state: KPropertyState, override val callInterceptor: CallInterceptor
) : AbstractKPropertyProxy(state, callInterceptor), KProperty1<Any?, Any?> {
protected fun IrValueParameter.getActualType(): IrType {
return when (this.type.classOrNull) {
null -> (state.getField(this.type.classifierOrFail) as KTypeState).irType
else -> this.type
}
}
override val getter: KProperty1.Getter<Any?, Any?>
get() = object : Getter(state.property.getter!!), KProperty1.Getter<Any?, Any?> {
override fun invoke(p1: Any?): Any? = call(p1)
override fun call(vararg args: Any?): Any? {
checkArguments(1, args.size)
val receiverParameter = getter.dispatchReceiverParameter ?: getter.extensionReceiverParameter
val receiver = Variable(receiverParameter!!.symbol, args[0].toState(receiverParameter.type))
val receiverParameter = (getter.dispatchReceiverParameter ?: getter.extensionReceiverParameter)!!
val receiver = Variable(receiverParameter.symbol, args[0].toState(receiverParameter.getActualType()))
return callInterceptor.interceptProxy(getter, listOf(receiver))
}
@@ -48,10 +60,10 @@ internal class KMutableProperty1Proxy(
override fun call(vararg args: Any?) {
checkArguments(2, args.size)
val receiverParameter = setter.dispatchReceiverParameter ?: setter.extensionReceiverParameter
val receiver = Variable(receiverParameter!!.symbol, args[0].toState(receiverParameter.type))
val receiverParameter = (setter.dispatchReceiverParameter ?: setter.extensionReceiverParameter)!!
val receiver = Variable(receiverParameter.symbol, args[0].toState(receiverParameter.getActualType()))
val valueParameter = setter.valueParameters.single()
val value = Variable(valueParameter.symbol, args[1].toState(valueParameter.type))
val value = Variable(valueParameter.symbol, args[1].toState(valueParameter.getActualType()))
callInterceptor.interceptProxy(setter, listOf(receiver, value))
}
@@ -42,16 +42,15 @@ internal abstract class ReflectionState : State {
private fun renderReceivers(dispatchReceiver: IrType?, extensionReceiver: IrType?): String {
return buildString {
if (dispatchReceiver != null) {
append(dispatchReceiver.renderType())
append(".")
append(dispatchReceiver.renderType()).append(".")
}
val addParentheses = dispatchReceiver != null && extensionReceiver != null
if (addParentheses) append("(")
if (extensionReceiver != null) {
append(extensionReceiver.renderType())
append(".")
val addParentheses = dispatchReceiver != null
if (addParentheses) append("(")
append(extensionReceiver.renderType()).append(".")
if (addParentheses) append(")")
}
if (addParentheses) append(")")
}
}
@@ -79,7 +78,12 @@ internal abstract class ReflectionState : State {
}
protected fun IrType.renderType(): String {
var renderedType = this.render()
var renderedType = this.render().replace("<root>.", "")
if (renderedType.contains("<get-")) {
val startIndex = renderedType.indexOf("<get-")
val lastTriangle = renderedType.indexOf('>', startIndex) + 1
renderedType = renderedType.replaceRange(startIndex, lastTriangle, "get")
}
do {
val index = renderedType.indexOf(" of ")
if (index == -1) break
@@ -23,3 +23,10 @@ const val mutablePropertyWithReceiverName = B(10)::b.<!EVALUATED: `b`!>name<!>
const val mutablePropertyWithReceiverGet = B(11)::b.<!EVALUATED: `11`!>get()<!>
const val mutablePropertyWithReceiverSet = B(12).apply { this::b.set(13) }.<!EVALUATED: `13`!>b<!>
const val mutablePropertyWithReceiverInvoke = B(14)::b.<!EVALUATED: `14`!>invoke()<!>
@CompileTimeCalculation
var <T> T.bar : T
get() = this
set(value) { }
const val barToString = String::bar.<!EVALUATED: `var T.bar: T`!>toString()<!>