Rewrote callable reference lowering
For each callable reference a class inherited from KFunctionImpl is built.
This commit is contained in:
+6
-3
@@ -52,10 +52,13 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform
|
||||
}
|
||||
|
||||
override final fun visitField(declaration: IrField): IrStatement {
|
||||
val isDelegated = declaration.descriptor.isDelegated
|
||||
if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||
val peek = scopeStack.peek()
|
||||
val fieldDiffersFromProperty = peek == null || peek.scope.scopeOwner != declaration.descriptor
|
||||
if (fieldDiffersFromProperty)
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||
val result = visitFieldNew(declaration)
|
||||
if (isDelegated) scopeStack.pop()
|
||||
if (fieldDiffersFromProperty)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -55,6 +55,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
when (memberDeclaration) {
|
||||
is IrFunction -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||
is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||
is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||
is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||
else -> null
|
||||
}
|
||||
|
||||
+21
-20
@@ -101,34 +101,35 @@ internal class SpecialDescriptorsFactory(val context: Context) {
|
||||
descriptor: FunctionDescriptor,
|
||||
bridgeDirections: Array<BridgeDirection>) {
|
||||
val returnType = when (bridgeDirections[0]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!!
|
||||
BridgeDirection.NOT_NEEDED -> descriptor.returnType
|
||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!!
|
||||
BridgeDirection.NOT_NEEDED -> descriptor.returnType
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType
|
||||
}
|
||||
|
||||
val extensionReceiverType = when (bridgeDirections[1]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type
|
||||
BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type
|
||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type
|
||||
BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType
|
||||
}
|
||||
|
||||
val valueParameters = descriptor.valueParameters.mapIndexed { index, valueParameterDescriptor ->
|
||||
when (bridgeDirections[index + 2]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor
|
||||
BridgeDirection.NOT_NEEDED -> valueParameterDescriptor
|
||||
BridgeDirection.FROM_VALUE_TYPE -> ValueParameterDescriptorImpl(
|
||||
containingDeclaration = valueParameterDescriptor.containingDeclaration,
|
||||
original = null,
|
||||
index = index,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = valueParameterDescriptor.name,
|
||||
outType = context.builtIns.anyType,
|
||||
declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(),
|
||||
isCrossinline = valueParameterDescriptor.isCrossinline,
|
||||
isNoinline = valueParameterDescriptor.isNoinline,
|
||||
varargElementType = valueParameterDescriptor.varargElementType,
|
||||
source = SourceElement.NO_SOURCE)
|
||||
}
|
||||
val outType = when (bridgeDirections[index + 2]) {
|
||||
BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor.type
|
||||
BridgeDirection.NOT_NEEDED -> valueParameterDescriptor.type
|
||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType
|
||||
}
|
||||
ValueParameterDescriptorImpl(
|
||||
containingDeclaration = valueParameterDescriptor.containingDeclaration,
|
||||
original = null,
|
||||
index = index,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = valueParameterDescriptor.name,
|
||||
outType = outType,
|
||||
declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(),
|
||||
isCrossinline = valueParameterDescriptor.isCrossinline,
|
||||
isNoinline = valueParameterDescriptor.isNoinline,
|
||||
varargElementType = valueParameterDescriptor.varargElementType,
|
||||
source = SourceElement.NO_SOURCE)
|
||||
}
|
||||
bridgeDescriptor.initialize(
|
||||
/* receiverParameterType = */ extensionReceiverType,
|
||||
|
||||
+4
-6
@@ -29,19 +29,17 @@ enum class KonanPhase(val description: String,
|
||||
/* ... */ LOWER("IR Lowering"),
|
||||
/* ... ... */ LOWER_INLINE("Functions inlining"),
|
||||
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
||||
/* ... ... */ LOWER_INTEROP("Interop lowering"),
|
||||
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
||||
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS),
|
||||
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS),
|
||||
/* ... ... */ LOWER_CALLABLES("Callable references Lowering",
|
||||
LOWER_INTEROP, LOWER_INITIALIZERS, LOWER_DELEGATION),
|
||||
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES),
|
||||
/* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES),
|
||||
/* ... ... */ LOWER_INTEROP("Interop lowering", LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES),
|
||||
/* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC),
|
||||
/* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering",
|
||||
LOWER_TAILREC, LOWER_ENUMS),
|
||||
/* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", LOWER_TAILREC, LOWER_ENUMS),
|
||||
/* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", LOWER_DEFAULT_PARAMETER_EXTENT),
|
||||
/* ... ... */ LOWER_LATEINIT("Lateinit properties lowering"),
|
||||
/* ... ... */ LOWER_BUILTIN_OPERATORS("BuiltIn Operators Lowering", LOWER_DEFAULT_PARAMETER_EXTENT, LOWER_LATEINIT),
|
||||
|
||||
-1
@@ -40,7 +40,6 @@ enum class ValueType(val classFqName: FqNameUnsafe, val isNullable: Boolean = fa
|
||||
FLOAT(KotlinBuiltIns.FQ_NAMES._float),
|
||||
DOUBLE(KotlinBuiltIns.FQ_NAMES._double),
|
||||
|
||||
UNBOUND_CALLABLE_REFERENCE(FqNameUnsafe("konan.internal.UnboundCallableReference")),
|
||||
NATIVE_PTR(KonanBuiltIns.FqNames.nativePtr),
|
||||
|
||||
NATIVE_POINTED(InteropBuiltIns.FqNames.nativePointed, isNullable = true),
|
||||
|
||||
-2
@@ -137,8 +137,6 @@ internal fun KonanBuiltIns.getKonanInternalFunctions(name: String): List<Functio
|
||||
return konanInternal.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).toList()
|
||||
}
|
||||
|
||||
internal fun KotlinType.isUnboundCallableReference() = this.isRepresentedAs(ValueType.UNBOUND_CALLABLE_REFERENCE)
|
||||
|
||||
internal val KotlinType.isFunctionOrKFunctionType: Boolean
|
||||
get() {
|
||||
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
||||
|
||||
-1
@@ -33,7 +33,6 @@ private val valueTypes = ValueType.values().associate {
|
||||
ValueType.FLOAT -> LLVMFloatType()
|
||||
ValueType.DOUBLE -> LLVMDoubleType()
|
||||
|
||||
ValueType.UNBOUND_CALLABLE_REFERENCE,
|
||||
ValueType.NATIVE_PTR, ValueType.NATIVE_POINTED, ValueType.C_POINTER -> int8TypePtr
|
||||
}!!
|
||||
}
|
||||
|
||||
+4
-43
@@ -689,7 +689,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
is IrBreak -> return evaluateBreak (value)
|
||||
is IrContinue -> return evaluateContinue (value)
|
||||
is IrGetObjectValue -> return evaluateGetObjectValue (value)
|
||||
is IrCallableReference -> return evaluateCallableReference (value)
|
||||
is IrFunctionReference -> return evaluateFunctionReference (value)
|
||||
is IrSuspendableExpression ->
|
||||
return evaluateSuspendableExpression (value)
|
||||
is IrSuspensionPoint -> return evaluateSuspensionPoint (value)
|
||||
@@ -1744,17 +1744,16 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateCallableReference(expression: IrCallableReference): LLVMValueRef {
|
||||
private fun evaluateFunctionReference(expression: IrFunctionReference): LLVMValueRef {
|
||||
// TODO: consider creating separate IR element for pointer to function.
|
||||
assert (expression.type.isUnboundCallableReference() ||
|
||||
TypeUtils.getClassDescriptor(expression.type) == context.interopBuiltIns.cPointer)
|
||||
assert (TypeUtils.getClassDescriptor(expression.type) == context.interopBuiltIns.cPointer)
|
||||
|
||||
assert (expression.getArguments().isEmpty())
|
||||
|
||||
val descriptor = expression.descriptor
|
||||
assert (descriptor.dispatchReceiverParameter == null)
|
||||
|
||||
val entry = codegen.functionEntryPointAddress(descriptor as FunctionDescriptor)
|
||||
val entry = codegen.functionEntryPointAddress(descriptor)
|
||||
return entry
|
||||
}
|
||||
|
||||
@@ -1822,10 +1821,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
val argsWithContinuationIfNeeded = if (descriptor.isSuspend)
|
||||
args + getContinuation()
|
||||
else args
|
||||
if (descriptor.isFunctionInvoke) {
|
||||
return evaluateFunctionInvoke(descriptor, argsWithContinuationIfNeeded, resultLifetime)
|
||||
}
|
||||
|
||||
if (descriptor.isIntrinsic) {
|
||||
return evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
|
||||
}
|
||||
@@ -1840,40 +1835,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private val functionImplUnboundRefGetter by lazy {
|
||||
context.builtIns.getKonanInternalClass("FunctionImpl")
|
||||
.unsubstitutedMemberScope.getContributedDescriptors()
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.single { it.name.asString() == "unboundRef" }
|
||||
.getter!!
|
||||
}
|
||||
|
||||
private fun evaluateFunctionInvoke(descriptor: FunctionDescriptor,
|
||||
args: List<LLVMValueRef>, resultLifetime: Lifetime): LLVMValueRef {
|
||||
|
||||
// Note: the whole function code below is written in the assumption that
|
||||
// `invoke` method receiver is passed as first argument.
|
||||
|
||||
val functionImpl = args[0] // Instance of `konan.internal.FunctionImpl`.
|
||||
|
||||
// `functionImpl.unboundRef` is the pointer to (static) function of type
|
||||
// `(FunctionImpl, Arg_1, ..., Arg_n): Ret`. See [CallableReferenceLowering] for details.
|
||||
// LLVM type for such function is equal to type for `FunctionImpl.invoke(Arg_1, ..., Arg_n): Ret`.
|
||||
// So we can use the latter for simplicity:
|
||||
val unboundRefType = codegen.getLlvmFunctionType(descriptor)
|
||||
|
||||
// Get `functionImpl.unboundRef`:
|
||||
val unboundRef = evaluateSimpleFunctionCall(functionImplUnboundRefGetter,
|
||||
listOf(functionImpl), Lifetime.IRRELEVANT /* unboundRef isn't managed reference */)
|
||||
|
||||
// Cast `functionImpl.unboundRef` to pointer to function:
|
||||
val entryPtr = codegen.bitcast(pointerType(unboundRefType), unboundRef, "entry")
|
||||
|
||||
return call(descriptor, entryPtr, args, resultLifetime)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateSimpleFunctionCall(
|
||||
descriptor: FunctionDescriptor, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime, superClass: ClassDescriptor? = null): LLVMValueRef {
|
||||
|
||||
+451
-205
@@ -18,256 +18,502 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionOrKFunctionType
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.descriptors.impl.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.util.addArguments
|
||||
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.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
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.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.replace
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
|
||||
/**
|
||||
* This lowering pass lowers all [IrCallableReference]s to unbound ones.
|
||||
*/
|
||||
internal class CallableReferenceLowering(val context: KonanBackendContext) : DeclarationContainerLoweringPass {
|
||||
internal class CallableReferenceLowering(val context: Context): DeclarationContainerLoweringPass {
|
||||
|
||||
var callableReferenceCount = 0
|
||||
private var functionReferenceCount = 0
|
||||
|
||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||
irDeclarationContainer.declarations.transformFlat { declaration ->
|
||||
if (declaration !is IrDeclarationContainer)
|
||||
lowerCallableReferences(this, irDeclarationContainer, declaration)
|
||||
lowerFunctionReferences(irDeclarationContainer, declaration)
|
||||
else
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all callable references in the function body to unbound ones.
|
||||
* Returns the list of this function and all created ones.
|
||||
*/
|
||||
private fun lowerCallableReferences(lower: CallableReferenceLowering,
|
||||
irDeclarationContainer: IrDeclarationContainer,
|
||||
declaration: IrDeclaration): List<IrDeclaration> {
|
||||
val containingDeclaration = when (irDeclarationContainer) {
|
||||
is IrClass -> irDeclarationContainer.descriptor
|
||||
is IrFile -> irDeclarationContainer.packageFragmentDescriptor
|
||||
else -> throw AssertionError("Unexpected declaration container: $irDeclarationContainer")
|
||||
}
|
||||
val transformer = CallableReferencesUnbinder(lower, containingDeclaration)
|
||||
declaration.transformChildrenVoid(transformer)
|
||||
return listOf(declaration) + transformer.createdFunctions
|
||||
}
|
||||
|
||||
private object DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE :
|
||||
IrDeclarationOriginImpl("FUNCTION_FOR_CALLABLE_REFERENCE")
|
||||
|
||||
/**
|
||||
* Replaces all callable references in the function body to unbound ones.
|
||||
* Adds all created functions to [createdFunctions].
|
||||
*/
|
||||
private class CallableReferencesUnbinder(val lower: CallableReferenceLowering,
|
||||
val containingDeclaration: DeclarationDescriptor) : IrElementTransformerVoid() {
|
||||
|
||||
val createdFunctions = mutableListOf<IrFunction>()
|
||||
|
||||
private val builtIns = lower.context.builtIns
|
||||
|
||||
override fun visitElement(element: IrElement): IrElement {
|
||||
return super.visitElement(element)
|
||||
}
|
||||
|
||||
private val unboundCallableReferenceType by lazy {
|
||||
builtIns.getKonanInternalClass("UnboundCallableReference").defaultType
|
||||
}
|
||||
|
||||
private val simpleFunctionImplClass by lazy {
|
||||
builtIns.getKonanInternalClass("SimpleFunctionImpl")
|
||||
}
|
||||
|
||||
private val simpleFunctionImplBoundArgsGetter by lazy {
|
||||
simpleFunctionImplClass.defaultType.memberScope.getContributedDescriptors()
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.single { it.name.asString() == "boundArgs" }
|
||||
.getter!!
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
// Class is a declaration container - it will be visited by the main visitor (CallableReferenceLowering).
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
if (!expression.type.isFunctionOrKFunctionType) {
|
||||
// Not a subject of this lowering.
|
||||
return expression
|
||||
private fun lowerFunctionReferences(irDeclarationContainer: IrDeclarationContainer,
|
||||
declaration: IrDeclaration): List<IrDeclaration> {
|
||||
val containingDeclaration = when (irDeclarationContainer) {
|
||||
is IrClass -> irDeclarationContainer.descriptor
|
||||
is IrFile -> irDeclarationContainer.packageFragmentDescriptor
|
||||
else -> throw AssertionError("Unexpected declaration container: $irDeclarationContainer")
|
||||
}
|
||||
val createdClasses = mutableListOf<IrDeclaration>()
|
||||
declaration.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
|
||||
val descriptor = expression.descriptor
|
||||
val boundArgs = expression.getArguments()
|
||||
val boundParams = boundArgs.map { it.first }
|
||||
|
||||
val allParams = descriptor.explicitParameters
|
||||
val unboundParams = allParams - boundParams
|
||||
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
|
||||
// The code below creates a call to `SimpleFunctionImpl` constructor which creates the object implementing
|
||||
// the function type.
|
||||
|
||||
// Create the function to be used as `unboundRef` of `SimpleFunctionImpl`:
|
||||
val newFunction = createSimpleFunctionImplTarget(descriptor, unboundParams, boundParams, startOffset, endOffset)
|
||||
|
||||
createdFunctions.add(newFunction)
|
||||
|
||||
// Create the call to constructor and its arguments:
|
||||
|
||||
val unboundRef = IrFunctionReferenceImpl(startOffset, endOffset,
|
||||
unboundCallableReferenceType, newFunction.descriptor, null)
|
||||
val simpleFunctionImplClassConstructor = simpleFunctionImplClass.unsubstitutedPrimaryConstructor!!
|
||||
|
||||
val boundArgsVarargParam = simpleFunctionImplClassConstructor.valueParameters[1]
|
||||
val boundArgsVararg = IrVarargImpl(
|
||||
startOffset, endOffset,
|
||||
boundArgsVarargParam.type,
|
||||
boundArgsVarargParam.varargElementType!!,
|
||||
boundArgs.map { it.second }
|
||||
)
|
||||
|
||||
return IrCallImpl(startOffset, endOffset, simpleFunctionImplClassConstructor).apply {
|
||||
putValueArgument(0, unboundRef)
|
||||
putValueArgument(1, boundArgsVararg)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For given function [descriptor] creates the function which calls [descriptor] but
|
||||
* takes all [boundParams] packed into `SimpleFunctionImpl` (and all [unboundParams] as is).
|
||||
*/
|
||||
private fun createSimpleFunctionImplTarget(descriptor: FunctionDescriptor,
|
||||
unboundParams: List<ParameterDescriptor>,
|
||||
boundParams: List<ParameterDescriptor>,
|
||||
startOffset: Int, endOffset: Int): IrFunctionImpl {
|
||||
|
||||
// Create new function descriptor:
|
||||
val newDescriptor = createSimpleFunctionImplTargetDescriptor(descriptor, unboundParams)
|
||||
|
||||
val builder = lower.context.createIrBuilder(newDescriptor)
|
||||
val blockBody = builder.irBlockBody(startOffset, endOffset) {
|
||||
val boundArgsGet = irCall(simpleFunctionImplBoundArgsGetter).apply {
|
||||
dispatchReceiver = irGet(newDescriptor.valueParameters[0])
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
// Class is a declaration container - it will be visited by the main visitor (CallableReferenceLowering).
|
||||
return declaration
|
||||
}
|
||||
|
||||
+irLet(boundArgsGet) { boundArgs ->
|
||||
val arrayGet = boundArgs.type.memberScope.getContributedDescriptors()
|
||||
.filterIsInstance<FunctionDescriptor>().single { it.name.asString() == "get" }
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
// TODO: some handling for type parameters is probably required here.
|
||||
|
||||
// Call to old function from new function:
|
||||
val call = irCall(descriptor).apply {
|
||||
// unboundParams are received as all new function parameters except first:
|
||||
val newUnboundParams = newDescriptor.valueParameters.drop(1)
|
||||
assert (unboundParams.size == newUnboundParams.size)
|
||||
addArguments(unboundParams.mapIndexed { index, param ->
|
||||
param to irGet(newUnboundParams[index])
|
||||
})
|
||||
|
||||
// boundParams are received in `SimpleFunctionImpl.boundArgs`:
|
||||
addArguments(boundParams.mapIndexed { index, param ->
|
||||
param to irCall(arrayGet).apply {
|
||||
dispatchReceiver = irGet(boundArgs)
|
||||
putValueArgument(0, irInt(index))
|
||||
}
|
||||
})
|
||||
if (!expression.type.isFunctionOrKFunctionType) {
|
||||
// Not a subject of this lowering.
|
||||
return expression
|
||||
}
|
||||
|
||||
irReturn(call)
|
||||
val loweredFunctionReference = FunctionReferenceBuilder(containingDeclaration, expression).build()
|
||||
createdClasses += loweredFunctionReference.functionReferenceClass
|
||||
return IrCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
calleeDescriptor = loweredFunctionReference.functionReferenceConstructorDescriptor).apply {
|
||||
expression.getArguments().forEachIndexed { index, argument ->
|
||||
putValueArgument(index, argument.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return listOf(declaration) + createdClasses
|
||||
}
|
||||
|
||||
private abstract class DescriptorWithIrBuilder<out D : DeclarationDescriptor, out B : IrDeclaration> {
|
||||
|
||||
protected abstract fun buildDescriptor(): D
|
||||
|
||||
protected open fun doInitialize() {}
|
||||
|
||||
protected abstract fun buildIr(): B
|
||||
|
||||
val descriptor by lazy { buildDescriptor() }
|
||||
|
||||
private val builtIr by lazy { buildIr() }
|
||||
private var initialized: Boolean = false
|
||||
|
||||
fun initialize() {
|
||||
doInitialize()
|
||||
initialized = true
|
||||
}
|
||||
|
||||
val ir: B
|
||||
get() {
|
||||
if (!initialized)
|
||||
throw Error("Access to IR before initialization")
|
||||
return builtIr
|
||||
}
|
||||
}
|
||||
|
||||
private class BuiltFunctionReference(val functionReferenceClass: IrClass,
|
||||
val functionReferenceConstructorDescriptor: ClassConstructorDescriptor)
|
||||
|
||||
private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor,
|
||||
val functionReference: IrFunctionReference) {
|
||||
|
||||
private val functionDescriptor = functionReference.descriptor
|
||||
private val functionParameters = functionDescriptor.explicitParameters
|
||||
private val boundFunctionParameters = functionReference.getArguments().map { it.first }
|
||||
private val unboundFunctionParameters = functionParameters - boundFunctionParameters
|
||||
|
||||
private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl
|
||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, PropertyDescriptor>
|
||||
private val functionReferenceMembers = mutableListOf<IrDeclaration>()
|
||||
|
||||
private fun KotlinType.replace(types: List<KotlinType>) = this.replace(types.map(::TypeProjectionImpl))
|
||||
|
||||
private val kFunctionImplClassDescriptor = context.builtIns.getKonanInternalClass("KFunctionImpl")
|
||||
|
||||
fun build(): BuiltFunctionReference {
|
||||
val startOffset = functionReference.startOffset
|
||||
val endOffset = functionReference.endOffset
|
||||
|
||||
val superTypes = mutableListOf<KotlinType>(
|
||||
kFunctionImplClassDescriptor.defaultType.replace(listOf(functionDescriptor.returnType!!))
|
||||
)
|
||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||
val functionClassDescriptor = context.reflectionTypes.getKFunction(unboundFunctionParameters.size)
|
||||
val types = unboundFunctionParameters.map { it.type } + functionDescriptor.returnType!!
|
||||
superTypes += functionClassDescriptor.defaultType.replace(types)
|
||||
|
||||
functionReferenceClassDescriptor = ClassDescriptorImpl(
|
||||
/* containingDeclaration = */ containingDeclaration,
|
||||
/* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* kind = */ ClassKind.CLASS,
|
||||
/* superTypes = */ superTypes,
|
||||
/* source = */ SourceElement.NO_SOURCE,
|
||||
/* isExternal = */ false
|
||||
)
|
||||
val constructorBuilder = createConstructorBuilder()
|
||||
|
||||
val typeSubstitutor = TypeSubstitutor.create(
|
||||
functionClassDescriptor.declaredTypeParameters
|
||||
.withIndex()
|
||||
.associateBy({ it.value.typeConstructor }, { TypeProjectionImpl(types[it.index]) })
|
||||
)
|
||||
val invokeFunctionDescriptor = functionClassDescriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single().substitute(typeSubstitutor)!!
|
||||
val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionDescriptor)
|
||||
|
||||
val inheritedKFunctionImpl = kFunctionImplClassDescriptor.unsubstitutedMemberScope
|
||||
.getContributedDescriptors()
|
||||
.map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) }
|
||||
.filterNotNull()
|
||||
val contributedDescriptors = (
|
||||
inheritedKFunctionImpl + invokeMethodBuilder.descriptor
|
||||
).toList()
|
||||
functionReferenceClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.descriptor), null)
|
||||
|
||||
constructorBuilder.initialize()
|
||||
functionReferenceMembers.add(constructorBuilder.ir)
|
||||
|
||||
invokeMethodBuilder.initialize()
|
||||
functionReferenceMembers.add(invokeMethodBuilder.ir)
|
||||
|
||||
val functionReferenceClass = IrClassImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
descriptor = functionReferenceClassDescriptor,
|
||||
members = functionReferenceMembers
|
||||
)
|
||||
|
||||
functionReferenceClass.createParameterDeclarations()
|
||||
|
||||
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.descriptor)
|
||||
}
|
||||
|
||||
private fun ParameterDescriptor.copyAsValueParameter(newOwner: CallableDescriptor, index: Int)
|
||||
= when (this) {
|
||||
is ValueParameterDescriptor -> this.copy(newOwner, name, index)
|
||||
is ReceiverParameterDescriptor -> ValueParameterDescriptorImpl(
|
||||
containingDeclaration = newOwner,
|
||||
original = null,
|
||||
index = index,
|
||||
annotations = annotations,
|
||||
name = name,
|
||||
outType = type,
|
||||
declaresDefaultValue = false,
|
||||
isCrossinline = false,
|
||||
isNoinline = false,
|
||||
varargElementType = null,
|
||||
source = source
|
||||
)
|
||||
else -> throw Error("Unexpected parameter descriptor: $this")
|
||||
}
|
||||
|
||||
private fun createConstructorBuilder()
|
||||
= object : DescriptorWithIrBuilder<ClassConstructorDescriptorImpl, IrConstructor>() {
|
||||
|
||||
private val kFunctionImplConstructorDescriptor = kFunctionImplClassDescriptor.constructors.single()
|
||||
private lateinit var constructorParameters: List<ValueParameterDescriptor>
|
||||
|
||||
override fun buildDescriptor(): ClassConstructorDescriptorImpl {
|
||||
return ClassConstructorDescriptorImpl.create(
|
||||
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* isPrimary = */ false,
|
||||
/* source = */ SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
|
||||
override fun doInitialize() {
|
||||
constructorParameters = boundFunctionParameters.mapIndexed { index, parameter ->
|
||||
parameter.copyAsValueParameter(descriptor, index)
|
||||
}
|
||||
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||
descriptor.returnType = functionReferenceClassDescriptor.defaultType
|
||||
}
|
||||
|
||||
override fun buildIr(): IrConstructor {
|
||||
argumentToPropertiesMap = boundFunctionParameters.associate {
|
||||
it to buildPropertyWithBackingField(it.name, it.type, false)
|
||||
}
|
||||
|
||||
val startOffset = functionReference.startOffset
|
||||
val endOffset = functionReference.endOffset
|
||||
val irBuilder = context.createIrBuilder(descriptor, startOffset, endOffset)
|
||||
return IrConstructorImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
descriptor = descriptor).apply {
|
||||
|
||||
createParameterDeclarations()
|
||||
|
||||
body = irBuilder.irBlockBody {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, kFunctionImplConstructorDescriptor).apply {
|
||||
val name = IrConstImpl<String>(startOffset, endOffset, context.builtIns.stringType,
|
||||
IrConstKind.String, functionDescriptor.name.asString())
|
||||
putValueArgument(0, name)
|
||||
val fqName = IrConstImpl<String>(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String,
|
||||
functionDescriptor.fullName)
|
||||
putValueArgument(1, fqName)
|
||||
val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType,
|
||||
boundFunctionParameters.isNotEmpty())
|
||||
putValueArgument(2, bound)
|
||||
val needReceiver = boundFunctionParameters.singleOrNull() is ReceiverParameterDescriptor
|
||||
val receiver = if (needReceiver) irGet(constructorParameters.single()) else irNull()
|
||||
putValueArgument(3, receiver)
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClassDescriptor)
|
||||
// Save all arguments to fields.
|
||||
boundFunctionParameters.forEachIndexed { index, parameter ->
|
||||
+irSetField(irThis(), argumentToPropertiesMap[parameter]!!, irGet(constructorParameters[index]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val newFunction = IrFunctionImpl(
|
||||
startOffset, endOffset, DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE,
|
||||
newDescriptor,
|
||||
blockBody
|
||||
)
|
||||
// TODO: what about private package level functions?
|
||||
private val DeclarationDescriptor.fullName: String
|
||||
get() {
|
||||
return when (this) {
|
||||
is PackageFragmentDescriptor -> fqNameSafe.asString()
|
||||
is ClassDescriptor -> containingDeclaration.fullName + "." + fqNameSafe
|
||||
is FunctionDescriptor -> containingDeclaration.fullName + "." + functionName
|
||||
is PropertyDescriptor -> containingDeclaration.fullName + "." + fqNameSafe
|
||||
else -> TODO("$this")
|
||||
}
|
||||
}
|
||||
|
||||
newFunction.createParameterDeclarations()
|
||||
private fun createInvokeMethodBuilder(functionInvokeFunctionDescriptor: FunctionDescriptor)
|
||||
= object : DescriptorWithIrBuilder<SimpleFunctionDescriptorImpl, IrFunction>() {
|
||||
|
||||
return newFunction
|
||||
}
|
||||
override fun buildDescriptor() = SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* name = */ Name.identifier("invoke"),
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* source = */ SourceElement.NO_SOURCE)
|
||||
|
||||
/**
|
||||
* Creates descriptor for [createSimpleFunctionImplTarget].
|
||||
*/
|
||||
private fun createSimpleFunctionImplTargetDescriptor(descriptor: CallableDescriptor,
|
||||
unboundParams: List<ParameterDescriptor>): FunctionDescriptor {
|
||||
override fun doInitialize() {
|
||||
val valueParameters = functionInvokeFunctionDescriptor.valueParameters
|
||||
.map { it.copyAsValueParameter(this.descriptor, it.index) }
|
||||
|
||||
val newName = Name.identifier("${descriptor.name}\$bound-${lower.callableReferenceCount++}")
|
||||
this.descriptor.initialize(
|
||||
/* receiverParameterType = */ null,
|
||||
/* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter,
|
||||
/* typeParameters = */ emptyList(),
|
||||
/* unsubstitutedValueParameters = */ valueParameters,
|
||||
/* unsubstitutedReturnType = */ functionInvokeFunctionDescriptor.returnType,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE).apply {
|
||||
overriddenDescriptors += functionInvokeFunctionDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
val newDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
containingDeclaration, Annotations.EMPTY,
|
||||
newName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE)
|
||||
override fun buildIr(): IrFunction {
|
||||
val startOffset = functionReference.startOffset
|
||||
val endOffset = functionReference.endOffset
|
||||
val ourDescriptor = this.descriptor
|
||||
val irBuilder = context.createIrBuilder(this.descriptor, startOffset, endOffset)
|
||||
return IrFunctionImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
descriptor = this.descriptor).apply {
|
||||
|
||||
val simpleFunctionImplType = simpleFunctionImplClass.defaultType
|
||||
createParameterDeclarations()
|
||||
|
||||
// Map each unbound param of original function to parameter of new function.
|
||||
val newUnboundParams = unboundParams.mapIndexed { index, param ->
|
||||
ValueParameterDescriptorImpl(
|
||||
containingDeclaration = newDescriptor,
|
||||
original = null,
|
||||
index = index + 1,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = param.name,
|
||||
outType = builtIns.nullableAnyType, // Use erased type.
|
||||
declaresDefaultValue = false,
|
||||
isCrossinline = false, isNoinline = false,
|
||||
varargElementType = null,
|
||||
source = SourceElement.NO_SOURCE)
|
||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(
|
||||
irCall(functionReference.descriptor).apply {
|
||||
var unboundIndex = 0
|
||||
val unboundArgsSet = unboundFunctionParameters.toSet()
|
||||
functionParameters.forEach {
|
||||
val argument = if (unboundArgsSet.contains(it))
|
||||
irGet(ourDescriptor.valueParameters[unboundIndex++])
|
||||
else
|
||||
irGet(irThis(), argumentToPropertiesMap[it]!!)
|
||||
when (it) {
|
||||
functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||
functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument
|
||||
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
|
||||
}
|
||||
}
|
||||
assert(unboundIndex == ourDescriptor.valueParameters.size,
|
||||
{ "Not all arguments of <invoke> are used" })
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// `<func>: SimpleFunctionImpl`
|
||||
val functionParameter = ValueParameterDescriptorImpl(
|
||||
containingDeclaration = newDescriptor,
|
||||
original = null,
|
||||
index = 0,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = Name.special("<func>"),
|
||||
outType = simpleFunctionImplType,
|
||||
declaresDefaultValue = false,
|
||||
isCrossinline = false, isNoinline = false,
|
||||
varargElementType = null,
|
||||
source = SourceElement.NO_SOURCE)
|
||||
private fun createPropertyGetterBuilder(propertyDescriptor: PropertyDescriptor, type: KotlinType)
|
||||
= object : DescriptorWithIrBuilder<PropertyGetterDescriptorImpl, IrFunction>() {
|
||||
|
||||
val newValueParameters = listOf(functionParameter) + newUnboundParams
|
||||
override fun buildDescriptor() = PropertyGetterDescriptorImpl(
|
||||
/* correspondingProperty = */ propertyDescriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE,
|
||||
/* isDefault = */ false,
|
||||
/* isExternal = */ false,
|
||||
/* isInline = */ false,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* original = */ null,
|
||||
/* source = */ SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
val newReturnType = builtIns.nullableAnyType // Use erased type.
|
||||
override fun doInitialize() {
|
||||
descriptor.apply {
|
||||
initialize(type)
|
||||
}
|
||||
}
|
||||
|
||||
newDescriptor.initialize(null, null, descriptor.typeParameters, newValueParameters,
|
||||
newReturnType, Modality.FINAL, Visibilities.PRIVATE)
|
||||
override fun buildIr() = IrFunctionImpl(
|
||||
startOffset = functionReference.startOffset,
|
||||
endOffset = functionReference.endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
descriptor = descriptor).apply {
|
||||
|
||||
return newDescriptor
|
||||
createParameterDeclarations()
|
||||
|
||||
body = context.createIrBuilder(descriptor, startOffset, endOffset).irBlockBody {
|
||||
+irReturn(irGetField(irThis(), propertyDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPropertySetterBuilder(propertyDescriptor: PropertyDescriptor, type: KotlinType)
|
||||
= object : DescriptorWithIrBuilder<PropertySetterDescriptorImpl, IrFunction>() {
|
||||
|
||||
override fun buildDescriptor() = PropertySetterDescriptorImpl(
|
||||
/* correspondingProperty = */ propertyDescriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE,
|
||||
/* isDefault = */ false,
|
||||
/* isExternal = */ false,
|
||||
/* isInline = */ false,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* original = */ null,
|
||||
/* source = */ SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
lateinit var valueParameterDescriptor: ValueParameterDescriptor
|
||||
|
||||
override fun doInitialize() {
|
||||
descriptor.apply {
|
||||
valueParameterDescriptor = ValueParameterDescriptorImpl(
|
||||
containingDeclaration = this,
|
||||
original = null,
|
||||
index = 0,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = Name.identifier("value"),
|
||||
outType = type,
|
||||
declaresDefaultValue = false,
|
||||
isCrossinline = false,
|
||||
isNoinline = false,
|
||||
varargElementType = null,
|
||||
source = SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
initialize(valueParameterDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildIr() = IrFunctionImpl(
|
||||
startOffset = functionReference.startOffset,
|
||||
endOffset = functionReference.endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
descriptor = descriptor).apply {
|
||||
|
||||
createParameterDeclarations()
|
||||
|
||||
body = context.createIrBuilder(descriptor, startOffset, endOffset).irBlockBody {
|
||||
+irSetField(irThis(), propertyDescriptor, irGet(valueParameterDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPropertyWithBackingFieldBuilder(name: Name, type: KotlinType, isMutable: Boolean)
|
||||
= object : DescriptorWithIrBuilder<PropertyDescriptorImpl, IrProperty>() {
|
||||
|
||||
private lateinit var getterBuilder: DescriptorWithIrBuilder<PropertyGetterDescriptorImpl, IrFunction>
|
||||
private var setterBuilder: DescriptorWithIrBuilder<PropertySetterDescriptorImpl, IrFunction>? = null
|
||||
|
||||
override fun buildDescriptor() = PropertyDescriptorImpl.create(
|
||||
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||
/* annotations = */ Annotations.EMPTY,
|
||||
/* modality = */ Modality.FINAL,
|
||||
/* visibility = */ Visibilities.PRIVATE,
|
||||
/* isVar = */ isMutable,
|
||||
/* name = */ name,
|
||||
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/* source = */ SourceElement.NO_SOURCE,
|
||||
/* lateInit = */ false,
|
||||
/* isConst = */ false,
|
||||
/* isHeader = */ false,
|
||||
/* isImpl = */ false,
|
||||
/* isExternal = */ false,
|
||||
/* isDelegated = */ false)
|
||||
|
||||
override fun doInitialize() {
|
||||
getterBuilder = createPropertyGetterBuilder(descriptor, type).apply { initialize() }
|
||||
if (isMutable)
|
||||
setterBuilder = createPropertySetterBuilder(descriptor, type).apply { initialize() }
|
||||
descriptor.initialize(getterBuilder.descriptor, setterBuilder?.descriptor)
|
||||
val receiverType: KotlinType? = null
|
||||
descriptor.setType(type, emptyList(), functionReferenceClassDescriptor.thisAsReceiverParameter, receiverType)
|
||||
}
|
||||
|
||||
override fun buildIr(): IrProperty {
|
||||
val startOffset = functionReference.startOffset
|
||||
val endOffset = functionReference.endOffset
|
||||
val backingField = IrFieldImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
descriptor = descriptor)
|
||||
return IrPropertyImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
isDelegated = false,
|
||||
descriptor = descriptor,
|
||||
backingField = backingField,
|
||||
getter = getterBuilder.ir,
|
||||
setter = setterBuilder?.ir)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): PropertyDescriptor {
|
||||
val propertyBuilder = createPropertyWithBackingFieldBuilder(name, type, isMutable).apply { initialize() }
|
||||
|
||||
functionReferenceMembers.add(propertyBuilder.ir)
|
||||
return propertyBuilder.descriptor
|
||||
}
|
||||
|
||||
private object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL :
|
||||
IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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 konan.internal
|
||||
|
||||
/**
|
||||
* Represents the reference to callable without any bound arguments.
|
||||
* It is supposed to be represented at runtime as native pointer to code.
|
||||
*
|
||||
* TODO: it seems to be very closely related to native interop types.
|
||||
*/
|
||||
abstract class UnboundCallableReference internal constructor()
|
||||
|
||||
/**
|
||||
* Values of function types are represented at runtime as instances of this class (and its subclasses).
|
||||
*
|
||||
* [FunctionImpl] is a reference to callable with itself as single bound argument,
|
||||
* i.e. when calling this function with arguments `args`, [unboundRef] is called with arguments `(this, *args)`.
|
||||
* So the instance is supposed to contain all implicit (bound) arguments of target function, e.g. captured values.
|
||||
*/
|
||||
open class FunctionImpl(val unboundRef: UnboundCallableReference)
|
||||
|
||||
/**
|
||||
* Simple [FunctionImpl] implementation: all bound arguments of target callable to be placed into [boundArgs].
|
||||
*/
|
||||
class SimpleFunctionImpl(unboundRef: UnboundCallableReference, vararg val boundArgs: Any?) : FunctionImpl(unboundRef)
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 konan.internal
|
||||
|
||||
import kotlin.reflect.KFunction
|
||||
|
||||
@FixmeReflection
|
||||
open class KFunctionImpl<out R>(override val name: String, val fqName: String, val bound: Boolean, val receiver: Any?): KFunction<R> {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is KFunctionImpl<*>) return false
|
||||
return fqName == other.fqName && bound == other.bound && receiver == other.receiver
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return (fqName.hashCode() * 31 + if (bound) 1 else 0) * 31 + receiver.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return fqName
|
||||
}
|
||||
}
|
||||
@@ -65,11 +65,11 @@ public interface KProperty<out R> : KCallable<R> {
|
||||
|
||||
//
|
||||
@FixmeReflection
|
||||
public interface KProperty0<out R> : kotlin.reflect.KProperty<R>/* TODO , (T) -> R*/ {
|
||||
public interface KProperty0<out R> : kotlin.reflect.KProperty<R>, () -> R {
|
||||
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
||||
|
||||
public abstract fun get(): R
|
||||
public abstract operator fun invoke(): R
|
||||
public override abstract operator fun invoke(): R
|
||||
|
||||
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
||||
//
|
||||
@@ -78,11 +78,11 @@ public interface KProperty0<out R> : kotlin.reflect.KProperty<R>/* TODO , (T) ->
|
||||
}
|
||||
|
||||
@FixmeReflection
|
||||
public interface KProperty1<T, out R> : kotlin.reflect.KProperty<R>/* TODO , (T) -> R*/ {
|
||||
public interface KProperty1<T, out R> : kotlin.reflect.KProperty<R>, (T) -> R {
|
||||
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
||||
|
||||
public abstract fun get(receiver: T): R
|
||||
public abstract operator fun invoke(receiver: T): R
|
||||
public override abstract operator fun invoke(receiver: T): R
|
||||
|
||||
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
||||
//
|
||||
@@ -91,11 +91,11 @@ public interface KProperty1<T, out R> : kotlin.reflect.KProperty<R>/* TODO , (T)
|
||||
}
|
||||
|
||||
@FixmeReflection
|
||||
public interface KProperty2<T1, T2, out R> : kotlin.reflect.KProperty<R>/* TODO , (T) -> R*/ {
|
||||
public interface KProperty2<T1, T2, out R> : kotlin.reflect.KProperty<R>, (T1, T2) -> R {
|
||||
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
||||
|
||||
public abstract fun get(receiver1: T1, receiver2: T2): R
|
||||
public abstract operator fun invoke(receiver1: T1, receiver2: T2): R
|
||||
public override abstract operator fun invoke(receiver1: T1, receiver2: T2): R
|
||||
|
||||
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user