Support default impls
This commit is contained in:
committed by
Dmitry Petrov
parent
7950235df3
commit
011ed60eee
@@ -16,8 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
|
||||
object JvmDeclarationOrigins {
|
||||
interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER")
|
||||
object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPL")
|
||||
}
|
||||
|
||||
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
||||
object DEFAULT_IMPLS_DELEGATION : IrStatementOrigin.IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION")
|
||||
}
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.FileClassLowering
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.InitializersLowering
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.PropertiesLowering
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
@@ -28,6 +26,8 @@ class JvmLower(val context: JvmBackendContext) {
|
||||
FileClassLowering(context.jvmFileClassProvider).lower(irFile)
|
||||
PropertiesLowering().lower(irFile)
|
||||
InitializersLowering().runOnNormalizedFile(irFile)
|
||||
InterfaceLowering(context.state).runOnNormalizedFile(irFile)
|
||||
InterfaceDelegationLowering(context.state).runOnNormalizedFile(irFile)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-9
@@ -19,11 +19,8 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.SuperClassInfo
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
@@ -99,6 +96,9 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac
|
||||
is IrAnonymousInitializer -> {
|
||||
// skip
|
||||
}
|
||||
is IrClass -> {
|
||||
ClassCodegen(declaration, context).generate()
|
||||
}
|
||||
else -> throw RuntimeException("Unsupported declaration $declaration")
|
||||
}
|
||||
}
|
||||
@@ -118,9 +118,8 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac
|
||||
}
|
||||
|
||||
fun ClassDescriptor.calculateClassFlags(): Int {
|
||||
return (if (!DescriptorUtils.isInterface(this)) Opcodes.ACC_SUPER else 0).
|
||||
or(calculateCommonFlags()).
|
||||
or(if (DescriptorUtils.isInterface(this)) Opcodes.ACC_INTERFACE else 0)
|
||||
return (if (DescriptorUtils.isInterface(this)) Opcodes.ACC_INTERFACE else Opcodes.ACC_SUPER).
|
||||
or(calcModalityFlag()).or(AsmUtil.getVisibilityAccessFlagForClass(this))
|
||||
}
|
||||
|
||||
fun MemberDescriptor.calculateCommonFlags(): Int {
|
||||
@@ -138,6 +137,11 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
||||
throw RuntimeException("Unsupported visibility $visibility for descriptor $this")
|
||||
}
|
||||
|
||||
return flags.or(calcModalityFlag())
|
||||
}
|
||||
|
||||
private fun MemberDescriptor.calcModalityFlag(): Int {
|
||||
var flags = 0
|
||||
when (modality) {
|
||||
Modality.ABSTRACT -> {
|
||||
flags = flags.or(Opcodes.ACC_ABSTRACT)
|
||||
@@ -150,7 +154,7 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
||||
Modality.OPEN -> {
|
||||
assert(!Visibilities.isPrivate(visibility))
|
||||
}
|
||||
else -> throw RuntimeException("Unsupported modality $modality for descriptor $this")
|
||||
else -> throw RuntimeException("Unsupported modality $modality for descriptor ${this}")
|
||||
}
|
||||
|
||||
if (this is CallableMemberDescriptor) {
|
||||
@@ -158,7 +162,6 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
||||
flags = flags or Opcodes.ACC_STATIC
|
||||
}
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ class ExpressionCodegen(
|
||||
} else {
|
||||
val receiver = expression.dispatchReceiver
|
||||
receiver?.apply {
|
||||
gen(receiver, callable.owner, data)
|
||||
gen(receiver, callable.dispatchReceiverType!!, data)
|
||||
}
|
||||
|
||||
val args = (listOf(expression.extensionReceiver).filterNotNull() +
|
||||
|
||||
+26
-6
@@ -16,24 +16,44 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.InitializersLowering
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen.createFrameMap
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_STATIC
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class FunctionCodegen(val irFunction: IrFunction, val classCodegen: ClassCodegen) {
|
||||
fun generate() {
|
||||
val signature = classCodegen.typeMapper.mapSignatureWithGeneric(irFunction.descriptor, OwnerKind.IMPLEMENTATION)
|
||||
val isStatic = isStaticMethod(classCodegen.descriptor.getMemberOwnerKind(), irFunction.descriptor)
|
||||
val frameMap = createFrameMap(classCodegen.state, irFunction.descriptor, signature, isStatic)
|
||||
|
||||
val state = classCodegen.state
|
||||
|
||||
val descriptor = irFunction.descriptor
|
||||
|
||||
fun generate() {
|
||||
val signature = classCodegen.typeMapper.mapSignatureWithGeneric(descriptor, OwnerKind.IMPLEMENTATION)
|
||||
val isStatic = isStaticMethod(classCodegen.descriptor.getMemberOwnerKind(), descriptor) || DescriptorUtils.isStaticDeclaration(descriptor)
|
||||
val frameMap = createFrameMap(classCodegen.state, descriptor, signature, isStatic)
|
||||
|
||||
var flags = AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION, state).or(if (isStatic) Opcodes.ACC_STATIC else 0)
|
||||
val interfaceClInit = JvmCodegenUtil.isJvmInterface(classCodegen.descriptor) && InitializersLowering.clinitName == descriptor.name
|
||||
if (interfaceClInit) {
|
||||
//reset abstract flag
|
||||
flags = flags.xor(Opcodes.ACC_ABSTRACT)
|
||||
}
|
||||
val methodVisitor = classCodegen.visitor.newMethod(irFunction.OtherOrigin,
|
||||
irFunction.descriptor.calculateCommonFlags().or(if (isStatic) ACC_STATIC else 0),
|
||||
flags,
|
||||
signature.asmMethod.name, signature.asmMethod.descriptor,
|
||||
signature.genericsSignature, null/*TODO support exception*/)
|
||||
|
||||
if (!state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0) {
|
||||
methodVisitor.visitEnd()
|
||||
return
|
||||
}
|
||||
|
||||
ExpressionCodegen(irFunction, frameMap, InstructionAdapter(methodVisitor), classCodegen).generate()
|
||||
}
|
||||
}
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
interface DefaultImplsClassDescriptor : ClassDescriptor {
|
||||
val correspondingInterface: ClassDescriptor
|
||||
}
|
||||
|
||||
class DefaultImplsClassDescriptorImpl(
|
||||
private val nameImpl: Name,
|
||||
override val correspondingInterface: ClassDescriptor,
|
||||
private val sourceElement: SourceElement
|
||||
) : DefaultImplsClassDescriptor {
|
||||
override fun getCompanionObjectDescriptor(): ClassDescriptor? = null
|
||||
override fun getConstructors(): Collection<ClassConstructorDescriptor> = emptyList()
|
||||
override fun getContainingDeclaration(): DeclarationDescriptor = correspondingInterface
|
||||
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> = emptyList()
|
||||
override fun getKind(): ClassKind = ClassKind.CLASS
|
||||
|
||||
override fun getMemberScope(typeSubstitution: TypeSubstitution): MemberScope = error("File class has no member scope")
|
||||
override fun getModality(): Modality = Modality.FINAL
|
||||
override fun getOriginal(): ClassDescriptor = this
|
||||
override fun getName(): Name = nameImpl
|
||||
override fun getStaticScope(): MemberScope = error("File class has no static scope")
|
||||
override fun getThisAsReceiverParameter(): ReceiverParameterDescriptor = error("File class has no instances")
|
||||
override fun getUnsubstitutedInnerClassesScope(): MemberScope = error("File class has no inner classes scope")
|
||||
override fun getUnsubstitutedMemberScope(): MemberScope = error("File class has no member scope")
|
||||
override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = null
|
||||
override fun getVisibility(): Visibility = Visibilities.PUBLIC
|
||||
override fun isCompanionObject(): Boolean = false
|
||||
override fun isData(): Boolean = false
|
||||
override fun substitute(substitutor: TypeSubstitutor): ClassDescriptor = error("File class can't be substituted")
|
||||
override fun getSource(): SourceElement = sourceElement
|
||||
override fun isInner(): Boolean = false
|
||||
|
||||
override val annotations = Annotations.EMPTY
|
||||
|
||||
private val typeConstructor = ClassTypeConstructorImpl(this, annotations, true, emptyList(), listOf(builtIns.anyType))
|
||||
private val defaultType = KotlinTypeFactory.simpleNotNullType(annotations, this, emptyList())
|
||||
|
||||
override fun getTypeConstructor(): TypeConstructor = typeConstructor
|
||||
|
||||
override fun getDefaultType(): SimpleType = defaultType
|
||||
|
||||
override fun getMemberScope(typeArguments: MutableList<out TypeProjection>): MemberScope =
|
||||
MemberScope.Empty // TODO do we need a more useful MemberScope here?
|
||||
|
||||
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R {
|
||||
return visitor.visitClassDescriptor(this, data)
|
||||
}
|
||||
|
||||
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>) {
|
||||
visitor.visitClassDescriptor(this, null)
|
||||
}
|
||||
|
||||
override fun toString(): String =
|
||||
"IrFileClassDescriptor($fqNameUnsafe)"
|
||||
}
|
||||
+2
-2
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmDeclarationOrigins
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.getMemberOwnerKind
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -127,7 +127,7 @@ class InitializersLowering : ClassLoweringPass {
|
||||
Modality.FINAL, Visibilities.PUBLIC
|
||||
)
|
||||
irClass.declarations.add(
|
||||
IrFunctionImpl(irClass.startOffset, irClass.endOffset, JvmDeclarationOrigins.CLASS_STATIC_INITIALIZER,
|
||||
IrFunctionImpl(irClass.startOffset, irClass.endOffset, JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER,
|
||||
staticInitializerDescriptor,
|
||||
IrBlockBodyImpl(irClass.startOffset, irClass.endOffset,
|
||||
staticInitializerStatements.map { it.copy() }))
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.isDefinitelyNotDefaultImplsMethod
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
|
||||
class InterfaceDelegationLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass {
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
val descriptor = irClass.descriptor
|
||||
if (!DescriptorUtils.isClass(descriptor)) {
|
||||
return
|
||||
}
|
||||
|
||||
irClass.transformChildrenVoid(this)
|
||||
generateInterfaceMethods(irClass, descriptor)
|
||||
}
|
||||
|
||||
|
||||
private fun generateInterfaceMethods(irClass: IrClass, descriptor: ClassDescriptor) {
|
||||
val classDescriptor = if (descriptor is DefaultImplsClassDescriptor) descriptor.correspondingInterface else descriptor
|
||||
for ((interfaceFun, value) in CodegenUtil.getNonPrivateTraitMethods(classDescriptor)) {
|
||||
//skip java 8 default methods
|
||||
if (!interfaceFun.isDefinitelyNotDefaultImplsMethod()) {
|
||||
val inheritedFun =
|
||||
if (classDescriptor !== descriptor) {
|
||||
InterfaceLowering.createDefaultImplFunDescriptor(descriptor as DefaultImplsClassDescriptorImpl, interfaceFun, classDescriptor)
|
||||
}
|
||||
else {
|
||||
value
|
||||
}
|
||||
generateDelegationToDefaultImpl(irClass, interfaceFun, inheritedFun)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDelegationToDefaultImpl(irClass: IrClass, interfaceFun: FunctionDescriptor, inheritedFun: FunctionDescriptor) {
|
||||
val irBody = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
||||
val irFunction = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, inheritedFun, irBody)
|
||||
irClass.declarations.add(irFunction)
|
||||
|
||||
val interfaceDescriptor = interfaceFun.containingDeclaration as ClassDescriptor
|
||||
val defaultImpls = InterfaceLowering.createDefaultImplsClassDescriptor(interfaceDescriptor)
|
||||
val defaultImplFun = InterfaceLowering.createDefaultImplFunDescriptor(defaultImpls, interfaceFun, interfaceDescriptor)
|
||||
val returnType = inheritedFun.returnType!!
|
||||
val irCallImpl = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, defaultImplFun, null, JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION)
|
||||
irBody.statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, inheritedFun, irCallImpl))
|
||||
|
||||
var shift = 0
|
||||
if (inheritedFun.dispatchReceiverParameter != null) {
|
||||
irCallImpl.putValueArgument(0, IrThisReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irClass.descriptor.defaultType, irClass.descriptor))
|
||||
shift = 1
|
||||
}
|
||||
inheritedFun.valueParameters.mapIndexed { i, valueParameterDescriptor ->
|
||||
irCallImpl.putValueArgument(i + shift, IrGetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueParameterDescriptor, null))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.isDefinitelyNotDefaultImplsMethod
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
|
||||
class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass {
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
if (!DescriptorUtils.isInterface(irClass.descriptor)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
val interfaceDescriptor = irClass.descriptor
|
||||
val defaultImplsDescriptor = createDefaultImplsClassDescriptor(interfaceDescriptor)
|
||||
val defaultImplsIrClass = IrClassImpl(irClass.startOffset, irClass.endOffset, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS, defaultImplsDescriptor)
|
||||
irClass.declarations.add(defaultImplsIrClass)
|
||||
|
||||
val members = defaultImplsIrClass.declarations
|
||||
|
||||
irClass.declarations.filterIsInstance<IrFunction>().mapNotNull {
|
||||
val descriptor = it.descriptor
|
||||
if (descriptor.modality != Modality.ABSTRACT) {
|
||||
val functionDescriptorImpl = createDefaultImplFunDescriptor(defaultImplsDescriptor, descriptor, interfaceDescriptor)
|
||||
|
||||
members.add(IrFunctionImpl(it.startOffset, it.endOffset, it.origin, functionDescriptorImpl, it.body))
|
||||
it.body = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
irClass.transformChildrenVoid(this)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
fun createDefaultImplsClassDescriptor(interfaceDescriptor: ClassDescriptor): DefaultImplsClassDescriptorImpl {
|
||||
return DefaultImplsClassDescriptorImpl(
|
||||
Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME), interfaceDescriptor, interfaceDescriptor.source
|
||||
)
|
||||
}
|
||||
|
||||
fun createDefaultImplFunDescriptor(
|
||||
defaultImplsDescriptor: DefaultImplsClassDescriptorImpl,
|
||||
descriptor: FunctionDescriptor,
|
||||
interfaceDescriptor: ClassDescriptor
|
||||
): SimpleFunctionDescriptorImpl {
|
||||
|
||||
val newFunction = SimpleFunctionDescriptorImpl.create(
|
||||
defaultImplsDescriptor, AnnotationsImpl(emptyList()), descriptor.name, descriptor.kind, descriptor.source
|
||||
)
|
||||
|
||||
val valueParameters =
|
||||
listOf(ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
|
||||
newFunction, null, 0, AnnotationsImpl(emptyList()), Name.identifier("this"),
|
||||
interfaceDescriptor.defaultType, false, false, false, false, null, interfaceDescriptor.source, null)
|
||||
) +
|
||||
descriptor.valueParameters.map { it.copy(newFunction, it.name, it.index + 1) }
|
||||
newFunction.initialize(
|
||||
null, null, emptyList()/*TODO: type parameters*/,
|
||||
valueParameters, descriptor.returnType, Modality.FINAL, descriptor.visibility
|
||||
)
|
||||
return newFunction
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
interface LoweredFunction: FunctionDescriptor
|
||||
|
||||
class LoweredFunctionImpl(containingDeclaration: DeclarationDescriptor,
|
||||
original: FunctionDescriptor,
|
||||
annotations: Annotations,
|
||||
name: Name,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
source: SourceElement) :
|
||||
FunctionDescriptorImpl(containingDeclaration, original, annotations, name, kind, source), LoweredFunction {
|
||||
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? {
|
||||
return super.getDispatchReceiverParameter()
|
||||
}
|
||||
|
||||
override fun createSubstitutedCopy(newOwner: DeclarationDescriptor, original: FunctionDescriptor?, kind: CallableMemberDescriptor.Kind, newName: Name?, annotations: Annotations, source: SourceElement): FunctionDescriptorImpl {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user