Initial support of function callable references
This commit is contained in:
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.DescriptorFactory
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
|
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
@@ -195,6 +196,11 @@ class PropertyReferenceCodegen(
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun generateCallableReferenceSignature(iv: InstructionAdapter, callable: CallableDescriptor, state: GenerationState) {
|
fun generateCallableReferenceSignature(iv: InstructionAdapter, callable: CallableDescriptor, state: GenerationState) {
|
||||||
|
iv.aconst(getSignatureString(callable, state))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getSignatureString(callable: CallableDescriptor, state: GenerationState): String {
|
||||||
if (callable is LocalVariableDescriptor) {
|
if (callable is LocalVariableDescriptor) {
|
||||||
val asmType = state.bindingContext.get(CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, callable)
|
val asmType = state.bindingContext.get(CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, callable)
|
||||||
?: throw AssertionError("No delegated property metadata owner for $callable")
|
?: throw AssertionError("No delegated property metadata owner for $callable")
|
||||||
@@ -203,8 +209,7 @@ class PropertyReferenceCodegen(
|
|||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
throw AssertionError("Local delegated property is not found in $asmType: $callable")
|
throw AssertionError("Local delegated property is not found in $asmType: $callable")
|
||||||
}
|
}
|
||||||
iv.aconst("<v#$index>") // v = "variable"
|
return "<v#$index>"
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val accessor = when (callable) {
|
val accessor = when (callable) {
|
||||||
@@ -218,7 +223,7 @@ class PropertyReferenceCodegen(
|
|||||||
}
|
}
|
||||||
val declaration = DescriptorUtils.unwrapFakeOverride(accessor).original
|
val declaration = DescriptorUtils.unwrapFakeOverride(accessor).original
|
||||||
val method = state.typeMapper.mapAsmMethod(declaration)
|
val method = state.typeMapper.mapAsmMethod(declaration)
|
||||||
iv.aconst(method.name + method.descriptor)
|
return method.name + method.descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|||||||
+24
@@ -87,6 +87,30 @@ fun ClassDescriptor.getFunction(name: String, types: List<KotlinType>): Function
|
|||||||
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single().substitute(typeSubstitutor)!!
|
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single().substitute(typeSubstitutor)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ClassDescriptor.getStaticFunction(name: String, types: List<KotlinType>): FunctionDescriptor {
|
||||||
|
val typeSubstitutor = TypeSubstitutor.create(
|
||||||
|
declaredTypeParameters
|
||||||
|
.withIndex()
|
||||||
|
.associateBy({ it.value.typeConstructor }, { TypeProjectionImpl(types[it.index]) })
|
||||||
|
)
|
||||||
|
return staticScope
|
||||||
|
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single().substitute(typeSubstitutor)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ClassDescriptor.getProperty(name: String, types: List<KotlinType>): PropertyDescriptor {
|
||||||
|
val typeSubstitutor = TypeSubstitutor.create(
|
||||||
|
declaredTypeParameters
|
||||||
|
.withIndex()
|
||||||
|
.associateBy({ it.value.typeConstructor }, { TypeProjectionImpl(types[it.index]) })
|
||||||
|
)
|
||||||
|
return unsubstitutedMemberScope
|
||||||
|
.getContributedVariables(
|
||||||
|
Name.identifier(name),
|
||||||
|
NoLookupLocation.FROM_BACKEND
|
||||||
|
).single().substitute(typeSubstitutor) as PropertyDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val KotlinType.isFunctionOrKFunctionType: Boolean
|
val KotlinType.isFunctionOrKFunctionType: Boolean
|
||||||
get() {
|
get() {
|
||||||
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
||||||
|
|||||||
@@ -175,6 +175,8 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
|
|||||||
|
|
||||||
val kFunctionImpl = calc { symbolTable.referenceClass(context.reflectionTypes.kFunctionImpl) }
|
val kFunctionImpl = calc { symbolTable.referenceClass(context.reflectionTypes.kFunctionImpl) }
|
||||||
|
|
||||||
|
val functionReference = calc { symbolTable.referenceClass(context.getInternalClass("FunctionReference")) }
|
||||||
|
|
||||||
val kProperty0Impl = calc { symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl) }
|
val kProperty0Impl = calc { symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl) }
|
||||||
val kProperty1Impl = calc { symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl) }
|
val kProperty1Impl = calc { symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl) }
|
||||||
val kProperty2Impl = calc { symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl) }
|
val kProperty2Impl = calc { symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl) }
|
||||||
|
|||||||
+1
-1
@@ -239,7 +239,7 @@ fun IrConstructor.callsSuper(): Boolean {
|
|||||||
return callsSuper
|
return callsSuper
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ParameterDescriptor.copyAsValueParameter(newOwner: CallableDescriptor, index: Int) = when (this) {
|
fun ParameterDescriptor.copyAsValueParameter(newOwner: CallableDescriptor, index: Int, name: Name = this.name) = when (this) {
|
||||||
is ValueParameterDescriptor -> this.copy(newOwner, name, index)
|
is ValueParameterDescriptor -> this.copy(newOwner, name, index)
|
||||||
is ReceiverParameterDescriptor -> ValueParameterDescriptorImpl(
|
is ReceiverParameterDescriptor -> ValueParameterDescriptorImpl(
|
||||||
containingDeclaration = newOwner,
|
containingDeclaration = newOwner,
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class JvmLower(val context: JvmBackendContext) {
|
|||||||
},
|
},
|
||||||
Visibilities.PUBLIC //TODO properly figure out visibility
|
Visibilities.PUBLIC //TODO properly figure out visibility
|
||||||
).runOnFilePostfix(irFile)
|
).runOnFilePostfix(irFile)
|
||||||
|
CallableReferenceLowering(context).lower(irFile)
|
||||||
|
|
||||||
EnumClassLowering(context).runOnFilePostfix(irFile)
|
EnumClassLowering(context).runOnFilePostfix(irFile)
|
||||||
//Should be before SyntheticAccessorLowering cause of synthetic accessor for companion constructor
|
//Should be before SyntheticAccessorLowering cause of synthetic accessor for companion constructor
|
||||||
|
|||||||
+19
-7
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicFunction
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicFunction
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.lower.CrIrType
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil.*
|
import org.jetbrains.kotlin.codegen.AsmUtil.*
|
||||||
@@ -20,6 +21,7 @@ import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty
|
|||||||
import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq
|
import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq
|
||||||
import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump
|
import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump
|
||||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||||
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
@@ -949,13 +951,19 @@ class ExpressionCodegen(
|
|||||||
assert(classReference is IrGetClass)
|
assert(classReference is IrGetClass)
|
||||||
JavaClassProperty.generateImpl(mv, gen((classReference as IrGetClass).argument, data))
|
JavaClassProperty.generateImpl(mv, gen((classReference as IrGetClass).argument, data))
|
||||||
} else {
|
} else {
|
||||||
val type = classReference.classType.toKotlinType()
|
val classType = classReference.classType
|
||||||
if (TypeUtils.isTypeParameter(type)) {
|
if (classType is CrIrType) {
|
||||||
assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
|
putJavaLangClassInstance(mv, classType.type)
|
||||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
return
|
||||||
}
|
} else {
|
||||||
|
val type = classType.toKotlinType()
|
||||||
|
if (TypeUtils.isTypeParameter(type)) {
|
||||||
|
assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
|
||||||
|
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
||||||
|
}
|
||||||
|
|
||||||
putJavaLangClassInstance(mv, typeMapper.mapType(type))
|
putJavaLangClassInstance(mv, typeMapper.mapType(type))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wrapIntoKClass) {
|
if (wrapIntoKClass) {
|
||||||
@@ -1025,7 +1033,7 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
// We should inline callable containing reified type parameters even if inline is disabled
|
// We should inline callable containing reified type parameters even if inline is disabled
|
||||||
// because they may contain something to reify and straight call will probably fail at runtime
|
// because they may contain something to reify and straight call will probably fail at runtime
|
||||||
val isInline = (!state.isInlineDisabled || InlineUtil.containsReifiedTypeParameters(descriptor)) && (InlineUtil.isInline(descriptor) || InlineUtil.isArrayConstructorWithLambda(descriptor))
|
val isInline = descriptor.isInlineCall(state)
|
||||||
|
|
||||||
if (!isInline) return IrCallGenerator.DefaultCallGenerator
|
if (!isInline) return IrCallGenerator.DefaultCallGenerator
|
||||||
|
|
||||||
@@ -1130,3 +1138,7 @@ fun DefaultCallArgs.generateOnStackIfNeeded(callGenerator: IrCallGenerator, isCo
|
|||||||
}
|
}
|
||||||
return toInts.isNotEmpty()
|
return toInts.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun CallableDescriptor.isInlineCall(state: GenerationState) =
|
||||||
|
(!state.isInlineDisabled || InlineUtil.containsReifiedTypeParameters(this)) &&
|
||||||
|
(InlineUtil.isInline(this) || InlineUtil.isArrayConstructorWithLambda(this))
|
||||||
+728
@@ -0,0 +1,728 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.createFakeOverrideDescriptor
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineCall
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
|
import org.jetbrains.kotlin.ir.types.toIrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
|
//Hack implementation to support CR java types in lower
|
||||||
|
class CrIrType(val type: Type) : IrType {
|
||||||
|
override val annotations = emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
//Originally was copied from K/Native
|
||||||
|
class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||||
|
|
||||||
|
object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL")
|
||||||
|
|
||||||
|
private var functionReferenceCount = 0
|
||||||
|
|
||||||
|
private val inlineLambdaReferences = mutableSetOf<IrFunctionReference>()
|
||||||
|
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
val descriptor = expression.descriptor
|
||||||
|
if (descriptor.isInlineCall(context.state)) {
|
||||||
|
//TODO: more wise filtering
|
||||||
|
descriptor.valueParameters.map { valueParameter ->
|
||||||
|
if (InlineUtil.isInlineParameter(valueParameter)) {
|
||||||
|
expression.getValueArgument(valueParameter.index)?.let {
|
||||||
|
if (isInlineIrExpression(it)) {
|
||||||
|
(it as IrBlock).statements.filterIsInstance<IrFunctionReference>().forEach { reference ->
|
||||||
|
inlineLambdaReferences.add(reference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: clean
|
||||||
|
return super.visitCall(expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
if (!expression.type.toKotlinType().isFunctionOrKFunctionType || inlineLambdaReferences.contains(expression)) {
|
||||||
|
// Not a subject of this lowering.
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
|
val loweredFunctionReference = FunctionReferenceBuilder(currentScope!!.scope.scopeOwner, expression).build()
|
||||||
|
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset)
|
||||||
|
return irBuilder.irBlock(expression) {
|
||||||
|
+loweredFunctionReference.functionReferenceClass
|
||||||
|
+irCall(loweredFunctionReference.functionReferenceConstructor.symbol).apply {
|
||||||
|
expression.getArguments().forEachIndexed { index, argument ->
|
||||||
|
putValueArgument(index, argument.second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BuiltFunctionReference(
|
||||||
|
val functionReferenceClass: IrClass,
|
||||||
|
val functionReferenceConstructor: IrConstructor
|
||||||
|
)
|
||||||
|
|
||||||
|
private val kotlinPackageScope = context.builtIns.builtInsPackageScope
|
||||||
|
|
||||||
|
private val continuationClassDescriptor = context.getClass(FqName("kotlin.coroutines.experimental.Continuation"))
|
||||||
|
|
||||||
|
//private val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||||
|
|
||||||
|
private inner class FunctionReferenceBuilder(
|
||||||
|
val containingDeclaration: DeclarationDescriptor,
|
||||||
|
val irFunctionReference: IrFunctionReference
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val functionDescriptor = irFunctionReference.descriptor
|
||||||
|
private val functionParameters = functionDescriptor.explicitParameters
|
||||||
|
private val boundFunctionParameters = irFunctionReference.getArguments().map { it.first }
|
||||||
|
private val unboundFunctionParameters = functionParameters - boundFunctionParameters
|
||||||
|
|
||||||
|
private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl
|
||||||
|
private lateinit var functionReferenceClass: IrClassImpl
|
||||||
|
private lateinit var functionReferenceThis: IrValueParameterSymbol
|
||||||
|
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
||||||
|
|
||||||
|
private val functionReference = context.ir.symbols.functionReference
|
||||||
|
|
||||||
|
fun build(): BuiltFunctionReference {
|
||||||
|
val startOffset = irFunctionReference.startOffset
|
||||||
|
val endOffset = irFunctionReference.endOffset
|
||||||
|
|
||||||
|
val returnType = functionDescriptor.returnType!!
|
||||||
|
val superTypes: MutableList<KotlinType> = mutableListOf(
|
||||||
|
functionReference.descriptor.defaultType
|
||||||
|
)
|
||||||
|
|
||||||
|
val numberOfParameters = unboundFunctionParameters.size
|
||||||
|
val functionClassDescriptor = context.getClass(FqName("kotlin.jvm.functions.Function$numberOfParameters"))
|
||||||
|
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
||||||
|
val functionClassTypeParameters = functionParameterTypes + returnType
|
||||||
|
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters)
|
||||||
|
|
||||||
|
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||||
|
var suspendFunctionClassTypeParameters: List<KotlinType>? = null
|
||||||
|
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
|
||||||
|
if (lastParameterType != null && TypeUtils.getClassDescriptor(lastParameterType) == continuationClassDescriptor) {
|
||||||
|
// If the last parameter is Continuation<> inherit from SuspendFunction.
|
||||||
|
suspendFunctionClassDescriptor = kotlinPackageScope.getContributedClassifier(
|
||||||
|
Name.identifier("SuspendFunction${numberOfParameters - 1}"), NoLookupLocation.FROM_BACKEND
|
||||||
|
) as ClassDescriptor
|
||||||
|
suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) + lastParameterType.arguments.single().type
|
||||||
|
superTypes += suspendFunctionClassDescriptor.defaultType.replace(suspendFunctionClassTypeParameters)
|
||||||
|
}
|
||||||
|
|
||||||
|
functionReferenceClassDescriptor = ClassDescriptorImpl(
|
||||||
|
/* containingDeclaration = */ containingDeclaration,
|
||||||
|
/* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* kind = */ ClassKind.CLASS,
|
||||||
|
/* superTypes = */ superTypes,
|
||||||
|
/* source = */ /*TODO*/ (containingDeclaration as? DeclarationDescriptorWithSource)?.source ?: NO_SOURCE,
|
||||||
|
/* isExternal = */ false,
|
||||||
|
LockBasedStorageManager.NO_LOCKS
|
||||||
|
)
|
||||||
|
functionReferenceClass = IrClassImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
descriptor = functionReferenceClassDescriptor
|
||||||
|
)
|
||||||
|
|
||||||
|
val contributedDescriptors = mutableListOf<DeclarationDescriptor>()
|
||||||
|
val constructorBuilder = createConstructorBuilder()
|
||||||
|
functionReferenceClassDescriptor.initialize(
|
||||||
|
SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null
|
||||||
|
)
|
||||||
|
|
||||||
|
functionReferenceClass.createParameterDeclarations()
|
||||||
|
|
||||||
|
functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol
|
||||||
|
|
||||||
|
val invokeFunctionDescriptor = functionClassDescriptor.getFunction("invoke", functionClassTypeParameters)
|
||||||
|
|
||||||
|
val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionDescriptor)
|
||||||
|
val getSignatureBuilder =
|
||||||
|
createGetSignatureMethodBuilder(functionReference.owner.descriptor.getFunction("getSignature", emptyList()))
|
||||||
|
val getNameBuilder = createGetNameMethodBuilder(functionReference.owner.descriptor.getProperty("name", emptyList()))
|
||||||
|
val getOwnerBuilder = createGetOwnerMethodBuilder(functionReference.owner.descriptor.getFunction("getOwner", emptyList()))
|
||||||
|
|
||||||
|
val suspendInvokeMethodBuilder =
|
||||||
|
if (suspendFunctionClassDescriptor != null) {
|
||||||
|
val suspendInvokeFunctionDescriptor =
|
||||||
|
suspendFunctionClassDescriptor.getFunction("invoke", suspendFunctionClassTypeParameters!!)
|
||||||
|
createInvokeMethodBuilder(suspendInvokeFunctionDescriptor)
|
||||||
|
} else null
|
||||||
|
|
||||||
|
val inheritedScope = functionReference.descriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors().mapNotNull { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) }
|
||||||
|
.filterNot { it.name.asString() == "getSignature" || it.name.asString() == "name" || it.name.asString() == "getOwner" }
|
||||||
|
|
||||||
|
contributedDescriptors.addAll(
|
||||||
|
(
|
||||||
|
inheritedScope + invokeMethodBuilder.symbol.descriptor +
|
||||||
|
suspendInvokeMethodBuilder?.symbol?.descriptor + getSignatureBuilder.symbol.descriptor
|
||||||
|
).filterNotNull()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
constructorBuilder.initialize()
|
||||||
|
functionReferenceClass.declarations.add(constructorBuilder.ir)
|
||||||
|
|
||||||
|
invokeMethodBuilder.initialize()
|
||||||
|
functionReferenceClass.declarations.add(invokeMethodBuilder.ir)
|
||||||
|
|
||||||
|
getSignatureBuilder.initialize()
|
||||||
|
functionReferenceClass.declarations.add(getSignatureBuilder.ir)
|
||||||
|
|
||||||
|
getNameBuilder.initialize()
|
||||||
|
functionReferenceClass.declarations.add(getNameBuilder.ir)
|
||||||
|
|
||||||
|
getOwnerBuilder.initialize()
|
||||||
|
functionReferenceClass.declarations.add(getOwnerBuilder.ir)
|
||||||
|
|
||||||
|
suspendInvokeMethodBuilder?.let {
|
||||||
|
it.initialize()
|
||||||
|
functionReferenceClass.declarations.add(it.ir)
|
||||||
|
}
|
||||||
|
|
||||||
|
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.ir)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createConstructorBuilder() = object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||||
|
|
||||||
|
private val kFunctionRefConstructorSymbol =
|
||||||
|
functionReference.constructors.filter { it.descriptor.valueParameters.size == 2 }.single()
|
||||||
|
|
||||||
|
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||||
|
ClassConstructorDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* isPrimary = */ false,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun doInitialize() {
|
||||||
|
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||||
|
val constructorParameters = boundFunctionParameters.mapIndexed { index, parameter ->
|
||||||
|
parameter.copyAsValueParameter(descriptor, index, parameter.name)
|
||||||
|
}
|
||||||
|
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||||
|
descriptor.returnType = functionReferenceClassDescriptor.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildIr(): IrConstructor {
|
||||||
|
argumentToPropertiesMap = boundFunctionParameters.associate {
|
||||||
|
it to buildPropertyWithBackingField(it.name.safeName(), it.type, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val startOffset = irFunctionReference.startOffset
|
||||||
|
val endOffset = irFunctionReference.endOffset
|
||||||
|
return IrConstructorImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
symbol = symbol
|
||||||
|
).apply {
|
||||||
|
returnType = symbol.descriptor.returnType.toIrType()!!
|
||||||
|
|
||||||
|
val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset)
|
||||||
|
|
||||||
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
body = irBuilder.irBlockBody {
|
||||||
|
+IrDelegatingConstructorCallImpl(
|
||||||
|
startOffset, endOffset, context.irBuiltIns.unitType,
|
||||||
|
kFunctionRefConstructorSymbol, kFunctionRefConstructorSymbol.descriptor
|
||||||
|
).apply {
|
||||||
|
val const =
|
||||||
|
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, unboundFunctionParameters.size)
|
||||||
|
putValueArgument(0, const)
|
||||||
|
|
||||||
|
val irReceiver = valueParameters.firstOrNull()
|
||||||
|
val receiver = boundFunctionParameters.singleOrNull()
|
||||||
|
|
||||||
|
val receiverValue = receiver?.let {
|
||||||
|
irGet(irReceiver!!.symbol.owner)
|
||||||
|
} ?: irNull()
|
||||||
|
putValueArgument(1, receiverValue)
|
||||||
|
//TODO use receiver from base class
|
||||||
|
receiver?.let {
|
||||||
|
+irSetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[it]!!.owner, receiverValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, context.irBuiltIns.unitType)
|
||||||
|
// Save all arguments to fields.
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createInvokeMethodBuilder(superFunctionDescriptor: FunctionDescriptor) =
|
||||||
|
object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
|
|
||||||
|
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||||
|
SimpleFunctionDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* name = */ Name.identifier("invoke"),
|
||||||
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun doInitialize() {
|
||||||
|
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
||||||
|
val valueParameters = superFunctionDescriptor.valueParameters
|
||||||
|
.map { it.copyAsValueParameter(descriptor, it.index) }
|
||||||
|
|
||||||
|
descriptor.initialize(
|
||||||
|
/* receiverParameterType = */ null,
|
||||||
|
/* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter,
|
||||||
|
/* typeParameters = */ emptyList(),
|
||||||
|
/* unsubstitutedValueParameters = */ valueParameters,
|
||||||
|
/* unsubstitutedReturnType = */ superFunctionDescriptor.returnType,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* visibility = */ Visibilities.PUBLIC
|
||||||
|
).apply {
|
||||||
|
overriddenDescriptors += superFunctionDescriptor
|
||||||
|
isSuspend = superFunctionDescriptor.isSuspend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildIr(): IrSimpleFunction {
|
||||||
|
val startOffset = irFunctionReference.startOffset
|
||||||
|
val endOffset = irFunctionReference.endOffset
|
||||||
|
val ourSymbol = symbol
|
||||||
|
return IrFunctionImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
symbol = ourSymbol
|
||||||
|
).apply {
|
||||||
|
|
||||||
|
val function = this
|
||||||
|
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||||
|
returnType = ourSymbol.descriptor.returnType!!.toIrType()!!
|
||||||
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
|
+irReturn(
|
||||||
|
irCall(irFunctionReference.symbol).apply {
|
||||||
|
var unboundIndex = 0
|
||||||
|
val unboundArgsSet = unboundFunctionParameters.toSet()
|
||||||
|
functionParameters.forEach {
|
||||||
|
val argument =
|
||||||
|
if (!unboundArgsSet.contains(it))
|
||||||
|
// Bound parameter - read from field.
|
||||||
|
irGetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[it]!!.owner)
|
||||||
|
else {
|
||||||
|
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
||||||
|
// For suspend functions the last argument is continuation and it is implicit.
|
||||||
|
TODO()
|
||||||
|
// irCall(getContinuationSymbol,
|
||||||
|
// listOf(ourSymbol.descriptor.returnType!!))
|
||||||
|
else
|
||||||
|
irGet(valueParameters[unboundIndex++])
|
||||||
|
}
|
||||||
|
when (it) {
|
||||||
|
functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||||
|
functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument
|
||||||
|
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): IrFieldSymbol {
|
||||||
|
val fieldSymbol = IrFieldSymbolImpl(
|
||||||
|
JvmPropertyDescriptorImpl.createFinalField(
|
||||||
|
Name.identifier("this$0"), type, functionReferenceClassDescriptor,
|
||||||
|
Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val field = IrFieldImpl(
|
||||||
|
irFunctionReference.startOffset,
|
||||||
|
irFunctionReference.endOffset,
|
||||||
|
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
fieldSymbol,
|
||||||
|
type.toIrType()!!
|
||||||
|
)
|
||||||
|
|
||||||
|
functionReferenceClass.declarations.add(field)
|
||||||
|
return fieldSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGetNameMethodBuilder(superNameProperty: PropertyDescriptor) =
|
||||||
|
object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
|
|
||||||
|
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||||
|
PropertyDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
superNameProperty.modality,
|
||||||
|
superNameProperty.visibility,
|
||||||
|
false,
|
||||||
|
/* name = */ superNameProperty.name,
|
||||||
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE,
|
||||||
|
false, false, false, false, false, false
|
||||||
|
).let { property ->
|
||||||
|
|
||||||
|
property.overriddenDescriptors += superNameProperty
|
||||||
|
PropertyGetterDescriptorImpl(
|
||||||
|
property,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
Modality.OPEN,
|
||||||
|
Visibilities.PUBLIC,
|
||||||
|
false, false, false,
|
||||||
|
CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
null,
|
||||||
|
SourceElement.NO_SOURCE
|
||||||
|
).also {
|
||||||
|
property.initialize(it, null)
|
||||||
|
property.setType(
|
||||||
|
/* outType = */ superNameProperty.type,
|
||||||
|
/* typeParameters = */ superNameProperty.typeParameters,
|
||||||
|
/* dispatchReceiverParameter = */ superNameProperty.dispatchReceiverParameter,
|
||||||
|
/* receiverType = */ superNameProperty.extensionReceiverParameter?.type
|
||||||
|
)
|
||||||
|
//overriddenDescriptors += superNameProperty.getter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun doInitialize() {
|
||||||
|
val descriptor = symbol.descriptor as PropertyGetterDescriptorImpl
|
||||||
|
descriptor.initialize(superNameProperty.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildIr(): IrSimpleFunction {
|
||||||
|
val startOffset = irFunctionReference.startOffset
|
||||||
|
val endOffset = irFunctionReference.endOffset
|
||||||
|
val ourSymbol = symbol
|
||||||
|
return IrFunctionImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
symbol = ourSymbol
|
||||||
|
).apply {
|
||||||
|
|
||||||
|
val function = this
|
||||||
|
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||||
|
returnType = ourSymbol.descriptor.returnType!!.toIrType()!!
|
||||||
|
|
||||||
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
|
+irReturn(
|
||||||
|
IrConstImpl.string(-1, -1, context.irBuiltIns.stringType, functionDescriptor.name.asString())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun createGetSignatureMethodBuilder(superFunctionDescriptor: FunctionDescriptor) =
|
||||||
|
object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
|
|
||||||
|
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||||
|
SimpleFunctionDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* name = */ Name.identifier("getSignature"),
|
||||||
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun doInitialize() {
|
||||||
|
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
||||||
|
val valueParameters = superFunctionDescriptor.valueParameters
|
||||||
|
.map { it.copyAsValueParameter(descriptor, it.index) }
|
||||||
|
|
||||||
|
descriptor.initialize(
|
||||||
|
/* receiverParameterType = */ null,
|
||||||
|
/* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter,
|
||||||
|
/* typeParameters = */ emptyList(),
|
||||||
|
/* unsubstitutedValueParameters = */ valueParameters,
|
||||||
|
/* unsubstitutedReturnType = */ superFunctionDescriptor.returnType,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* visibility = */ Visibilities.PUBLIC
|
||||||
|
).apply {
|
||||||
|
overriddenDescriptors += superFunctionDescriptor
|
||||||
|
isSuspend = superFunctionDescriptor.isSuspend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildIr(): IrSimpleFunction {
|
||||||
|
val startOffset = irFunctionReference.startOffset
|
||||||
|
val endOffset = irFunctionReference.endOffset
|
||||||
|
val ourSymbol = symbol
|
||||||
|
return IrFunctionImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
symbol = ourSymbol
|
||||||
|
).apply {
|
||||||
|
|
||||||
|
val function = this
|
||||||
|
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||||
|
returnType = ourSymbol.descriptor.returnType!!.toIrType()!!
|
||||||
|
|
||||||
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
|
+irReturn(
|
||||||
|
IrConstImpl.string(
|
||||||
|
-1, -1, context.irBuiltIns.stringType,
|
||||||
|
PropertyReferenceCodegen.getSignatureString(
|
||||||
|
irFunctionReference.symbol.descriptor, this@CallableReferenceLowering.context.state
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGetOwnerMethodBuilder(superFunctionDescriptor: FunctionDescriptor) =
|
||||||
|
object : SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
|
||||||
|
|
||||||
|
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
|
||||||
|
SimpleFunctionDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* name = */ Name.identifier("getOwner"),
|
||||||
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun doInitialize() {
|
||||||
|
val descriptor = symbol.descriptor as SimpleFunctionDescriptorImpl
|
||||||
|
val valueParameters = superFunctionDescriptor.valueParameters
|
||||||
|
.map { it.copyAsValueParameter(descriptor, it.index) }
|
||||||
|
|
||||||
|
descriptor.initialize(
|
||||||
|
/* receiverParameterType = */ null,
|
||||||
|
/* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter,
|
||||||
|
/* typeParameters = */ emptyList(),
|
||||||
|
/* unsubstitutedValueParameters = */ valueParameters,
|
||||||
|
/* unsubstitutedReturnType = */ superFunctionDescriptor.returnType,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* visibility = */ Visibilities.PUBLIC
|
||||||
|
).apply {
|
||||||
|
overriddenDescriptors += superFunctionDescriptor
|
||||||
|
isSuspend = superFunctionDescriptor.isSuspend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildIr(): IrSimpleFunction {
|
||||||
|
val startOffset = irFunctionReference.startOffset
|
||||||
|
val endOffset = irFunctionReference.endOffset
|
||||||
|
val ourSymbol = symbol
|
||||||
|
return IrFunctionImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
symbol = ourSymbol
|
||||||
|
).apply {
|
||||||
|
returnType = symbol.descriptor.returnType!!.toIrType()!!
|
||||||
|
val function = this
|
||||||
|
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
|
||||||
|
|
||||||
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
|
+irReturn(
|
||||||
|
generateCallableReferenceDeclarationContainer(irFunctionReference)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.generateCallableReferenceDeclarationContainer(
|
||||||
|
irFunctionReference: IrFunctionReference
|
||||||
|
): IrExpression {
|
||||||
|
val descriptor = irFunctionReference.symbol.descriptor
|
||||||
|
val globalContext = this@CallableReferenceLowering.context
|
||||||
|
val state = globalContext.state
|
||||||
|
val container = descriptor.containingDeclaration
|
||||||
|
|
||||||
|
val type =
|
||||||
|
when {
|
||||||
|
container is ClassDescriptor ->
|
||||||
|
// TODO: getDefaultType() here is wrong and won't work for arrays
|
||||||
|
state.typeMapper.mapType(container.defaultType)
|
||||||
|
container is PackageFragmentDescriptor ->
|
||||||
|
state.typeMapper.mapOwner(descriptor)
|
||||||
|
descriptor is VariableDescriptorWithAccessors ->
|
||||||
|
globalContext.state.bindingContext.get(
|
||||||
|
CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, descriptor
|
||||||
|
)!!
|
||||||
|
else -> state.typeMapper.mapOwner(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
val clazzDescriptor = globalContext.getClass(FqName("java.lang.Class"))
|
||||||
|
val clazz = IrClassReferenceImpl(
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
UNDEFINED_OFFSET,
|
||||||
|
clazzDescriptor.toIrType(),
|
||||||
|
clazzDescriptor,
|
||||||
|
CrIrType(type)
|
||||||
|
)
|
||||||
|
|
||||||
|
val isContainerPackage = if (descriptor is LocalVariableDescriptor)
|
||||||
|
DescriptorUtils.getParentOfType(descriptor, ClassDescriptor::class.java) == null
|
||||||
|
else
|
||||||
|
container is PackageFragmentDescriptor
|
||||||
|
|
||||||
|
val reflectionClass = globalContext.getClass(FqName("kotlin.jvm.internal.Reflection"))
|
||||||
|
return if (isContainerPackage) {
|
||||||
|
// Note that this name is not used in reflection. There should be the name of the referenced declaration's module instead,
|
||||||
|
// but there's no nice API to obtain that name here yet
|
||||||
|
// TODO: write the referenced declaration's module name and use it in reflection
|
||||||
|
val module = IrConstImpl.string(
|
||||||
|
-1, -1, globalContext.irBuiltIns.stringType,
|
||||||
|
state.moduleName
|
||||||
|
)
|
||||||
|
val function = reflectionClass.getStaticFunction("getOrCreateKotlinPackage", emptyList())
|
||||||
|
irCall(IrSimpleFunctionSymbolImpl(function), function.returnType!!.toIrType()!!).apply {
|
||||||
|
putValueArgument(0, clazz)
|
||||||
|
putValueArgument(1, module)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val function = reflectionClass.staticScope
|
||||||
|
.getContributedFunctions(Name.identifier("getOrCreateKotlinClass"), NoLookupLocation.FROM_BACKEND)
|
||||||
|
.single { it.valueParameters.size == 1 }
|
||||||
|
irCall(IrSimpleFunctionSymbolImpl(function), function.returnType!!.toIrType()!!).apply {
|
||||||
|
putValueArgument(0, clazz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO rewrite
|
||||||
|
private fun Name.safeName(): Name {
|
||||||
|
return if (isSpecial) {
|
||||||
|
val name = asString()
|
||||||
|
Name.identifier("$${name.substring(1, name.length - 1)}")
|
||||||
|
} else this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from K/Native IrUtils2.kt
|
||||||
|
// TODO move IrUtils2.kt to common
|
||||||
|
private fun IrClass.createParameterDeclarations() {
|
||||||
|
thisReceiver = IrValueParameterImpl(
|
||||||
|
startOffset, endOffset,
|
||||||
|
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
||||||
|
descriptor.thisAsReceiverParameter,
|
||||||
|
this.symbol.typeWith(this.typeParameters.map { it.defaultType }),
|
||||||
|
null
|
||||||
|
).also { valueParameter ->
|
||||||
|
valueParameter.parent = this
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(typeParameters.isEmpty())
|
||||||
|
assert(descriptor.declaredTypeParameters.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
private val IrTypeParameter.defaultType: IrType get() = this.symbol.defaultType
|
||||||
|
|
||||||
|
private val IrTypeParameterSymbol.defaultType: IrType
|
||||||
|
get() = IrSimpleTypeImpl(
|
||||||
|
this,
|
||||||
|
false,
|
||||||
|
emptyList(),
|
||||||
|
emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
private fun IrClassifierSymbol.typeWith(arguments: List<IrType>): IrSimpleType =
|
||||||
|
IrSimpleTypeImpl(
|
||||||
|
this,
|
||||||
|
false,
|
||||||
|
arguments.map { makeTypeProjection(it, Variance.INVARIANT) },
|
||||||
|
emptyList()
|
||||||
|
)
|
||||||
@@ -145,6 +145,9 @@ fun IrBuilderWithScope.irSetVar(variable: IrVariableSymbol, value: IrExpression)
|
|||||||
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, field: IrField) =
|
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, field: IrField) =
|
||||||
IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver)
|
IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver)
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.irSetField(receiver: IrExpression?, field: IrField, value: IrExpression) =
|
||||||
|
IrSetFieldImpl(startOffset, endOffset, field.symbol, receiver, value, field.type)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
|
fun IrBuilderWithScope.irGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
|
||||||
IrGetObjectValueImpl(startOffset, endOffset, type, classSymbol)
|
IrGetObjectValueImpl(startOffset, endOffset, type, classSymbol)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user