Delegated implementations for functions and extension functions.

This commit is contained in:
Dmitry Petrov
2016-09-01 19:39:46 +03:00
committed by Dmitry Petrov
parent 2438876173
commit d27f22ae0e
7 changed files with 121 additions and 19 deletions
@@ -51,7 +51,7 @@ fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: R
IrGetObjectValueImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
receiver.classQualifier.descriptor)
is ExtensionReceiver ->
IrGetExtensionReceiverImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset, receiver.type,
IrGetExtensionReceiverImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset,
receiver.declarationDescriptor.extensionReceiverParameter!!)
else ->
TODO("Receiver: ${receiver.javaClass.simpleName}")
@@ -16,12 +16,11 @@
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.descriptors.IrImplementingDelegateDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.expressions.IrGetVariableImpl
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
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.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import java.lang.AssertionError
class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator {
override val context: GeneratorContext get() = declarationGenerator.context
@@ -58,18 +59,28 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
private fun generateMembersDeclaredInSupertypeList(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
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) {
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 delegateType = getInferredTypeWithImplicitCastsOrFail(ktDelegateExpression)
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 irDelegate = IrDelegateImpl(ktDelegateExpression.startOffset, ktDelegateExpression.endOffset, IrDeclarationOrigin.DELEGATE,
delegateDescriptor)
@@ -77,7 +88,51 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
irDelegate.initializer = bodyGenerator.generatePropertyInitializerBody(ktDelegateExpression)
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) {
@@ -285,11 +285,7 @@ class StatementGenerator(
)
is CallableDescriptor -> {
val extensionReceiver = referenceTarget.extensionReceiverParameter ?: TODO("No extension receiver: $referenceTarget")
IrGetExtensionReceiverImpl(
expression.startOffset, expression.endOffset,
extensionReceiver.type,
extensionReceiver
)
IrGetExtensionReceiverImpl(expression.startOffset, expression.endOffset, extensionReceiver)
}
else ->
error("Expected this or receiver: $referenceTarget")
@@ -47,6 +47,7 @@ enum class IrDeclarationOrigin {
DEFINED,
DELEGATE,
DELEGATED_PROPERTY_ACCESSOR,
DELEGATED_MEMBER,
CLASS_FOR_ENUM_ENTRY,
ENUM_CLASS_SPECIAL_MEMBER,
GENERATED_DATA_CLASS_MEMBER,
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType
interface IrGetExtensionReceiver : IrDeclarationReference, IrExpressionWithCopy {
override val descriptor: ReceiverParameterDescriptor
@@ -29,12 +28,11 @@ interface IrGetExtensionReceiver : IrDeclarationReference, IrExpressionWithCopy
class IrGetExtensionReceiverImpl(
startOffset: Int,
endOffset: Int,
type: KotlinType,
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 =
visitor.visitGetExtensionReceiver(this, data)
override fun copy(): IrGetExtensionReceiver =
IrGetExtensionReceiverImpl(startOffset, endOffset, type, descriptor)
IrGetExtensionReceiverImpl(startOffset, endOffset, descriptor)
}
@@ -1,5 +1,14 @@
interface IBase
object BaseImpl : IBase
interface 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
fun otherImpl(): IOther = object : IOther {}
@@ -1,9 +1,20 @@
FILE /delegatedImplementation.kt
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
CONSTRUCTOR private constructor BaseImpl()
BLOCK_BODY
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
FUN public fun otherImpl(): IOther
BLOCK_BODY
@@ -21,6 +32,22 @@ FILE /delegatedImplementation.kt
DELEGATE val `Test1$IBase$delegate`: BaseImpl
EXPRESSION_BODY
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
CONSTRUCTOR public constructor Test2()
BLOCK_BODY
@@ -28,6 +55,22 @@ FILE /delegatedImplementation.kt
DELEGATE val `Test2$IBase$delegate`: BaseImpl
EXPRESSION_BODY
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
EXPRESSION_BODY
CALL .otherImpl type=IOther operator=null