Added lowering of property callable reference for provideDelegate.

PropertyDelegationLowering is now lowering all callable references to properties.
This commit is contained in:
Igor Chevdar
2017-03-03 16:46:36 +03:00
parent 2d3879ea0d
commit 7d433be68b
@@ -46,7 +46,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
} }
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
val kProperties = mutableListOf<IrExpression>() val kProperties = mutableMapOf<VariableDescriptorWithAccessors, Pair<IrExpression, Int>>()
val getter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND).single() val getter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND).single()
val typeParameterT = genericArrayType.declaredTypeParameters[0] val typeParameterT = genericArrayType.declaredTypeParameters[0]
@@ -63,62 +63,49 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty): IrStatement { override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty): IrStatement {
declaration.transformChildrenVoid(this) declaration.transformChildrenVoid(this)
val name = declaration.descriptor.name.asString()
val type = declaration.descriptor.type
val initializer = declaration.delegate.initializer!! val initializer = declaration.delegate.initializer!!
return IrVariableImpl(declaration.startOffset, declaration.endOffset, return IrVariableImpl(declaration.startOffset, declaration.endOffset,
declaration.origin, declaration.delegate.descriptor, declaration.origin, declaration.delegate.descriptor,
IrBlockImpl(initializer.startOffset, initializer.endOffset, initializer.type, null, IrBlockImpl(initializer.startOffset, initializer.endOffset, initializer.type, null,
listOf( listOf(
transformBridgeToDelegate(name, type, declaration.getter), declaration.getter,
transformBridgeToDelegate(name, type, declaration.setter), declaration.setter,
initializer initializer
).filterNotNull()) ).filterNotNull())
) )
} }
override fun visitProperty(declaration: IrProperty): IrStatement {
declaration.transformChildrenVoid(this)
if (declaration.isDelegated) {
val name = declaration.descriptor.name.asString()
val type = declaration.descriptor.returnType!!
declaration.getter = transformBridgeToDelegate(name, type, declaration.getter)
declaration.setter = transformBridgeToDelegate(name, type, declaration.setter)
}
return declaration
}
private fun transformBridgeToDelegate(name: String, type: KotlinType, irFunction: IrFunction?): IrFunction? {
irFunction?.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCallableReference(expression: IrCallableReference): IrExpression { override fun visitCallableReference(expression: IrCallableReference): IrExpression {
val fieldInitializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expression.transformChildrenVoid(this)
getKPropertyImplConstructorDescriptorWithProjection(type)).apply { val propertyDescriptor = expression.descriptor as? VariableDescriptorWithAccessors
if (propertyDescriptor == null) return expression
val field = kProperties.getOrPut(propertyDescriptor) {
val initializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
getKPropertyImplConstructorDescriptorWithProjection(propertyDescriptor.type)).apply {
putValueArgument(0, IrConstImpl<String>(UNDEFINED_OFFSET, UNDEFINED_OFFSET, putValueArgument(0, IrConstImpl<String>(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.builtIns.stringType, IrConstKind.String, name)) context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString()))
} }
val index = kProperties.size val index = kProperties.size
kProperties.add(fieldInitializer)
initializer to index
}
return IrCallImpl(expression.startOffset, expression.endOffset, substitutedGetter).apply { return IrCallImpl(expression.startOffset, expression.endOffset, substitutedGetter).apply {
dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField) dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField)
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, index)) putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second))
} }
} }
}) })
return irFunction
}
}) if (kProperties.isNotEmpty()) {
val initializers = kProperties.values.sortedBy { it.second }.map { it.first }
if (kProperties.size > 0) {
irFile.declarations.add(0, IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFile.declarations.add(0, IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
kPropertiesField, kPropertiesField,
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.createArrayOfExpression(kPropertyImplType, kProperties)))) context.createArrayOfExpression(kPropertyImplType, initializers))))
} }
} }