diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 797e7573912..3f0e21923bd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -15,11 +15,22 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.KotlinTypeFactory +import org.jetbrains.kotlin.types.TypeProjection +import org.jetbrains.kotlin.types.typeUtil.asTypeProjection +import org.jetbrains.kotlin.utils.addIfNotNull import java.lang.System.out +import java.util.* +import kotlin.reflect.KProperty internal class SpecialDescriptorsFactory(val context: Context) { private val enumSpecialDescriptorsFactory by lazy { EnumSpecialDescriptorsFactory(context) } @@ -106,11 +117,77 @@ internal class SpecialDescriptorsFactory(val context: Context) { } } + +class ReflectionTypes(module: ModuleDescriptor) { + val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect") + val KONAN_INTERNAL_FQ_NAME = FqName("konan.internal") + + private val kotlinReflectScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { + module.getPackage(KOTLIN_REFLECT_FQ_NAME).memberScope + } + + private val konanInternalScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { + module.getPackage(KONAN_INTERNAL_FQ_NAME).memberScope + } + + private fun find(memberScope: MemberScope, className: String): ClassDescriptor { + val name = Name.identifier(className) + return memberScope.getContributedClassifier(name, NoLookupLocation.FROM_REFLECTION) as ClassDescriptor + } + + private class ClassLookup(val memberScope: MemberScope) { + operator fun getValue(types: ReflectionTypes, property: KProperty<*>): ClassDescriptor { + return types.find(memberScope, property.name.capitalize()) + } + } + + private fun getFunctionTypeArgumentProjections( + receiverType: KotlinType?, + parameterTypes: List, + returnType: KotlinType + ): List { + val arguments = ArrayList(parameterTypes.size + (if (receiverType != null) 1 else 0) + 1) + + arguments.addIfNotNull(receiverType?.asTypeProjection()) + + parameterTypes.mapTo(arguments, KotlinType::asTypeProjection) + + arguments.add(returnType.asTypeProjection()) + + return arguments + } + + fun getKFunction(n: Int): ClassDescriptor = find(kotlinReflectScope, "KFunction$n") + + val kClass: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kProperty2: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kProperty0Impl: ClassDescriptor by ClassLookup(konanInternalScope) + val kProperty1Impl: ClassDescriptor by ClassLookup(konanInternalScope) + val kMutableProperty0Impl: ClassDescriptor by ClassLookup(konanInternalScope) + val kMutableProperty1Impl: ClassDescriptor by ClassLookup(konanInternalScope) + val kMutableProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kMutableProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope) + + fun getKFunctionType( + annotations: Annotations, + receiverType: KotlinType?, + parameterTypes: List, + returnType: KotlinType + ): KotlinType { + val arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType) + val classDescriptor = getKFunction(arguments.size - 1 /* return type */) + return KotlinTypeFactory.simpleNotNullType(annotations, classDescriptor, arguments) + } +} + internal class Context(val config: KonanConfig) : KonanBackendContext() { var moduleDescriptor: ModuleDescriptor? = null val specialDescriptorsFactory = SpecialDescriptorsFactory(this) + val reflectionTypes: ReflectionTypes by lazy { ReflectionTypes(moduleDescriptor!!) } private val vtableBuilders = mutableMapOf() fun getVtableBuilder(classDescriptor: ClassDescriptor) = vtableBuilders.getOrPut(classDescriptor) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt index 4238398a03e..1ed929866e6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt @@ -101,6 +101,7 @@ private class CallableReferencesUnbinder(val lower: CallableReferenceLowering, } override fun visitCallableReference(expression: IrCallableReference): IrExpression { + expression.transformChildrenVoid(this) if (!expression.type.isFunctionOrKFunctionType) { // Not a subject of this lowering. return expression diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt index 4dfe4a61bf3..b8eef19c073 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt @@ -1,26 +1,26 @@ package org.jetbrains.kotlin.backend.konan.lower -import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.jvm.descriptors.initialize import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.OverriddenFunctionDescriptor import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.createArrayOfExpression -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl -import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.IrCallableReference +import org.jetbrains.kotlin.ir.expressions.IrConstKind +import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName @@ -28,31 +28,48 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.* internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass { - private val kotlinReflectPackage = context.irModule!!.descriptor.getPackage(FqName.fromSegments(listOf("kotlin", "reflect"))) - private val genericKPropertyImplType = kotlinReflectPackage.memberScope.getContributedClassifier(Name.identifier("KPropertyImpl"), - NoLookupLocation.FROM_BACKEND) as ClassDescriptor + private val genericKProperty0ImplType = context.reflectionTypes.kProperty0Impl + private val genericKProperty1ImplType = context.reflectionTypes.kProperty1Impl + private val genericKMutableProperty0ImplType = context.reflectionTypes.kMutableProperty0Impl + private val genericKMutableProperty1ImplType = context.reflectionTypes.kMutableProperty1Impl private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin")) private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - fun getKPropertyImplConstructorDescriptorWithProjection(type: KotlinType): ClassConstructorDescriptor { - val typeParameterT = genericKPropertyImplType.declaredTypeParameters[0] - val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(type))) + private fun getKPropertyImplConstructorDescriptor(returnType: KotlinType, isMutable: Boolean): ClassConstructorDescriptor { + val genericKPropertyImplType = if (isMutable) genericKMutableProperty0ImplType else genericKProperty0ImplType + val typeParameterR = genericKPropertyImplType.declaredTypeParameters[0] + val typeSubstitutor = TypeSubstitutor.create(mapOf( + typeParameterR.typeConstructor to TypeProjectionImpl(returnType))) return genericKPropertyImplType.unsubstitutedPrimaryConstructor!!.substitute(typeSubstitutor)!! } - fun ClassDescriptor.replace(vararg type: KotlinType): SimpleType { + private fun getKPropertyImplConstructorDescriptor(receiverType: KotlinType?, returnType: KotlinType, isMutable: Boolean) + : ClassConstructorDescriptor { + if (receiverType == null) + return getKPropertyImplConstructorDescriptor(returnType, isMutable) + val genericKPropertyImplType = if (isMutable) genericKMutableProperty1ImplType else genericKProperty1ImplType + val typeParameterT = genericKPropertyImplType.declaredTypeParameters[0] + val typeParameterR = genericKPropertyImplType.declaredTypeParameters[1] + val typeSubstitutor = TypeSubstitutor.create(mapOf( + typeParameterT.typeConstructor to TypeProjectionImpl(receiverType), + typeParameterR.typeConstructor to TypeProjectionImpl(returnType))) + return genericKPropertyImplType.unsubstitutedPrimaryConstructor!!.substitute(typeSubstitutor)!! + } + + private fun ClassDescriptor.replace(vararg type: KotlinType): SimpleType { return this.defaultType.replace(type.map(::TypeProjectionImpl)) } override fun lower(irFile: IrFile) { val kProperties = mutableMapOf>() - val getter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND).single() + val arrayItemGetter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), + NoLookupLocation.FROM_BACKEND).single() val typeParameterT = genericArrayType.declaredTypeParameters[0] - val kPropertyImplType = genericKPropertyImplType.replace(context.builtIns.anyType) + val kPropertyImplType = genericKProperty1ImplType.replace(context.builtIns.anyType, context.builtIns.anyType) val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(kPropertyImplType))) - val substitutedGetter = getter.substitute(typeSubstitutor)!! + val substitutedArrayItemGetter = arrayItemGetter.substitute(typeSubstitutor)!! val kPropertiesField = createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor, genericArrayType.replace(kPropertyImplType)) @@ -81,26 +98,26 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa expression.transformChildrenVoid(this) val propertyDescriptor = expression.descriptor as? VariableDescriptorWithAccessors if (propertyDescriptor == null) return expression - val field = kProperties.getOrPut(propertyDescriptor) { - val initializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - getKPropertyImplConstructorDescriptorWithProjection(propertyDescriptor.type)).apply { - putValueArgument(0, IrConstImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString())) + val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null } + if (receiversCount == 1 || propertyDescriptor !is PropertyDescriptor) // Has receiver or is local delegated. + return createKProperty(expression, propertyDescriptor) + else if (receiversCount == 0) { // Cache KProperties with no arguments. + val field = kProperties.getOrPut(propertyDescriptor) { + createKProperty(expression, propertyDescriptor) to kProperties.size } - val index = kProperties.size - initializer to index - } - - return IrCallImpl(expression.startOffset, expression.endOffset, substitutedGetter).apply { - dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField) - putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second)) + return IrCallImpl(expression.startOffset, expression.endOffset, substitutedArrayItemGetter).apply { + dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField) + putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second)) + } } + else throw AssertionError("Callable reference to properties with two receivers is not allowed: $propertyDescriptor") } }) if (kProperties.isNotEmpty()) { val initializers = kProperties.values.sortedBy { it.second }.map { it.first } + // TODO: move to object for lazy initialization. irFile.declarations.add(0, IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, kPropertiesField, @@ -109,6 +126,57 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa } } + private fun createKProperty(expression: IrCallableReference, propertyDescriptor: VariableDescriptorWithAccessors): IrCallImpl { + val getter = propertyDescriptor.getter!! + val receiverTypes = mutableListOf() + getter.dispatchReceiverParameter.let { + if (it != null && expression.dispatchReceiver == null) + receiverTypes.add(it.type) + } + getter.extensionReceiverParameter.let { + if (it != null && expression.extensionReceiver == null) + receiverTypes.add(it.type) + } + val receiverType = receiverTypes.singleOrNull() + + val startOffset = expression.startOffset + val endOffset = expression.endOffset + val getterKFunctionType = context.reflectionTypes.getKFunctionType( + annotations = Annotations.EMPTY, + receiverType = receiverType, + parameterTypes = listOf(), + returnType = propertyDescriptor.type) + val getterCallableReference = IrCallableReferenceImpl(startOffset, endOffset, getterKFunctionType, getter, null).apply { + dispatchReceiver = expression.dispatchReceiver + extensionReceiver = expression.extensionReceiver + } + + val setterCallableReference = propertyDescriptor.setter.let { + if (it == null) null + else { + val setterKFunctionType = context.reflectionTypes.getKFunctionType( + annotations = Annotations.EMPTY, + receiverType = receiverType, + parameterTypes = listOf(propertyDescriptor.type), + returnType = context.builtIns.unitType) + IrCallableReferenceImpl(startOffset, endOffset, setterKFunctionType, it, null).apply { + dispatchReceiver = expression.dispatchReceiver + extensionReceiver = expression.extensionReceiver + } + } + } + + val descriptor = getKPropertyImplConstructorDescriptor(receiverType, propertyDescriptor.type, setterCallableReference != null) + val initializer = IrCallImpl(startOffset, endOffset, descriptor).apply { + putValueArgument(0, IrConstImpl(startOffset, endOffset, + context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString())) + putValueArgument(1, getterCallableReference) + if (setterCallableReference != null) + putValueArgument(2, setterCallableReference) + } + return initializer + } + private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION : IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION") diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index c7afcbf613c..582a42f8a14 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -651,6 +651,42 @@ task delegatedProperty_map(type: RunKonanTest) { source = "codegen/delegatedProperty/map.kt" } +task propertyCallableReference_valClass(type: RunKonanTest) { + goldValue = "42\n117\n" + source = "codegen/propertyCallableReference/valClass.kt" +} + +task propertyCallableReference_valModule(type: RunKonanTest) { + goldValue = "42\n" + source = "codegen/propertyCallableReference/valModule.kt" +} + +task propertyCallableReference_varClass(type: RunKonanTest) { + goldValue = "117\n117\n42\n42\n" + source = "codegen/propertyCallableReference/varClass.kt" +} + +task propertyCallableReference_varModule(type: RunKonanTest) { + goldValue = "117\n117\n" + source = "codegen/propertyCallableReference/varModule.kt" +} + +task propertyCallableReference_valExtension(type: RunKonanTest) { + goldValue = "42\n117\n" + source = "codegen/propertyCallableReference/valExtension.kt" +} + +task propertyCallableReference_varExtension(type: RunKonanTest) { + goldValue = "117\n117\n42\n42\n" + source = "codegen/propertyCallableReference/varExtension.kt" +} + +task propertyCallableReference_linkTest(type: LinkKonanTest) { + goldValue = "42\n117\n" + source = "codegen/propertyCallableReference/linkTest_main.kt" + lib = "codegen/propertyCallableReference/linkTest_lib.kt" +} + task array0(type: RunKonanTest) { goldValue = "5\n6\n7\n8\n9\n10\n11\n12\n13\n" source = "runtime/collections/array0.kt" diff --git a/backend.native/tests/codegen/propertyCallableReference/linkTest_lib.kt b/backend.native/tests/codegen/propertyCallableReference/linkTest_lib.kt new file mode 100644 index 00000000000..7595b1acde4 --- /dev/null +++ b/backend.native/tests/codegen/propertyCallableReference/linkTest_lib.kt @@ -0,0 +1,3 @@ +package a + +class A(val x: Int) \ No newline at end of file diff --git a/backend.native/tests/codegen/propertyCallableReference/linkTest_main.kt b/backend.native/tests/codegen/propertyCallableReference/linkTest_main.kt new file mode 100644 index 00000000000..5af7b724a75 --- /dev/null +++ b/backend.native/tests/codegen/propertyCallableReference/linkTest_main.kt @@ -0,0 +1,9 @@ +import a.A + +fun main(args: Array) { + val p1 = A::x + println(p1.get(A(42))) + val a = A(117) + val p2 = a::x + println(p2.get()) +} \ No newline at end of file diff --git a/backend.native/tests/codegen/propertyCallableReference/valClass.kt b/backend.native/tests/codegen/propertyCallableReference/valClass.kt new file mode 100644 index 00000000000..9e3f29f56f5 --- /dev/null +++ b/backend.native/tests/codegen/propertyCallableReference/valClass.kt @@ -0,0 +1,9 @@ +class A(val x: Int) + +fun main(args: Array) { + val p1 = A::x + println(p1.get(A(42))) + val a = A(117) + val p2 = a::x + println(p2.get()) +} \ No newline at end of file diff --git a/backend.native/tests/codegen/propertyCallableReference/valExtension.kt b/backend.native/tests/codegen/propertyCallableReference/valExtension.kt new file mode 100644 index 00000000000..ef7a7dcc4ee --- /dev/null +++ b/backend.native/tests/codegen/propertyCallableReference/valExtension.kt @@ -0,0 +1,13 @@ +class A(y: Int) { + var x = y +} + +val A.z get() = this.x + +fun main(args: Array) { + val p1 = A::z + println(p1.get(A(42))) + val a = A(117) + val p2 = a::z + println(p2.get()) +} \ No newline at end of file diff --git a/backend.native/tests/codegen/propertyCallableReference/valModule.kt b/backend.native/tests/codegen/propertyCallableReference/valModule.kt new file mode 100644 index 00000000000..800051cebfa --- /dev/null +++ b/backend.native/tests/codegen/propertyCallableReference/valModule.kt @@ -0,0 +1,6 @@ +val x = 42 + +fun main(args: Array) { + val p = ::x + println(p.get()) +} \ No newline at end of file diff --git a/backend.native/tests/codegen/propertyCallableReference/varClass.kt b/backend.native/tests/codegen/propertyCallableReference/varClass.kt new file mode 100644 index 00000000000..a0b4e060a4e --- /dev/null +++ b/backend.native/tests/codegen/propertyCallableReference/varClass.kt @@ -0,0 +1,13 @@ +class A(var x: Int) + +fun main(args: Array) { + val p1 = A::x + val a = A(42) + p1.set(a, 117) + println(a.x) + println(p1.get(a)) + val p2 = a::x + p2.set(42) + println(a.x) + println(p2.get()) +} \ No newline at end of file diff --git a/backend.native/tests/codegen/propertyCallableReference/varExtension.kt b/backend.native/tests/codegen/propertyCallableReference/varExtension.kt new file mode 100644 index 00000000000..9f304fddd50 --- /dev/null +++ b/backend.native/tests/codegen/propertyCallableReference/varExtension.kt @@ -0,0 +1,21 @@ +class A(y: Int) { + var x = y +} + +var A.z: Int + get() = this.x + set(value: Int) { + this.x = value + } + +fun main(args: Array) { + val p1 = A::z + val a = A(42) + p1.set(a, 117) + println(a.x) + println(p1.get(a)) + val p2 = a::z + p2.set(42) + println(a.x) + println(p2.get()) +} \ No newline at end of file diff --git a/backend.native/tests/codegen/propertyCallableReference/varModule.kt b/backend.native/tests/codegen/propertyCallableReference/varModule.kt new file mode 100644 index 00000000000..627076ca8f7 --- /dev/null +++ b/backend.native/tests/codegen/propertyCallableReference/varModule.kt @@ -0,0 +1,8 @@ +var x = 42 + +fun main(args: Array) { + val p = ::x + p.set(117) + println(x) + println(p.get()) +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/konan/internal/KPropertyImpl.kt b/runtime/src/main/kotlin/konan/internal/KPropertyImpl.kt new file mode 100644 index 00000000000..de920a14299 --- /dev/null +++ b/runtime/src/main/kotlin/konan/internal/KPropertyImpl.kt @@ -0,0 +1,63 @@ +package konan.internal + +import kotlin.reflect.KProperty0 +import kotlin.reflect.KProperty1 +import kotlin.reflect.KProperty2 +import kotlin.reflect.KMutableProperty0 +import kotlin.reflect.KMutableProperty1 +import kotlin.reflect.KMutableProperty2 + +@FixmeReflection +open class KProperty0Impl(override val name: String, val getter: () -> R): KProperty0 { + override fun get(): R { + return getter() + } + override fun invoke(): R { + return getter() + } + +} + +@FixmeReflection +open class KProperty1Impl(override val name: String, val getter: (T) -> R): KProperty1 { + override fun get(receiver: T): R { + return getter(receiver) + } + override fun invoke(receiver: T): R { + return getter(receiver) + } +} + +@FixmeReflection +open class KProperty2Impl(override val name: String, val getter: (T1, T2) -> R): KProperty2 { + override fun get(receiver1: T1, receiver2: T2): R { + return getter(receiver1, receiver2) + } + override fun invoke(receiver1: T1, receiver2: T2): R { + return getter(receiver1, receiver2) + } +} + +@FixmeReflection +class KMutableProperty0Impl(name: String, getter: () -> R, val setter: (R) -> Unit) + : KProperty0Impl(name, getter), KMutableProperty0 { + override fun set(value: R): Unit { + setter(value) + } +} + +@FixmeReflection +public class KMutableProperty1Impl(name: String, getter: (T) -> R, val setter: (T, R) -> Unit) + : KProperty1Impl(name, getter), KMutableProperty1 { + override fun set(receiver: T, value: R): Unit { + setter(receiver, value) + } +} + +@FixmeReflection +public class KMutableProperty2Impl(name: String, getter: (T1, T2) -> R, val setter: (T1, T2, R) -> Unit) + : KProperty2Impl(name, getter), KMutableProperty2 { + override fun set(receiver1: T1, receiver2: T2, value: R): Unit { + setter(receiver1, receiver2, value) + } +} diff --git a/runtime/src/main/kotlin/kotlin/Function.kt b/runtime/src/main/kotlin/kotlin/Function.kt index 8c46cd9d69d..b640706adc2 100644 --- a/runtime/src/main/kotlin/kotlin/Function.kt +++ b/runtime/src/main/kotlin/kotlin/Function.kt @@ -5,4 +5,5 @@ package kotlin * * @param R return type of the function. */ +@FixmeReflection public interface Function diff --git a/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt b/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt index e4604877c36..97b734a5dfd 100644 --- a/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt +++ b/runtime/src/main/kotlin/kotlin/reflect/KProperty.kt @@ -47,6 +47,46 @@ public interface KProperty : KCallable { // public interface Getter : Accessor, KFunction } +// +@FixmeReflection +public interface KProperty0 : kotlin.reflect.KProperty/* TODO , (T) -> R*/ { +// public abstract val getter: kotlin.reflect.KProperty1.Getter + + public abstract fun get(): R + public abstract operator fun invoke(): R + +// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any? +// +// public interface Getter : kotlin.reflect.KProperty.Getter, (T) -> R { +// } +} + +@FixmeReflection +public interface KProperty1 : kotlin.reflect.KProperty/* TODO , (T) -> R*/ { +// public abstract val getter: kotlin.reflect.KProperty1.Getter + + public abstract fun get(receiver: T): R + public abstract operator fun invoke(receiver: T): R + +// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any? +// +// public interface Getter : kotlin.reflect.KProperty.Getter, (T) -> R { +// } +} + +@FixmeReflection +public interface KProperty2 : kotlin.reflect.KProperty/* TODO , (T) -> R*/ { +// public abstract val getter: kotlin.reflect.KProperty1.Getter + + public abstract fun get(receiver1: T1, receiver2: T2): R + public abstract operator fun invoke(receiver1: T1, receiver2: T2): R + +// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any? +// +// public interface Getter : kotlin.reflect.KProperty.Getter, (T) -> R { +// } +} + /** * Represents a property declared as a `var`. */ @@ -62,6 +102,16 @@ public interface KMutableProperty : KProperty { } @FixmeReflection -public class KPropertyImpl(override val name: String) : KProperty { +public interface KMutableProperty0 : KProperty0, KMutableProperty { + public abstract fun set(value: R) +} +@FixmeReflection +public interface KMutableProperty1 : KProperty1, KMutableProperty { + public abstract fun set(receiver: T, value: R) +} + +@FixmeReflection +public interface KMutableProperty2 : KProperty2, KMutableProperty { + public abstract fun set(receiver1: T1, receiver2: T2, value: R) } \ No newline at end of file