diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index 56fdbdef794..1e77b9096e6 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -888,8 +888,8 @@ class IrInterpreter(val irBuiltIns: IrBuiltIns, private val bodyMap: Map { - protected val propertyType: IrType get() = state.property.getter!!.returnType @@ -36,12 +35,76 @@ internal abstract class AbstractKPropertyProxy( get() = state.property.name.asString() override val annotations: List - get() = TODO("Not yet implemented") + get() = TODO("not implemented") + override val parameters: List + get() = state.getParameters(interpreter) override val returnType: KType get() = state.getReturnType(interpreter) + override val typeParameters: List + get() = listOf() override val visibility: KVisibility? get() = state.property.visibility.toKVisibility() + override fun call(vararg args: Any?): Any? = getter.call(*args) + + override fun callBy(args: Map): Any? = getter.callBy(args) + + protected fun checkArguments(expected: Int, actual: Int) { + if (expected != actual) { + throw IllegalArgumentException("Callable expects $expected arguments, but $actual were provided.") + } + } + + abstract inner class Getter(val getter: IrSimpleFunction) : KProperty.Getter { + override val property: KProperty = this@AbstractKPropertyProxy + + override val name: String = "" + override val annotations: List + get() = this@AbstractKPropertyProxy.annotations + override val parameters: List + get() = this@AbstractKPropertyProxy.parameters + override val returnType: KType + get() = this@AbstractKPropertyProxy.returnType + override val typeParameters: List + get() = this@AbstractKPropertyProxy.typeParameters + + override val isInline: Boolean = getter.isInline + override val isExternal: Boolean = getter.isExternal + override val isOperator: Boolean = getter.isOperator + override val isInfix: Boolean = getter.isInfix + override val isSuspend: Boolean = getter.isSuspend + + override val visibility: KVisibility? = getter.visibility.toKVisibility() + override val isFinal: Boolean = getter.modality == Modality.FINAL + override val isOpen: Boolean = getter.modality == Modality.OPEN + override val isAbstract: Boolean = getter.modality == Modality.ABSTRACT + } + + abstract inner class Setter(val setter: IrSimpleFunction) : KMutableProperty.Setter { + override val property: KProperty = this@AbstractKPropertyProxy + + override val name: String = "" + override val annotations: List + get() = this@AbstractKPropertyProxy.annotations + override val parameters: List + get() = this@AbstractKPropertyProxy.parameters + override val returnType: KType + get() = this@AbstractKPropertyProxy.returnType + override val typeParameters: List + get() = this@AbstractKPropertyProxy.typeParameters + + override val isInline: Boolean = setter.isInline + override val isExternal: Boolean = setter.isExternal + override val isOperator: Boolean = setter.isOperator + override val isInfix: Boolean = setter.isInfix + override val isSuspend: Boolean = setter.isSuspend + + override val visibility: KVisibility? = setter.visibility.toKVisibility() + override val isFinal: Boolean = setter.modality == Modality.FINAL + override val isOpen: Boolean = setter.modality == Modality.OPEN + override val isAbstract: Boolean = setter.modality == Modality.ABSTRACT + } + override fun equals(other: Any?): Boolean { if (other !is AbstractKPropertyProxy) return false return state == other.state diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt index fddee37ea44..9efcf088edd 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState -import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState import org.jetbrains.kotlin.ir.interpreter.toState import org.jetbrains.kotlin.ir.util.isSuspend import kotlin.reflect.* @@ -43,6 +42,7 @@ internal class KFunctionProxy( get() = state.getTypeParameters(interpreter) override fun call(vararg args: Any?): Any? { + // TODO check arity var index = 0 val dispatchReceiver = state.irFunction.dispatchReceiverParameter?.let { Variable(it.symbol, args[index++].toState(it.type)) } val extensionReceiver = state.irFunction.extensionReceiverParameter?.let { Variable(it.symbol, args[index++].toState(it.type)) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt index f5eaa7c35dc..7dc9a48a383 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt @@ -10,49 +10,50 @@ import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState import org.jetbrains.kotlin.ir.interpreter.state.State import org.jetbrains.kotlin.ir.interpreter.toState -import kotlin.reflect.KMutableProperty0 -import kotlin.reflect.KParameter -import kotlin.reflect.KProperty0 -import kotlin.reflect.KTypeParameter +import kotlin.reflect.* internal open class KProperty0Proxy( override val state: KPropertyState, override val interpreter: IrInterpreter ) : AbstractKPropertyProxy(state, interpreter), KProperty0 { + override val getter: KProperty0.Getter + get() = object : Getter(state.property.getter!!), KProperty0.Getter { + override fun invoke(): Any? = call() - override val getter: KProperty0.Getter - get() = TODO("Not yet implemented") - override val parameters: List - get() = TODO("Not yet implemented") - override val typeParameters: List - get() = TODO("Not yet implemented") + override fun call(vararg args: Any?): Any? { + checkArguments(0, args.size) + return state.dispatchReceiver!!.getState(state.property.symbol)!! + } - override fun call(vararg args: Any?): Any? { - TODO("Not yet implemented") - } + override fun callBy(args: Map): Any? { + TODO("Not yet implemented") + } + } - override fun callBy(args: Map): Any? { - TODO("Not yet implemented") - } - - override fun get(): Any? { - return state.dispatchReceiver!!.getState(state.property.symbol)!! - } + override fun get(): Any? = getter.call() override fun getDelegate(): Any? { TODO("Not yet implemented") } - override fun invoke(): Any? = get() + override fun invoke(): Any? = getter.call() } internal class KMutableProperty0Proxy( override val state: KPropertyState, override val interpreter: IrInterpreter ) : KProperty0Proxy(state, interpreter), KMutableProperty0 { + override val setter: KMutableProperty0.Setter = + object : Setter(state.property.setter!!), KMutableProperty0.Setter { + override fun invoke(p1: Any?) = call(p1) - override val setter: KMutableProperty0.Setter - get() = TODO("Not yet implemented") + override fun call(vararg args: Any?) { + checkArguments(1, args.size) + state.dispatchReceiver!!.setField(Variable(state.property.symbol, args.single().toState(propertyType))) + } - override fun set(value: Any?) { - state.dispatchReceiver!!.setField(Variable(state.property.symbol, value.toState(propertyType))) - } + override fun callBy(args: Map) { + TODO("Not yet implemented") + } + } + + override fun set(value: Any?) = setter.call(value) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt index 1d55d96ecdf..17de1ca1e1a 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt @@ -11,49 +11,53 @@ import org.jetbrains.kotlin.ir.interpreter.proxy.wrap import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState import org.jetbrains.kotlin.ir.interpreter.toState -import kotlin.reflect.KMutableProperty1 -import kotlin.reflect.KParameter -import kotlin.reflect.KProperty1 -import kotlin.reflect.KTypeParameter +import kotlin.reflect.* internal open class KProperty1Proxy( override val state: KPropertyState, override val interpreter: IrInterpreter ) : AbstractKPropertyProxy(state, interpreter), KProperty1 { - override val getter: KProperty1.Getter - get() = TODO("Not yet implemented") - override val parameters: List - get() = TODO("Not yet implemented") - override val typeParameters: List - get() = TODO("Not yet implemented") + get() = object : Getter(state.property.getter!!), KProperty1.Getter { + override fun invoke(p1: Proxy): Any? = call(p1) - override fun call(vararg args: Any?): Any? { - TODO("Not yet implemented") - } + override fun call(vararg args: Any?): Any? { + checkArguments(1, args.size) + val receiver = args.single() as Proxy + return receiver.state.getState(state.property.symbol)!!.wrap(interpreter) + } - override fun callBy(args: Map): Any? { - TODO("Not yet implemented") - } + override fun callBy(args: Map): Any? { + TODO("Not yet implemented") + } + } - override fun get(receiver: Proxy): Any? { - return receiver.state.getState(state.property.symbol)!!.wrap(interpreter) - } + override fun get(receiver: Proxy): Any? = getter.call(receiver) override fun getDelegate(receiver: Proxy): Any? { TODO("Not yet implemented") } - override fun invoke(p1: Proxy): Any? = get(p1) + override fun invoke(p1: Proxy): Any? = getter.call(p1) } internal class KMutableProperty1Proxy( override val state: KPropertyState, override val interpreter: IrInterpreter ) : KProperty1Proxy(state, interpreter), KMutableProperty1 { + override val setter: KMutableProperty1.Setter = + object : Setter(state.property.setter!!), KMutableProperty1.Setter { + override fun invoke(p1: Proxy, p2: Any?) = call(p1, p2) - override val setter: KMutableProperty1.Setter - get() = TODO("Not yet implemented") + override fun call(vararg args: Any?) { + checkArguments(2, args.size) + val receiver = args[0] as Proxy + val value = args[1] + receiver.state.setField(Variable(state.property.symbol, value.toState(propertyType))) + } - override fun set(receiver: Proxy, value: Any?) { - receiver.state.setField(Variable(state.property.symbol, value.toState(propertyType))) - } + override fun callBy(args: Map) { + TODO("Not yet implemented") + } + } + + override fun set(receiver: Proxy, value: Any?) = setter.call(receiver, value) } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty2Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty2Proxy.kt index 6353831e768..1f3be9f429c 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty2Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty2Proxy.kt @@ -6,51 +6,58 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection import org.jetbrains.kotlin.ir.interpreter.IrInterpreter -import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy +import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState -import kotlin.reflect.KMutableProperty2 -import kotlin.reflect.KParameter -import kotlin.reflect.KProperty2 -import kotlin.reflect.KTypeParameter +import org.jetbrains.kotlin.ir.interpreter.toState +import kotlin.reflect.* internal open class KProperty2Proxy( override val state: KPropertyState, override val interpreter: IrInterpreter -) : AbstractKPropertyProxy(state, interpreter), KProperty2 { +) : AbstractKPropertyProxy(state, interpreter), KProperty2 { + override val getter: KProperty2.Getter = + object : Getter(state.property.getter!!), KProperty2.Getter { + override fun invoke(p1: Any?, p2: Any?): Any? = call(p1, p2) - override val getter: KProperty2.Getter - get() = TODO("Not yet implemented") - override val parameters: List - get() = TODO("Not yet implemented") - override val typeParameters: List - get() = TODO("Not yet implemented") + override fun call(vararg args: Any?): Any? { + checkArguments(2, args.size) + val dispatch = Variable(getter.dispatchReceiverParameter!!.symbol, args[0].toState(getter.dispatchReceiverParameter!!.type)) + val extension = Variable(getter.extensionReceiverParameter!!.symbol, args[1].toState(getter.extensionReceiverParameter!!.type)) + return with(this@KProperty2Proxy.interpreter) { getter.interpret(listOf(dispatch, extension)) } + } - override fun call(vararg args: Any?): Any? { + override fun callBy(args: Map): Any? { + TODO("Not yet implemented") + } + } + + override fun get(receiver1: Any?, receiver2: Any?): Any? = getter.call(receiver1, receiver2) + + override fun getDelegate(receiver1: Any?, receiver2: Any?): Any? { TODO("Not yet implemented") } - override fun callBy(args: Map): Any? { - TODO("Not yet implemented") - } - - override fun get(receiver1: Proxy, receiver2: Proxy): Any? { - TODO("Not yet implemented") - } - - override fun getDelegate(receiver1: Proxy, receiver2: Proxy): Any? { - TODO("Not yet implemented") - } - - override fun invoke(p1: Proxy, p2: Proxy): Any? = get(p1, p2) + override fun invoke(p1: Any?, p2: Any?): Any? = getter.call(p1, p2) } internal class KMutableProperty2Proxy( override val state: KPropertyState, override val interpreter: IrInterpreter -) : KProperty2Proxy(state, interpreter), KMutableProperty2 { +) : KProperty2Proxy(state, interpreter), KMutableProperty2 { + override val setter: KMutableProperty2.Setter + get() = object : Setter(state.property.setter!!), KMutableProperty2.Setter { + override fun invoke(p1: Any?, p2: Any?, p3: Any?) = call(p1, p2, p3) - override val setter: KMutableProperty2.Setter - get() = TODO("Not yet implemented") + override fun call(vararg args: Any?) { + checkArguments(3, args.size) + val receiver1 = args[0] + val receiver2 = args[1] + val value = args[2] + TODO("Not yet implemented, receiver1 = $receiver1, receiver2 = $receiver2, value = $value") + } - override fun set(receiver1: Proxy, receiver2: Proxy, value: Any?) { - TODO("Not yet implemented") - } + override fun callBy(args: Map) { + TODO("Not yet implemented") + } + } + + override fun set(receiver1: Any?, receiver2: Any?, value: Any?) = setter.call(receiver1, receiver2, value) } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt index 0d7c9e43845..185531c3745 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt @@ -144,7 +144,10 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex notNullType.isPrimitiveType() || notNullType.isString() -> getPrimitiveClass(notNullType, asObject)!! notNullType.isArray() -> { val argumentFqName = (this as IrSimpleType).arguments.single().typeOrNull?.classOrNull?.owner?.fqNameWhenAvailable - argumentFqName?.let { Class.forName("[L$it;") } ?: Array::class.java + when { + argumentFqName != null && argumentFqName.asString() != "kotlin.Any" -> argumentFqName.let { Class.forName("[L$it;") } + else -> Array::class.java + } } notNullType.isNothing() -> Nothing::class.java notNullType.isAny() -> Any::class.java diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KParameterState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KParameterState.kt index 333ee6cf5be..03e09e0b33b 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KParameterState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KParameterState.kt @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.ir.interpreter.state.reflection -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrProperty -import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy import kotlin.reflect.KParameter @@ -51,6 +48,8 @@ internal class KParameterState( append(" of ") when (val parent = irParameter.parent) { + is IrSimpleFunction -> parent.correspondingPropertySymbol?.owner?.let { append(renderProperty(it)) } + ?: append(renderFunction(parent)) is IrFunction -> append(renderFunction(parent)) is IrProperty -> append(renderProperty(parent)) else -> TODO() diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KPropertyState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KPropertyState.kt index 991a80d1092..e40561417ce 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KPropertyState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KPropertyState.kt @@ -9,20 +9,35 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.expressions.IrPropertyReference import org.jetbrains.kotlin.ir.interpreter.IrInterpreter +import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KParameterProxy import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy import org.jetbrains.kotlin.ir.interpreter.state.State import org.jetbrains.kotlin.ir.types.classOrNull +import kotlin.reflect.KParameter import kotlin.reflect.KType internal class KPropertyState( - val property: IrProperty, override val irClass: IrClass, val dispatchReceiver: State? = null, val extensionReceiver: State? = null + val property: IrProperty, override val irClass: IrClass, val dispatchReceiver: State? = null ) : ReflectionState() { - constructor(propertyReference: IrPropertyReference, dispatchReceiver: State?, extensionReceiver: State?) - : this(propertyReference.symbol.owner, propertyReference.type.classOrNull!!.owner, dispatchReceiver, extensionReceiver) + constructor(propertyReference: IrPropertyReference, dispatchReceiver: State?) + : this(propertyReference.symbol.owner, propertyReference.type.classOrNull!!.owner, dispatchReceiver) + private var _parameters: List? = null private var _returnType: KType? = null + fun getParameters(interpreter: IrInterpreter): List { + if (_parameters != null) return _parameters!! + val kParameterIrClass = irClass.getIrClassOfReflectionFromList("parameters") + var index = 0 + val instanceParameter = property.getter?.dispatchReceiverParameter?.takeIf { dispatchReceiver == null } + ?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.INSTANCE), interpreter) } + val extensionParameter = property.getter?.extensionReceiverParameter + ?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.EXTENSION_RECEIVER), interpreter) } + _parameters = listOfNotNull(instanceParameter, extensionParameter) + return _parameters!! + } + fun getReturnType(interpreter: IrInterpreter): KType { if (_returnType != null) return _returnType!! val kTypeIrClass = irClass.getIrClassOfReflection("returnType") @@ -50,7 +65,6 @@ internal class KPropertyState( if (property != other.property) return false if (dispatchReceiver != other.dispatchReceiver) return false - if (extensionReceiver != other.extensionReceiver) return false return true } @@ -58,7 +72,6 @@ internal class KPropertyState( override fun hashCode(): Int { var result = property.hashCode() result = 31 * result + (dispatchReceiver?.hashCode() ?: 0) - result = 31 * result + (extensionReceiver?.hashCode() ?: 0) return result }