From 26e107589350de6187a491137883a5a9ff2186ae Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 19 Jan 2017 13:36:14 +0700 Subject: [PATCH] backend: lower local classes --- .../common/lower/LocalDeclarationsLowering.kt | 773 +++++++++++++++--- .../kotlin/backend/common/lower/LowerUtils.kt | 56 +- 2 files changed, 708 insertions(+), 121 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index 115b2de54d9..f05dc2d7bde 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -21,15 +21,12 @@ import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.Closure import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +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.* import org.jetbrains.kotlin.ir.util.transformFlat @@ -45,48 +42,135 @@ import java.util.* class LocalDeclarationsLowering(val context: BackendContext): DeclarationContainerLoweringPass { override fun lower(irDeclarationContainer: IrDeclarationContainer) { + if (irDeclarationContainer is IrDeclaration && + irDeclarationContainer.descriptor.parents.any { it is CallableDescriptor }) { + + // Lowering of non-local declarations handles all local declarations inside. + // This declaration is local and shouldn't be considered. + return + } + + // Continuous numbering across all declarations in the container. + lambdasCount = 0 + objectsCount = 0 + irDeclarationContainer.declarations.transformFlat { memberDeclaration -> if (memberDeclaration is IrFunction) - LocalFunctionsTransformer(memberDeclaration).lowerLocalFunctions() + LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() else null } } - private class LocalFunctionContext(val declaration: IrFunction) { + private var lambdasCount = 0 + private var objectsCount = 0 + + private abstract class LocalContext { + /** + * @return the expression to get the value for given descriptor, or `null` if [IrGetValue] should be used. + */ + abstract fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? + } + + private abstract class LocalContextWithClosureAsParameters : LocalContext() { + + abstract val declaration: IrFunction + open val descriptor: FunctionDescriptor + get() = declaration.descriptor + + abstract val transformedDescriptor: FunctionDescriptor + + val capturedValueToParameter: MutableMap = HashMap() + + override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { + val newDescriptor = capturedValueToParameter[descriptor] ?: return null + + return IrGetValueImpl(startOffset, endOffset, newDescriptor) + } + } + + private class LocalFunctionContext(override val declaration: IrFunction) : LocalContextWithClosureAsParameters() { lateinit var closure: Closure - val closureParametersCount: Int get() = closure.capturedValues.size - - lateinit var transformedDescriptor: FunctionDescriptor - - val old2new: MutableMap = HashMap() + override lateinit var transformedDescriptor: FunctionDescriptor var index: Int = -1 override fun toString(): String = - "LocalFunctionContext for ${declaration.descriptor}" + "LocalFunctionContext for $descriptor" } - private inner class LocalFunctionsTransformer(val memberFunction: IrFunction) { - val localFunctions: MutableMap = LinkedHashMap() - val new2old: MutableMap = HashMap() + private class LocalClassConstructorContext(override val declaration: IrConstructor) : LocalContextWithClosureAsParameters() { + override val descriptor: ClassConstructorDescriptor + get() = declaration.descriptor - fun lowerLocalFunctions(): List? { - collectLocalFunctions() - if (localFunctions.isEmpty()) return null + override lateinit var transformedDescriptor: ClassConstructorDescriptor + + override fun toString(): String = + "LocalClassConstructorContext for $descriptor" + } + + private class LocalClassContext(val declaration: IrClass) : LocalContext() { + lateinit var closure: Closure + + lateinit var transformedDescriptor: ClassDescriptorImpl + + val capturedValueToField: MutableMap = HashMap() + + var index: Int = -1 + + override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { + val fieldDescriptor = capturedValueToField[descriptor] ?: return null + + return IrGetFieldImpl(startOffset, endOffset, fieldDescriptor, + receiver = IrGetValueImpl(startOffset, endOffset, transformedDescriptor.thisAsReceiverParameter) + ) + } + + override fun toString(): String = + "LocalClassContext for ${declaration.descriptor}" + } + + private inner class LocalDeclarationsTransformer(val memberFunction: IrFunction) { + val localFunctions: MutableMap = LinkedHashMap() + val localClasses: MutableMap = LinkedHashMap() + val localClassConstructors: MutableMap = LinkedHashMap() + val localClassMembers: MutableSet = LinkedHashSet() + + val transformedDescriptors = mutableMapOf() + + val CallableDescriptor.transformed: CallableDescriptor? + get() = transformedDescriptors[this] as CallableDescriptor? + + val CallableMemberDescriptor.transformed: CallableMemberDescriptor? + get() = transformedDescriptors[this] as CallableMemberDescriptor? + + val FunctionDescriptor.transformed: FunctionDescriptor? + get() = transformedDescriptors[this] as FunctionDescriptor? + + val PropertyDescriptor.transformed: PropertyDescriptor? + get() = transformedDescriptors[this] as PropertyDescriptor? + + val oldParameterToNew: MutableMap = HashMap() + val newParameterToOld: MutableMap = HashMap() + val newParameterToCaptured: MutableMap = HashMap() + + fun lowerLocalDeclarations(): List? { + collectLocalDeclarations() + if (localFunctions.isEmpty() && localClasses.isEmpty()) return null collectClosures() transformDescriptors() - rewriteBodies() + rewriteDeclarations() - return collectRewrittenDeclarations() + val result = collectRewrittenDeclarations() + return result } private fun collectRewrittenDeclarations(): ArrayList = - ArrayList(localFunctions.size + 1).apply { + ArrayList(localFunctions.size + localClasses.size + 1).apply { add(memberFunction) localFunctions.values.mapTo(this) { @@ -97,53 +181,137 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain original.body ) } + + localClasses.values.mapTo(this) { + val original = it.declaration + IrClassImpl( + original.startOffset, original.endOffset, original.origin, + it.transformedDescriptor, + original.declarations + ) + } } - private inner class FunctionBodiesRewriter(val localFunctionContext: LocalFunctionContext?) : IrElementTransformerVoid() { + private inner class FunctionBodiesRewriter(val localContext: LocalContext?) : IrElementTransformerVoid() { override fun visitClass(declaration: IrClass): IrStatement { - // ignore local classes for now - return declaration - } - - override fun visitFunction(declaration: IrFunction): IrStatement { - // replace local function definition with an empty composite + // Replace local class definition with an empty composite. return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) } + override fun visitProperty(declaration: IrProperty): IrStatement { + declaration.transformChildrenVoid(this) + val newDescriptor = declaration.descriptor.transformed ?: return declaration + + return IrPropertyImpl( + declaration.startOffset, declaration.endOffset, + declaration.origin, declaration.isDelegated, newDescriptor, + declaration.backingField, + declaration.getter, declaration.setter + ) + } + + override fun visitField(declaration: IrField): IrStatement { + declaration.transformChildrenVoid(this) + val newDescriptor = declaration.descriptor.transformed ?: return declaration + + return IrFieldImpl( + declaration.startOffset, declaration.endOffset, declaration.origin, + newDescriptor, + declaration.initializer + ) + } + + override fun visitGetField(expression: IrGetField): IrExpression { + expression.transformChildrenVoid(this) + val newDescriptor = expression.descriptor.transformed ?: return expression + + return IrGetFieldImpl( + expression.startOffset, expression.endOffset, newDescriptor, + expression.receiver, expression.origin, expression.superQualifier + ) + } + + override fun visitSetField(expression: IrSetField): IrExpression { + expression.transformChildrenVoid(this) + val newDescriptor = expression.descriptor.transformed ?: return expression + + return IrSetFieldImpl( + expression.startOffset, expression.endOffset, newDescriptor, + expression.receiver, expression.value, + expression.origin, expression.superQualifier + ) + } + + override fun visitFunction(declaration: IrFunction): IrStatement { + if (declaration.descriptor in localFunctions) { + // Replace local function definition with an empty composite. + return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) + } else if (declaration.descriptor in localClassMembers){ + declaration.transformChildrenVoid(this) + + val transformedDescriptor = declaration.descriptor.transformed!! + + return IrFunctionImpl(declaration.startOffset, declaration.endOffset, declaration.origin, + transformedDescriptor, declaration.body) + } else { + throw AssertionError("the function is neither local itself nor member of a local class") + } + } + + override fun visitConstructor(declaration: IrConstructor): IrStatement { + // Body is transformed separately. + + val transformedDescriptor = localClassConstructors[declaration.descriptor]!!.transformedDescriptor + + return IrConstructorImpl(declaration.startOffset, declaration.endOffset, declaration.origin, + transformedDescriptor, declaration.body!!) + } + override fun visitGetValue(expression: IrGetValue): IrExpression { - val remapped = localFunctionContext?.let { it.old2new[expression.descriptor] } - return if (remapped == null) - expression - else - IrGetValueImpl(expression.startOffset, expression.endOffset, remapped, expression.origin) + val descriptor = expression.descriptor + + localContext?.irGet(expression.startOffset, expression.endOffset, descriptor)?.let { + return it + } + + oldParameterToNew[descriptor]?.let { + return IrGetValueImpl(expression.startOffset, expression.endOffset, it) + } + + return expression } override fun visitCall(expression: IrCall): IrExpression { expression.transformChildrenVoid(this) val oldCallee = expression.descriptor.original - val localFunctionData = localFunctions[oldCallee] ?: return expression + val newCallee = oldCallee.transformed ?: return expression - val newCallee = localFunctionData.transformedDescriptor - - val newCall = createNewCall(expression, newCallee).fillArguments(localFunctionData, expression) + val newCall = createNewCall(expression, newCallee).fillArguments(expression) return newCall } - private fun T.fillArguments(calleeContext: LocalFunctionContext, oldExpression: IrMemberAccessExpression): T { - val closureParametersCount = calleeContext.closureParametersCount + private fun T.fillArguments(oldExpression: IrMemberAccessExpression): T { - mapValueParametersIndexed { index, newValueParameterDescriptor -> - val capturedValueDescriptor = new2old[newValueParameterDescriptor] ?: - throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") - if (index >= closureParametersCount) - oldExpression.getValueArgument(capturedValueDescriptor as ValueParameterDescriptor) - else { - val remappedValueDescriptor = localFunctionContext?.let { it.old2new[capturedValueDescriptor] } - IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, - remappedValueDescriptor ?: capturedValueDescriptor) + mapValueParameters { newValueParameterDescriptor -> + val oldParameter = newParameterToOld[newValueParameterDescriptor] + + if (oldParameter != null) { + oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor) + } else { + // The callee expects captured value as argument. + val capturedValueDescriptor = + newParameterToCaptured[newValueParameterDescriptor] ?: + throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") + + localContext?.irGet( + oldExpression.startOffset, oldExpression.endOffset, + capturedValueDescriptor + ) ?: + // Captured value is directly available for the caller. + IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, capturedValueDescriptor) } } @@ -158,8 +326,7 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain expression.transformChildrenVoid(this) val oldCallee = expression.descriptor.original - val localFunctionData = localFunctions[oldCallee] ?: return expression - val newCallee = localFunctionData.transformedDescriptor + val newCallee = oldCallee.transformed ?: return expression val newCallableReference = IrCallableReferenceImpl( expression.startOffset, expression.endOffset, @@ -167,7 +334,7 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain newCallee, remapTypeArguments(expression, newCallee), expression.origin - ).fillArguments(localFunctionData, expression) + ).fillArguments(expression) return newCallableReference } @@ -176,26 +343,77 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain expression.transformChildrenVoid(this) val oldReturnTarget = expression.returnTarget - val localFunctionData = localFunctions[oldReturnTarget] ?: return expression - val newReturnTarget = localFunctionData.transformedDescriptor + val newReturnTarget = oldReturnTarget.transformed ?: return expression return IrReturnImpl(expression.startOffset, expression.endOffset, newReturnTarget, expression.value) } - } - private fun rewriteFunctionDeclaration(irFunction: IrFunction, localFunctionContext: LocalFunctionContext?) { - irFunction.transformChildrenVoid(FunctionBodiesRewriter(localFunctionContext)) - } - - private fun rewriteBodies() { - localFunctions.values.forEach { - rewriteFunctionDeclaration(it.declaration, it) + override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression { + if (expression.descriptor in transformedDescriptors) { + TODO() + } + return super.visitDeclarationReference(expression) } - rewriteFunctionDeclaration(memberFunction, null) + override fun visitDeclaration(declaration: IrDeclaration): IrStatement { + if (declaration.descriptor in transformedDescriptors) { + TODO() + } + return super.visitDeclaration(declaration) + } } - private fun createNewCall(oldCall: IrCall, newCallee: FunctionDescriptor) = + private fun rewriteFunctionBody(irFunction: IrFunction, localContext: LocalContext?) { + irFunction.transformChildrenVoid(FunctionBodiesRewriter(localContext)) + } + + private object DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE : + IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE") {} + + private fun rewriteClassMembers(irClass: IrClass, localClassContext: LocalClassContext) { + irClass.transformChildrenVoid(FunctionBodiesRewriter(localClassContext)) + + val primaryConstructor = irClass.descriptor.unsubstitutedPrimaryConstructor ?: + TODO("local classes without primary constructor") + + val primaryConstructorContext = localClassConstructors[primaryConstructor]!! + + localClassContext.capturedValueToField.forEach { capturedValue, fieldDescriptor -> + + val capturedValueExpression = + primaryConstructorContext.irGet(irClass.startOffset, irClass.endOffset, capturedValue)!! + + irClass.declarations.add( + IrFieldImpl( + irClass.startOffset, irClass.endOffset, + DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, + fieldDescriptor, + IrExpressionBodyImpl( + irClass.startOffset, irClass.endOffset, + capturedValueExpression + ) + ) + ) + } + } + + private fun rewriteDeclarations() { + localFunctions.values.forEach { + rewriteFunctionBody(it.declaration, it) + } + + localClassConstructors.values.forEach { + rewriteFunctionBody(it.declaration, it) + } + + localClasses.values.forEach { + rewriteClassMembers(it.declaration, it) + } + + rewriteFunctionBody(memberFunction, null) + } + + private fun createNewCall(oldCall: IrCall, newCallee: CallableDescriptor) = if (oldCall is IrCallWithShallowCopy) oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifier) else @@ -206,7 +424,7 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain oldCall.origin, oldCall.superQualifier ) - private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: FunctionDescriptor): Map? { + private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map? { val oldCallee = oldExpression.descriptor return if (oldCallee.typeParameters.isEmpty()) @@ -219,64 +437,78 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain private fun transformDescriptors() { localFunctions.values.forEach { - it.transformedDescriptor = createTransformedDescriptor(it) + createLiftedDescriptor(it) + } + + localClasses.values.forEach { + createLiftedDescriptor(it) + } + + localClassConstructors.values.forEach { + createTransformedConstructorDescriptor(it) + } + + localClassMembers.forEach { + createTransformedMemberDescriptor(it) + } + + localClasses.values.forEach { + initializeClassDescriptor(it) } } private fun suggestLocalName(descriptor: DeclarationDescriptor): String { - val localFunctionContext = localFunctions[descriptor] - return if (localFunctionContext != null && localFunctionContext.index >= 0) - "lambda-${localFunctionContext.index}" - else - descriptor.name.asString() + localFunctions[descriptor]?.let { + if (it.index >= 0) + return "lambda-${it.index}" + } + + localClasses[descriptor]?.let { + if (it.index >= 0) + return "object-${it.index}" + } + + return descriptor.name.asString() } - private fun generateNameForLiftedFunction(functionDescriptor: FunctionDescriptor): Name = + private fun generateNameForLiftedDeclaration(descriptor: DeclarationDescriptor, + newOwner: DeclarationDescriptor): Name = Name.identifier( - functionDescriptor.parentsWithSelf - .takeWhile { it is FunctionDescriptor } + descriptor.parentsWithSelf + .takeWhile { it != newOwner } .toList().reversed() .map { suggestLocalName(it) } .joinToString(separator = "$") ) - private fun createTransformedDescriptor(localFunctionContext: LocalFunctionContext): FunctionDescriptor { - val oldDescriptor = localFunctionContext.declaration.descriptor + private fun createLiftedDescriptor(localFunctionContext: LocalFunctionContext) { + val oldDescriptor = localFunctionContext.descriptor val memberOwner = memberFunction.descriptor.containingDeclaration val newDescriptor = SimpleFunctionDescriptorImpl.create( memberOwner, oldDescriptor.annotations, - generateNameForLiftedFunction(oldDescriptor), + generateNameForLiftedDeclaration(oldDescriptor, memberOwner), CallableMemberDescriptor.Kind.SYNTHESIZED, oldDescriptor.source ) - val closureParametersCount = localFunctionContext.closureParametersCount - val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size + localFunctionContext.transformedDescriptor = newDescriptor + transformedDescriptors[oldDescriptor] = newDescriptor - val newDispatchReceiverParameter = - if (memberOwner is ClassDescriptor && oldDescriptor.dispatchReceiverParameter != null) - memberOwner.thisAsReceiverParameter - else - null + if (oldDescriptor.dispatchReceiverParameter != null) { + throw AssertionError("local functions must not have dispatch receiver") + } + + val newDispatchReceiverParameter = null // Do not substitute type parameters for now. val newTypeParameters = oldDescriptor.typeParameters - val newValueParameters = ArrayList(newValueParametersCount).apply { - localFunctionContext.closure.capturedValues.mapIndexedTo(this) { i, capturedValueDescriptor -> - createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValueDescriptor, i).apply { - localFunctionContext.recordRemapped(capturedValueDescriptor, this) - } - } + // TODO: consider using fields to access the closure of enclosing class. + val capturedValues = localFunctionContext.closure.capturedValues - oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor -> - createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply { - localFunctionContext.recordRemapped(oldValueParameterDescriptor, this) - } - } - } + val newValueParameters = createTransformedValueParameters(localFunctionContext, capturedValues) newDescriptor.initialize( oldDescriptor.extensionReceiverParameter?.type, @@ -289,19 +521,282 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain ) oldDescriptor.extensionReceiverParameter?.let { - localFunctionContext.recordRemapped(it, newDescriptor.extensionReceiverParameter!!) + recordRemappedParameter(it, newDescriptor.extensionReceiverParameter!!) + } + } + + private fun createTransformedValueParameters(localContext: LocalContextWithClosureAsParameters, + capturedValues: List + ): List { + + val oldDescriptor = localContext.descriptor + val newDescriptor = localContext.transformedDescriptor + + val closureParametersCount = capturedValues.size + val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size + + val newValueParameters = ArrayList(newValueParametersCount).apply { + capturedValues.mapIndexedTo(this) { i, capturedValueDescriptor -> + createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValueDescriptor, i).apply { + localContext.recordCapturedAsParameter(capturedValueDescriptor, this) + } + } + + oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor -> + createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply { + recordRemappedParameter(oldValueParameterDescriptor, this) + } + } + } + return newValueParameters + } + + private fun createTransformedMemberDescriptor(oldDescriptor: MemberDescriptor) { + when (oldDescriptor) { + is PropertyDescriptor -> createTransformedMemberPropertyDescriptor(oldDescriptor) + is PropertyAccessorDescriptor -> { + // Transformed along with the property. + } + is FunctionDescriptor -> createTransformedMemberFunctionDescriptor(oldDescriptor) + + else -> TODO(oldDescriptor.toString()) + } + } + + private fun createTransformedMemberFunctionDescriptor(oldDescriptor: FunctionDescriptor) { + val memberOwner = localClasses[oldDescriptor.containingDeclaration]!!.transformedDescriptor + + val copyBuilder = oldDescriptor.newCopyBuilder() + + copyBuilder.setOwner(memberOwner) + copyBuilder.setDispatchReceiverParameter(memberOwner.thisAsReceiverParameter) + + val newDescriptor = copyBuilder.build()!! + + recordTransformedMemberDescriptor(oldDescriptor, newDescriptor) + } + + private fun createTransformedMemberPropertyDescriptor(oldDescriptor: PropertyDescriptor) { + val memberOwner = localClasses[oldDescriptor.containingDeclaration]!!.transformedDescriptor + + val newDescriptor = PropertyDescriptorImpl.create( + memberOwner, + oldDescriptor.annotations, + oldDescriptor.modality, + oldDescriptor.visibility, + oldDescriptor.isVar, + oldDescriptor.name, + oldDescriptor.kind, + oldDescriptor.source, + oldDescriptor.isLateInit, + oldDescriptor.isConst, + oldDescriptor.isHeader, + oldDescriptor.isImpl, + oldDescriptor.isExternal + ) + + val newDispatchReceiver = memberOwner.thisAsReceiverParameter + + newDescriptor.setType(oldDescriptor.type, oldDescriptor.typeParameters, + newDispatchReceiver, oldDescriptor.extensionReceiverParameter?.type) + + val oldGetter = oldDescriptor.getter + val newGetter = if (oldGetter == null) { + null + } else { + PropertyGetterDescriptorImpl( + newDescriptor, oldGetter.annotations, + oldGetter.modality, oldGetter.visibility, oldGetter.isDefault, + oldGetter.isExternal, oldGetter.isInline, oldGetter.kind, + /* original = */ oldGetter, + oldGetter.source + ).apply { + this.initialize(oldGetter.returnType) + recordTransformedMemberDescriptor(oldGetter, this) + } } - return newDescriptor + val oldSetter = oldDescriptor.setter + val newSetter = if (oldSetter == null) { + null + } else { + PropertySetterDescriptorImpl( + newDescriptor, oldSetter.annotations, + oldSetter.modality, oldSetter.visibility, oldSetter.isDefault, + oldSetter.isExternal, oldSetter.isInline, oldSetter.kind, + /* original = */ oldSetter, + oldSetter.source + ).apply { + val parameter = PropertySetterDescriptorImpl.createSetterParameter(this, + oldSetter.valueParameters.single().type) + + this.initialize(parameter) + recordTransformedMemberDescriptor(oldSetter, this) + } + } + + newDescriptor.initialize(newGetter, newSetter) + + recordTransformedMemberDescriptor(oldDescriptor, newDescriptor) } - private fun LocalFunctionContext.recordRemapped(oldDescriptor: ValueDescriptor, newDescriptor: ParameterDescriptor): ParameterDescriptor { - old2new[oldDescriptor] = newDescriptor - new2old[newDescriptor] = oldDescriptor - return newDescriptor + private fun recordTransformedMemberDescriptor(oldDescriptor: CallableDescriptor, + newDescriptor: CallableDescriptor + ) { + + transformedDescriptors[oldDescriptor] = newDescriptor + + if (oldDescriptor.valueParameters.size != newDescriptor.valueParameters.size) throw AssertionError() + + oldDescriptor.valueParameters.forEach { + recordRemappedParameter(it, newDescriptor.valueParameters[it.index]) + } + + val oldDispatchReceiverParameter = oldDescriptor.dispatchReceiverParameter ?: + throw AssertionError("members of local classes must have dispatch receiver") + + recordRemappedParameter(oldDispatchReceiverParameter, newDescriptor.dispatchReceiverParameter!!) + + oldDescriptor.extensionReceiverParameter?.let { + recordRemappedParameter(it, newDescriptor.extensionReceiverParameter!!) + } } - private fun suggestNameForCapturedValueParameter(valueDescriptor: ValueDescriptor): Name = + private fun createTransformedConstructorDescriptor(localFunctionContext: LocalClassConstructorContext) { + val oldDescriptor = localFunctionContext.descriptor + val localClassContext = localClasses[oldDescriptor.containingDeclaration]!! + val newDescriptor = ClassConstructorDescriptorImpl.create( + localClassContext.transformedDescriptor, + Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source) + + localFunctionContext.transformedDescriptor = newDescriptor + transformedDescriptors[oldDescriptor] = newDescriptor + + // Do not substitute type parameters for now. + val newTypeParameters = oldDescriptor.typeParameters + + val capturedValues = localClassContext.closure.capturedValues + + val newValueParameters = createTransformedValueParameters(localFunctionContext, capturedValues) + + newDescriptor.initialize( + newValueParameters, + Visibilities.PRIVATE, + newTypeParameters + ) + + oldDescriptor.dispatchReceiverParameter?.let { + recordRemappedParameter(it, newDescriptor.dispatchReceiverParameter!!) + } + + oldDescriptor.extensionReceiverParameter?.let { + throw AssertionError("constructors can't have extension receiver") + } + } + + private fun createLiftedDescriptor(localClassContext: LocalClassContext) { + val irClass = localClassContext.declaration + val oldDescriptor = irClass.descriptor + + val memberOwner = memberFunction.descriptor.containingDeclaration + val newDescriptor = ClassDescriptorImpl(memberOwner, + generateNameForLiftedDeclaration(oldDescriptor, memberOwner), + oldDescriptor.modality, + oldDescriptor.kind, + oldDescriptor.typeConstructor.supertypes, + oldDescriptor.source, + oldDescriptor.isExternal) + + localClassContext.transformedDescriptor = newDescriptor + transformedDescriptors[oldDescriptor] = newDescriptor + + createFieldsForCapturedValues(localClassContext) + } + + private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) { + val newDescriptor = localClassContext.transformedDescriptor + + localClassContext.closure.capturedValues.forEach { capturedValue -> + val fieldDescriptor = PropertyDescriptorImpl.create( + newDescriptor, + Annotations.EMPTY, + Modality.FINAL, + Visibilities.PRIVATE, + /* isVar = */ false, + suggestNameForCapturedValue(capturedValue), + CallableMemberDescriptor.Kind.SYNTHESIZED, + SourceElement.NO_SOURCE, + /* lateInit = */ false, + /* isConst = */ false, + /* isHeader = */ false, + /* isImpl = */ false, + /* isExternal = */ false) + + fieldDescriptor.initialize(/* getter = */ null, /* setter = */ null) + + val extensionReceiverParameter: ReceiverParameterDescriptor? = null + + fieldDescriptor.setType( + capturedValue.type, + emptyList(), + newDescriptor.thisAsReceiverParameter, + extensionReceiverParameter) + + localClassContext.capturedValueToField[capturedValue] = fieldDescriptor + } + } + + private fun initializeClassDescriptor(localClassContext: LocalClassContext) { + val oldDescriptor = localClassContext.declaration.descriptor + + val constructors = oldDescriptor.constructors.map { + localClassConstructors[it]!!.transformedDescriptor + }.toSet() + + val newPrimaryConstructor = oldDescriptor.unsubstitutedPrimaryConstructor?.let { + localClassConstructors[it]!!.transformedDescriptor + } + + val newDescriptor = localClassContext.transformedDescriptor + + val oldContributedDescriptors = oldDescriptor.unsubstitutedMemberScope.getContributedDescriptors() + val callableMembers = oldContributedDescriptors + .filterIsInstance() + .filter { it.kind.isReal } + .map { it.transformed ?: TODO(it.toString()) } + + val otherMembers = oldContributedDescriptors.filter { it !is CallableMemberDescriptor } + + val fakeOverrides = computeOverrides(newDescriptor, callableMembers) + val newUnsubstitutedMemberScope = SimpleMemberScope(otherMembers + callableMembers + fakeOverrides) + + newDescriptor.initialize(newUnsubstitutedMemberScope, constructors, newPrimaryConstructor) + } + + private fun LocalContextWithClosureAsParameters.recordCapturedAsParameter( + oldDescriptor: ValueDescriptor, + newDescriptor: ValueParameterDescriptor + ) { + + capturedValueToParameter[oldDescriptor] = newDescriptor + newParameterToCaptured[newDescriptor] = oldDescriptor + + } + + private fun MutableMap.putAbsentOrSame(key: K, value: V) { + val current = this.getOrPut(key, { value }) + + if (current != value) { + error("$current != $value") + } + } + + private fun recordRemappedParameter(oldDescriptor: ParameterDescriptor, newDescriptor: ParameterDescriptor) { + oldParameterToNew.putAbsentOrSame(oldDescriptor, newDescriptor) + newParameterToOld.putAbsentOrSame(newDescriptor, oldDescriptor) + } + + private fun suggestNameForCapturedValue(valueDescriptor: ValueDescriptor): Name = if (valueDescriptor.name.isSpecial) { val oldNameStr = valueDescriptor.name.asString() Name.identifier("$" + oldNameStr.substring(1, oldNameStr.length - 1)) @@ -317,7 +812,7 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain ValueParameterDescriptorImpl( newParameterOwner, null, index, valueDescriptor.annotations, - suggestNameForCapturedValueParameter(valueDescriptor), + suggestNameForCapturedValue(valueDescriptor), valueDescriptor.type, false, false, false, null, valueDescriptor.source ) @@ -332,40 +827,80 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain private fun collectClosures() { memberFunction.acceptChildrenVoid(object : AbstractClosureAnnotator() { - override fun visitClass(declaration: IrClass) { - // ignore local classes for now - return - } - override fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) { localFunctions[functionDescriptor]?.closure = closure } override fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) { - // ignore local classes for now + localClasses[classDescriptor]?.closure = closure } }) } - private fun collectLocalFunctions() { + private fun collectLocalDeclarations() { memberFunction.acceptChildrenVoid(object : IrElementVisitorVoid { - var lambdasCount = 0 override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) } + private fun DeclarationDescriptor.isClassMember() = when (this.containingDeclaration) { + is CallableDescriptor -> false + is ClassDescriptor -> true + else -> TODO(this.toString()) + } + + override fun visitProperty(declaration: IrProperty) { + declaration.acceptChildrenVoid(this) + + val descriptor = declaration.descriptor + assert (descriptor.isClassMember()) + localClassMembers.add(descriptor) + } + override fun visitFunction(declaration: IrFunction) { declaration.acceptChildrenVoid(this) - val localFunctionContext = LocalFunctionContext(declaration) - localFunctions[declaration.descriptor] = localFunctionContext - if (declaration.descriptor.name.isSpecial) { - localFunctionContext.index = lambdasCount++ + + val descriptor = declaration.descriptor + + if (descriptor.isClassMember()) { + localClassMembers.add(descriptor) + } else { + val localFunctionContext = LocalFunctionContext(declaration) + + localFunctions[descriptor] = localFunctionContext + + if (descriptor.name.isSpecial) { + localFunctionContext.index = lambdasCount++ + } } + + } + + override fun visitConstructor(declaration: IrConstructor) { + declaration.acceptChildrenVoid(this) + + val descriptor = declaration.descriptor + assert (descriptor.isClassMember()) + + localClassConstructors[descriptor] = LocalClassConstructorContext(declaration) } override fun visitClass(declaration: IrClass) { - // ignore local classes for now + declaration.acceptChildrenVoid(this) + + val descriptor = declaration.descriptor + + if (descriptor.isClassMember()) { + assert (descriptor.isInner) + localClassMembers.add(descriptor) + } else { + val localClassContext = LocalClassContext(declaration) + localClasses[descriptor] = localClassContext + if (descriptor.name.isSpecial) { + localClassContext.index = objectsCount++ + } + } } }) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt index 63af6735eb1..3451ad801eb 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt @@ -1,13 +1,20 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.BackendContext -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy +import org.jetbrains.kotlin.resolve.OverridingUtil +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.Printer class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns) @@ -33,4 +40,49 @@ inline fun FunctionIrGenerator.irBlock(expression: IrExpression, origin: IrState this.irBlock(expression.startOffset, expression.endOffset, origin, resultType, body) inline fun FunctionIrGenerator.irBlockBody(irElement: IrElement, body: IrBlockBodyBuilder.() -> Unit) = - this.irBlockBody(irElement.startOffset, irElement.endOffset, body) \ No newline at end of file + this.irBlockBody(irElement.startOffset, irElement.endOffset, body) + +fun computeOverrides(current: ClassDescriptor, functionsFromCurrent: List): List { + + val result = mutableListOf() + + val allSuperDescriptors = current.typeConstructor.supertypes + .flatMap { it.memberScope.getContributedDescriptors() } + .filterIsInstance() + + for ((name, group) in allSuperDescriptors.groupBy { it.name }) { + OverridingUtil.generateOverridesInFunctionGroup( + name, + /* membersFromSupertypes = */ group, + /* membersFromCurrent = */ functionsFromCurrent.filter { it.name == name }, + current, + object : NonReportingOverrideStrategy() { + override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { + result.add(fakeOverride) + } + + override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) { + error("Conflict in scope of $current: $fromSuper vs $fromCurrent") + } + } + ) + } + + return result +} + +class SimpleMemberScope(val members: List) : MemberScopeImpl() { + + override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = TODO() + + override fun getContributedVariables(name: Name, location: LookupLocation): Collection = TODO() + + override fun getContributedFunctions(name: Name, location: LookupLocation): Collection = TODO() + + override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean): Collection = + members.filter { kindFilter.accepts(it) && nameFilter(it.name) } + + override fun printScopeStructure(p: Printer) = TODO("not implemented") + +} \ No newline at end of file