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 { override fun visitCallableReference(expression: IrCallableReference): IrExpression {
declaration.transformChildrenVoid(this) expression.transformChildrenVoid(this)
if (declaration.isDelegated) { val propertyDescriptor = expression.descriptor as? VariableDescriptorWithAccessors
val name = declaration.descriptor.name.asString() if (propertyDescriptor == null) return expression
val type = declaration.descriptor.returnType!! val field = kProperties.getOrPut(propertyDescriptor) {
declaration.getter = transformBridgeToDelegate(name, type, declaration.getter) val initializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
declaration.setter = transformBridgeToDelegate(name, type, declaration.setter) getKPropertyImplConstructorDescriptorWithProjection(propertyDescriptor.type)).apply {
} putValueArgument(0, IrConstImpl<String>(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
return declaration context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString()))
}
private fun transformBridgeToDelegate(name: String, type: KotlinType, irFunction: IrFunction?): IrFunction? {
irFunction?.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCallableReference(expression: IrCallableReference): IrExpression {
val fieldInitializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
getKPropertyImplConstructorDescriptorWithProjection(type)).apply {
putValueArgument(0, IrConstImpl<String>(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.builtIns.stringType, IrConstKind.String, name))
}
val index = kProperties.size
kProperties.add(fieldInitializer)
return IrCallImpl(expression.startOffset, expression.endOffset, substitutedGetter).apply {
dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField)
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, index))
}
} }
}) val index = kProperties.size
return irFunction
}
initializer to index
}
return IrCallImpl(expression.startOffset, expression.endOffset, substitutedGetter).apply {
dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField)
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second))
}
}
}) })
if (kProperties.size > 0) { if (kProperties.isNotEmpty()) {
val initializers = kProperties.values.sortedBy { it.second }.map { it.first }
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))))
} }
} }