Delegated implementations for functions and extension functions.
This commit is contained in:
committed by
Dmitry Petrov
parent
2438876173
commit
d27f22ae0e
+1
-1
@@ -51,7 +51,7 @@ fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: R
|
|||||||
IrGetObjectValueImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
|
IrGetObjectValueImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
|
||||||
receiver.classQualifier.descriptor)
|
receiver.classQualifier.descriptor)
|
||||||
is ExtensionReceiver ->
|
is ExtensionReceiver ->
|
||||||
IrGetExtensionReceiverImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset, receiver.type,
|
IrGetExtensionReceiverImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset,
|
||||||
receiver.declarationDescriptor.extensionReceiverParameter!!)
|
receiver.declarationDescriptor.extensionReceiverParameter!!)
|
||||||
else ->
|
else ->
|
||||||
TODO("Receiver: ${receiver.javaClass.simpleName}")
|
TODO("Receiver: ${receiver.javaClass.simpleName}")
|
||||||
|
|||||||
@@ -16,12 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi2ir.generators
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl
|
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetVariableImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrOperator
|
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||||
@@ -29,6 +28,8 @@ import org.jetbrains.kotlin.psi.KtParameter
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import java.lang.AssertionError
|
||||||
|
|
||||||
class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator {
|
class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator {
|
||||||
override val context: GeneratorContext get() = declarationGenerator.context
|
override val context: GeneratorContext get() = declarationGenerator.context
|
||||||
@@ -58,18 +59,28 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
|||||||
|
|
||||||
private fun generateMembersDeclaredInSupertypeList(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
private fun generateMembersDeclaredInSupertypeList(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
||||||
ktClassOrObject.getSuperTypeList()?.let { ktSuperTypeList ->
|
ktClassOrObject.getSuperTypeList()?.let { ktSuperTypeList ->
|
||||||
|
val delegatedMembers = irClass.descriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors(DescriptorKindFilter.CALLABLES)
|
||||||
|
.filterIsInstance<CallableMemberDescriptor>()
|
||||||
|
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
|
||||||
|
if (delegatedMembers.isEmpty()) return
|
||||||
|
|
||||||
for (ktEntry in ktSuperTypeList.entries) {
|
for (ktEntry in ktSuperTypeList.entries) {
|
||||||
if (ktEntry is KtDelegatedSuperTypeEntry) {
|
if (ktEntry is KtDelegatedSuperTypeEntry) {
|
||||||
generateDelegatedImplementationMembers(irClass, ktEntry)
|
generateDelegatedImplementationMembers(irClass, ktEntry, delegatedMembers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDelegatedImplementationMembers(irClass: IrClassImpl, ktEntry: KtDelegatedSuperTypeEntry) {
|
private fun generateDelegatedImplementationMembers(irClass: IrClassImpl, ktEntry: KtDelegatedSuperTypeEntry,
|
||||||
|
delegatedMembers: List<CallableMemberDescriptor>) {
|
||||||
val ktDelegateExpression = ktEntry.delegateExpression!!
|
val ktDelegateExpression = ktEntry.delegateExpression!!
|
||||||
val delegateType = getInferredTypeWithImplicitCastsOrFail(ktDelegateExpression)
|
val delegateType = getInferredTypeWithImplicitCastsOrFail(ktDelegateExpression)
|
||||||
val superType = getOrFail(BindingContext.TYPE, ktEntry.typeReference!!)
|
val superType = getOrFail(BindingContext.TYPE, ktEntry.typeReference!!)
|
||||||
|
val superTypeConstructorDescriptor = superType.constructor.declarationDescriptor
|
||||||
|
val superClass = superTypeConstructorDescriptor as? ClassDescriptor ?:
|
||||||
|
throw AssertionError("Unexpected supertype constructor for delegation: $superTypeConstructorDescriptor")
|
||||||
val delegateDescriptor = IrImplementingDelegateDescriptorImpl(irClass.descriptor, delegateType, superType)
|
val delegateDescriptor = IrImplementingDelegateDescriptorImpl(irClass.descriptor, delegateType, superType)
|
||||||
val irDelegate = IrDelegateImpl(ktDelegateExpression.startOffset, ktDelegateExpression.endOffset, IrDeclarationOrigin.DELEGATE,
|
val irDelegate = IrDelegateImpl(ktDelegateExpression.startOffset, ktDelegateExpression.endOffset, IrDeclarationOrigin.DELEGATE,
|
||||||
delegateDescriptor)
|
delegateDescriptor)
|
||||||
@@ -77,7 +88,51 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
|||||||
irDelegate.initializer = bodyGenerator.generatePropertyInitializerBody(ktDelegateExpression)
|
irDelegate.initializer = bodyGenerator.generatePropertyInitializerBody(ktDelegateExpression)
|
||||||
irClass.addMember(irDelegate)
|
irClass.addMember(irDelegate)
|
||||||
|
|
||||||
// TODO add delegated members
|
for (delegatedMember in delegatedMembers) {
|
||||||
|
val overriddenMember = delegatedMember.overriddenDescriptors.find { it.containingDeclaration.original == superClass.original }
|
||||||
|
if (overriddenMember != null) {
|
||||||
|
generateDelegatedMember(irClass, irDelegate, delegatedMember, overriddenMember)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateDelegatedMember(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegatedMember: CallableMemberDescriptor, overriddenMember: CallableMemberDescriptor) {
|
||||||
|
when (delegatedMember) {
|
||||||
|
is FunctionDescriptor ->
|
||||||
|
generateDelegatedFunction(irClass, irDelegate, delegatedMember, overriddenMember as FunctionDescriptor)
|
||||||
|
is PropertyDescriptor ->
|
||||||
|
generateDelegatedProperty(irClass, irDelegate, delegatedMember, overriddenMember as PropertyDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateDelegatedProperty(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: PropertyDescriptor, overridden: PropertyDescriptor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateDelegatedFunction(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor) {
|
||||||
|
val irFunction = IrFunctionImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated)
|
||||||
|
val irBlockBody = IrBlockBodyImpl(irDelegate.startOffset, irDelegate.endOffset)
|
||||||
|
|
||||||
|
val returnType = overridden.returnType!!
|
||||||
|
val irCall = IrCallImpl(irDelegate.startOffset, irDelegate.endOffset, returnType, overridden)
|
||||||
|
irCall.dispatchReceiver = IrGetVariableImpl(irDelegate.startOffset, irDelegate.endOffset, irDelegate.descriptor)
|
||||||
|
irCall.extensionReceiver = delegated.extensionReceiverParameter?.let { extensionReceiver ->
|
||||||
|
IrGetExtensionReceiverImpl(irDelegate.startOffset, irDelegate.endOffset, extensionReceiver)
|
||||||
|
}
|
||||||
|
irCall.mapValueParameters { overriddenValueParameter ->
|
||||||
|
val delegatedValueParameter = delegated.valueParameters[overriddenValueParameter.index]
|
||||||
|
IrGetVariableImpl(irDelegate.startOffset, irDelegate.endOffset, delegatedValueParameter)
|
||||||
|
}
|
||||||
|
if (KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType)) {
|
||||||
|
irBlockBody.addStatement(irCall)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
irBlockBody.addStatement(IrReturnImpl(irDelegate.startOffset, irDelegate.endOffset, context.builtIns.nothingType, delegated, irCall))
|
||||||
|
}
|
||||||
|
|
||||||
|
irFunction.body = irBlockBody
|
||||||
|
irClass.addMember(irFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateAdditionalMembersForDataClass(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
private fun generateAdditionalMembersForDataClass(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
||||||
|
|||||||
+1
-5
@@ -285,11 +285,7 @@ class StatementGenerator(
|
|||||||
)
|
)
|
||||||
is CallableDescriptor -> {
|
is CallableDescriptor -> {
|
||||||
val extensionReceiver = referenceTarget.extensionReceiverParameter ?: TODO("No extension receiver: $referenceTarget")
|
val extensionReceiver = referenceTarget.extensionReceiverParameter ?: TODO("No extension receiver: $referenceTarget")
|
||||||
IrGetExtensionReceiverImpl(
|
IrGetExtensionReceiverImpl(expression.startOffset, expression.endOffset, extensionReceiver)
|
||||||
expression.startOffset, expression.endOffset,
|
|
||||||
extensionReceiver.type,
|
|
||||||
extensionReceiver
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
else ->
|
else ->
|
||||||
error("Expected this or receiver: $referenceTarget")
|
error("Expected this or receiver: $referenceTarget")
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ enum class IrDeclarationOrigin {
|
|||||||
DEFINED,
|
DEFINED,
|
||||||
DELEGATE,
|
DELEGATE,
|
||||||
DELEGATED_PROPERTY_ACCESSOR,
|
DELEGATED_PROPERTY_ACCESSOR,
|
||||||
|
DELEGATED_MEMBER,
|
||||||
CLASS_FOR_ENUM_ENTRY,
|
CLASS_FOR_ENUM_ENTRY,
|
||||||
ENUM_CLASS_SPECIAL_MEMBER,
|
ENUM_CLASS_SPECIAL_MEMBER,
|
||||||
GENERATED_DATA_CLASS_MEMBER,
|
GENERATED_DATA_CLASS_MEMBER,
|
||||||
|
|||||||
+2
-4
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.ir.expressions
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
interface IrGetExtensionReceiver : IrDeclarationReference, IrExpressionWithCopy {
|
interface IrGetExtensionReceiver : IrDeclarationReference, IrExpressionWithCopy {
|
||||||
override val descriptor: ReceiverParameterDescriptor
|
override val descriptor: ReceiverParameterDescriptor
|
||||||
@@ -29,12 +28,11 @@ interface IrGetExtensionReceiver : IrDeclarationReference, IrExpressionWithCopy
|
|||||||
class IrGetExtensionReceiverImpl(
|
class IrGetExtensionReceiverImpl(
|
||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
type: KotlinType,
|
|
||||||
descriptor: ReceiverParameterDescriptor
|
descriptor: ReceiverParameterDescriptor
|
||||||
) : IrTerminalDeclarationReferenceBase<ReceiverParameterDescriptor>(startOffset, endOffset, type, descriptor), IrGetExtensionReceiver {
|
) : IrTerminalDeclarationReferenceBase<ReceiverParameterDescriptor>(startOffset, endOffset, descriptor.type, descriptor), IrGetExtensionReceiver {
|
||||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||||
visitor.visitGetExtensionReceiver(this, data)
|
visitor.visitGetExtensionReceiver(this, data)
|
||||||
|
|
||||||
override fun copy(): IrGetExtensionReceiver =
|
override fun copy(): IrGetExtensionReceiver =
|
||||||
IrGetExtensionReceiverImpl(startOffset, endOffset, type, descriptor)
|
IrGetExtensionReceiverImpl(startOffset, endOffset, descriptor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
interface IBase
|
interface IBase {
|
||||||
object BaseImpl : IBase
|
fun foo(x: Int, s: String)
|
||||||
|
fun bar(): Int
|
||||||
|
fun String.qux()
|
||||||
|
}
|
||||||
|
|
||||||
|
object BaseImpl : IBase {
|
||||||
|
override fun foo(x: Int, s: String) {}
|
||||||
|
override fun bar(): Int = 42
|
||||||
|
override fun String.qux() {}
|
||||||
|
}
|
||||||
|
|
||||||
interface IOther
|
interface IOther
|
||||||
fun otherImpl(): IOther = object : IOther {}
|
fun otherImpl(): IOther = object : IOther {}
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
FILE /delegatedImplementation.kt
|
FILE /delegatedImplementation.kt
|
||||||
CLASS INTERFACE IBase
|
CLASS INTERFACE IBase
|
||||||
|
FUN public abstract fun foo(/*0*/ x: kotlin.Int, /*1*/ s: kotlin.String): kotlin.Unit
|
||||||
|
FUN public abstract fun bar(): kotlin.Int
|
||||||
|
FUN public abstract fun kotlin.String.qux(): kotlin.Unit
|
||||||
CLASS OBJECT BaseImpl
|
CLASS OBJECT BaseImpl
|
||||||
CONSTRUCTOR private constructor BaseImpl()
|
CONSTRUCTOR private constructor BaseImpl()
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
INSTANCE_INITIALIZER_CALL classDescriptor=BaseImpl
|
INSTANCE_INITIALIZER_CALL classDescriptor=BaseImpl
|
||||||
|
FUN public open override /*1*/ fun foo(/*0*/ x: kotlin.Int, /*1*/ s: kotlin.String): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
FUN public open override /*1*/ fun bar(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=bar
|
||||||
|
CONST Int type=kotlin.Int value='42'
|
||||||
|
FUN public open override /*1*/ fun kotlin.String.qux(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
CLASS INTERFACE IOther
|
CLASS INTERFACE IOther
|
||||||
FUN public fun otherImpl(): IOther
|
FUN public fun otherImpl(): IOther
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
@@ -21,6 +32,22 @@ FILE /delegatedImplementation.kt
|
|||||||
DELEGATE val `Test1$IBase$delegate`: BaseImpl
|
DELEGATE val `Test1$IBase$delegate`: BaseImpl
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
GET_OBJECT BaseImpl type=BaseImpl
|
GET_OBJECT BaseImpl type=BaseImpl
|
||||||
|
FUN public open override /*1*/ /*delegation*/ fun foo(/*0*/ x: kotlin.Int, /*1*/ s: kotlin.String): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .foo type=kotlin.Unit operator=null
|
||||||
|
$this: GET_VAR Test1$IBase$delegate type=BaseImpl operator=null
|
||||||
|
x: GET_VAR x type=kotlin.Int operator=null
|
||||||
|
s: GET_VAR s type=kotlin.String operator=null
|
||||||
|
FUN public open override /*1*/ /*delegation*/ fun bar(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=bar
|
||||||
|
CALL .bar type=kotlin.Int operator=null
|
||||||
|
$this: GET_VAR Test1$IBase$delegate type=BaseImpl operator=null
|
||||||
|
FUN public open override /*1*/ /*delegation*/ fun kotlin.String.qux(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .qux type=kotlin.Unit operator=null
|
||||||
|
$this: GET_VAR Test1$IBase$delegate type=BaseImpl operator=null
|
||||||
|
$receiver: $RECEIVER of: qux type=kotlin.String
|
||||||
CLASS CLASS Test2
|
CLASS CLASS Test2
|
||||||
CONSTRUCTOR public constructor Test2()
|
CONSTRUCTOR public constructor Test2()
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
@@ -28,6 +55,22 @@ FILE /delegatedImplementation.kt
|
|||||||
DELEGATE val `Test2$IBase$delegate`: BaseImpl
|
DELEGATE val `Test2$IBase$delegate`: BaseImpl
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
GET_OBJECT BaseImpl type=BaseImpl
|
GET_OBJECT BaseImpl type=BaseImpl
|
||||||
|
FUN public open override /*1*/ /*delegation*/ fun foo(/*0*/ x: kotlin.Int, /*1*/ s: kotlin.String): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .foo type=kotlin.Unit operator=null
|
||||||
|
$this: GET_VAR Test2$IBase$delegate type=BaseImpl operator=null
|
||||||
|
x: GET_VAR x type=kotlin.Int operator=null
|
||||||
|
s: GET_VAR s type=kotlin.String operator=null
|
||||||
|
FUN public open override /*1*/ /*delegation*/ fun bar(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=bar
|
||||||
|
CALL .bar type=kotlin.Int operator=null
|
||||||
|
$this: GET_VAR Test2$IBase$delegate type=BaseImpl operator=null
|
||||||
|
FUN public open override /*1*/ /*delegation*/ fun kotlin.String.qux(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .qux type=kotlin.Unit operator=null
|
||||||
|
$this: GET_VAR Test2$IBase$delegate type=BaseImpl operator=null
|
||||||
|
$receiver: $RECEIVER of: qux type=kotlin.String
|
||||||
DELEGATE val `Test2$IOther$delegate`: IOther
|
DELEGATE val `Test2$IOther$delegate`: IOther
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
CALL .otherImpl type=IOther operator=null
|
CALL .otherImpl type=IOther operator=null
|
||||||
|
|||||||
Reference in New Issue
Block a user