Underlying classes for enum entries.
This commit is contained in:
committed by
Dmitry Petrov
parent
bd76e39a8c
commit
9eeb492fe3
@@ -146,39 +146,65 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
|
|||||||
private fun generateSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject) {
|
private fun generateSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject) {
|
||||||
val classDescriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
|
val classDescriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
|
||||||
|
|
||||||
if (classDescriptor.kind == ClassKind.ENUM_CLASS) {
|
when (classDescriptor.kind) {
|
||||||
val kotlinEnumConstructor = context.builtIns.enum.unsubstitutedPrimaryConstructor!!
|
ClassKind.ENUM_CLASS -> {
|
||||||
irBlockBody.addStatement(IrEnumConstructorCallImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset, kotlinEnumConstructor))
|
val kotlinEnumConstructor = context.builtIns.enum.unsubstitutedPrimaryConstructor!!
|
||||||
return
|
irBlockBody.addStatement(IrEnumConstructorCallImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset,
|
||||||
}
|
kotlinEnumConstructor, null))
|
||||||
|
}
|
||||||
val ktSuperTypeList = ktClassOrObject.getSuperTypeList() ?: return
|
ClassKind.ENUM_ENTRY -> {
|
||||||
for (ktSuperTypeListEntry in ktSuperTypeList.entries) {
|
irBlockBody.addStatement(generateEnumEntrySuperConstructorCall(ktClassOrObject as KtEnumEntry, classDescriptor))
|
||||||
if (ktSuperTypeListEntry is KtSuperTypeCallEntry) {
|
}
|
||||||
val statementGenerator = createStatementGenerator()
|
else -> {
|
||||||
val superConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperTypeListEntry)!!)
|
val ktSuperTypeList = ktClassOrObject.getSuperTypeList() ?: return
|
||||||
val irSuperConstructorCall = CallGenerator(statementGenerator).generateCall(
|
for (ktSuperTypeListEntry in ktSuperTypeList.entries) {
|
||||||
ktSuperTypeListEntry, superConstructorCall, IrOperator.SUPER_CONSTRUCTOR_CALL)
|
if (ktSuperTypeListEntry is KtSuperTypeCallEntry) {
|
||||||
irBlockBody.addStatement(irSuperConstructorCall)
|
val statementGenerator = createStatementGenerator()
|
||||||
|
val superConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperTypeListEntry)!!)
|
||||||
|
val irSuperConstructorCall = CallGenerator(statementGenerator).generateCall(
|
||||||
|
ktSuperTypeListEntry, superConstructorCall, IrOperator.SUPER_CONSTRUCTOR_CALL)
|
||||||
|
irBlockBody.addStatement(irSuperConstructorCall)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateEnumEntrySuperConstructorCall(ktEnumEntry: KtEnumEntry, enumEntryDescriptor: ClassDescriptor): IrExpression {
|
||||||
|
return generateEnumConstructorCallOrSuperCall(ktEnumEntry, enumEntryDescriptor.containingDeclaration as ClassDescriptor, null)
|
||||||
|
}
|
||||||
|
|
||||||
fun generateEnumEntryInitializer(ktEnumEntry: KtEnumEntry, enumEntryDescriptor: ClassDescriptor): IrExpression {
|
fun generateEnumEntryInitializer(ktEnumEntry: KtEnumEntry, enumEntryDescriptor: ClassDescriptor): IrExpression {
|
||||||
|
// Enum entry with body has a corresponding underlying class
|
||||||
|
if (ktEnumEntry.getBody() != null) {
|
||||||
|
val enumEntryConstructor = enumEntryDescriptor.unsubstitutedPrimaryConstructor!!
|
||||||
|
return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset,
|
||||||
|
enumEntryConstructor, enumEntryDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateEnumConstructorCallOrSuperCall(ktEnumEntry, enumEntryDescriptor.containingDeclaration as ClassDescriptor, enumEntryDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateEnumConstructorCallOrSuperCall(
|
||||||
|
ktEnumEntry: KtEnumEntry,
|
||||||
|
enumClassDescriptor: ClassDescriptor,
|
||||||
|
enumEntryOrNull: ClassDescriptor?
|
||||||
|
): IrExpression {
|
||||||
val statementGenerator = createStatementGenerator()
|
val statementGenerator = createStatementGenerator()
|
||||||
|
|
||||||
val ktSuperCallElement = ktEnumEntry.getSuperTypeListEntries().firstOrNull()
|
// Entry constructor with argument(s)
|
||||||
|
ktEnumEntry.getSuperTypeListEntries().firstOrNull()?.let { ktSuperCallElement ->
|
||||||
if (ktSuperCallElement != null) {
|
|
||||||
val enumConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperCallElement)!!)
|
val enumConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperCallElement)!!)
|
||||||
return CallGenerator(statementGenerator).generateEnumConstructorSuperCall(
|
return CallGenerator(statementGenerator).generateEnumConstructorSuperCall(
|
||||||
ktEnumEntry.startOffset, ktEnumEntry.endOffset, enumConstructorCall, enumEntryDescriptor)
|
ktEnumEntry.startOffset, ktEnumEntry.endOffset,
|
||||||
|
enumConstructorCall, enumEntryOrNull)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No-argument enum entry constructor
|
// No-argument enum entry constructor
|
||||||
val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
|
|
||||||
val enumClassConstructor = enumClassDescriptor.unsubstitutedPrimaryConstructor!!
|
val enumClassConstructor = enumClassDescriptor.unsubstitutedPrimaryConstructor!!
|
||||||
return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset, enumClassConstructor, enumEntryDescriptor)
|
return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset,
|
||||||
|
enumClassConstructor, enumEntryOrNull)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateNestedInitializersBody(ktClassOrObject: KtClassOrObject): IrBody {
|
fun generateNestedInitializersBody(ktClassOrObject: KtClassOrObject): IrBody {
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateEnumConstructorSuperCall(startOffset: Int, endOffset: Int, call: CallBuilder, enumEntryDescriptor: ClassDescriptor) : IrExpression {
|
fun generateEnumConstructorSuperCall(startOffset: Int, endOffset: Int, call: CallBuilder,
|
||||||
|
enumEntryDescriptor: ClassDescriptor?) : IrExpression {
|
||||||
val constructorDescriptor = call.descriptor
|
val constructorDescriptor = call.descriptor
|
||||||
if (constructorDescriptor !is ConstructorDescriptor) throw AssertionError("Constructor expected: $constructorDescriptor")
|
if (constructorDescriptor !is ConstructorDescriptor) throw AssertionError("Constructor expected: $constructorDescriptor")
|
||||||
val classDescriptor = constructorDescriptor.containingDeclaration
|
val classDescriptor = constructorDescriptor.containingDeclaration
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
|||||||
BodyGenerator(enumEntryDescriptor.containingDeclaration, context)
|
BodyGenerator(enumEntryDescriptor.containingDeclaration, context)
|
||||||
.generateEnumEntryInitializer(ktEnumEntry, enumEntryDescriptor)
|
.generateEnumEntryInitializer(ktEnumEntry, enumEntryDescriptor)
|
||||||
|
|
||||||
ktEnumEntry.getBody()?.let { ktEnumEntryBody ->
|
if (ktEnumEntry.getBody() != null) {
|
||||||
// TODO
|
irEnumEntry.correspondingClass = generateClass(ktEnumEntry)
|
||||||
}
|
}
|
||||||
|
|
||||||
return irEnumEntry
|
return irEnumEntry
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ enum class IrDeclarationKind {
|
|||||||
|
|
||||||
enum class IrDeclarationOrigin {
|
enum class IrDeclarationOrigin {
|
||||||
DEFINED,
|
DEFINED,
|
||||||
|
CLASS_FOR_ENUM_ENTRY,
|
||||||
GENERATED_DATA_CLASS_MEMBER,
|
GENERATED_DATA_CLASS_MEMBER,
|
||||||
LOCAL_FUNCTION_FOR_LAMBDA,
|
LOCAL_FUNCTION_FOR_LAMBDA,
|
||||||
IR_TEMPORARY_VARIABLE,
|
IR_TEMPORARY_VARIABLE,
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ interface IrEnumConstructorCall : IrGeneralCall {
|
|||||||
val enumEntryDescriptor: ClassDescriptor?
|
val enumEntryDescriptor: ClassDescriptor?
|
||||||
}
|
}
|
||||||
|
|
||||||
val IrEnumConstructorCall.isDelegating: Boolean
|
val IrEnumConstructorCall.isSuper: Boolean
|
||||||
get() = enumEntryDescriptor == null
|
get() = enumEntryDescriptor == null
|
||||||
|
|
||||||
class IrEnumConstructorCallImpl(
|
class IrEnumConstructorCallImpl(
|
||||||
|
|||||||
+29
@@ -6,4 +6,33 @@ enum class TestEnum2(val x: Int) {
|
|||||||
TEST1(1),
|
TEST1(1),
|
||||||
TEST2(2),
|
TEST2(2),
|
||||||
TEST3(3)
|
TEST3(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class TestEnum3 {
|
||||||
|
TEST {
|
||||||
|
override fun foo() {
|
||||||
|
println("Hello, world!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
abstract fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class TestEnum4(val x: Int) {
|
||||||
|
TEST1(1) {
|
||||||
|
override fun foo() {
|
||||||
|
println(TEST1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TEST2(2) {
|
||||||
|
val z: Int
|
||||||
|
init {
|
||||||
|
z = x
|
||||||
|
}
|
||||||
|
override fun foo() {
|
||||||
|
println(TEST2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
abstract fun foo()
|
||||||
}
|
}
|
||||||
+52
@@ -25,3 +25,55 @@ FILE /enum.kt
|
|||||||
ENUM_ENTRY enum entry TEST3
|
ENUM_ENTRY enum entry TEST3
|
||||||
init: ENUM_CONSTRUCTOR_CALL TestEnum2 TEST3
|
init: ENUM_CONSTRUCTOR_CALL TestEnum2 TEST3
|
||||||
x: CONST Int type=kotlin.Int value='3'
|
x: CONST Int type=kotlin.Int value='3'
|
||||||
|
CLASS ENUM_CLASS TestEnum3
|
||||||
|
FUN private constructor TestEnum3()
|
||||||
|
BLOCK_BODY
|
||||||
|
ENUM_CONSTRUCTOR_CALL Enum super
|
||||||
|
ENUM_ENTRY enum entry TEST
|
||||||
|
init: ENUM_CONSTRUCTOR_CALL TEST TEST
|
||||||
|
class: CLASS ENUM_ENTRY TEST
|
||||||
|
FUN private constructor TEST()
|
||||||
|
BLOCK_BODY
|
||||||
|
ENUM_CONSTRUCTOR_CALL TestEnum3 super
|
||||||
|
FUN public open override /*1*/ fun foo(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .println type=kotlin.Unit operator=null
|
||||||
|
message: CONST String type=kotlin.String value='Hello, world!'
|
||||||
|
FUN public abstract fun foo(): kotlin.Unit
|
||||||
|
CLASS ENUM_CLASS TestEnum4
|
||||||
|
FUN private constructor TestEnum4(/*0*/ x: kotlin.Int)
|
||||||
|
BLOCK_BODY
|
||||||
|
ENUM_CONSTRUCTOR_CALL Enum super
|
||||||
|
SET_BACKING_FIELD x type=kotlin.Unit operator=null
|
||||||
|
GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||||
|
PROPERTY public final val x: kotlin.Int
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||||
|
ENUM_ENTRY enum entry TEST1
|
||||||
|
init: ENUM_CONSTRUCTOR_CALL TEST1 TEST1
|
||||||
|
class: CLASS ENUM_ENTRY TEST1
|
||||||
|
FUN private constructor TEST1()
|
||||||
|
BLOCK_BODY
|
||||||
|
ENUM_CONSTRUCTOR_CALL TestEnum4 super
|
||||||
|
x: CONST Int type=kotlin.Int value='1'
|
||||||
|
FUN public open override /*1*/ fun foo(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .println type=kotlin.Unit operator=null
|
||||||
|
message: GET_ENUM_VALUE TEST1 type=TestEnum4
|
||||||
|
ENUM_ENTRY enum entry TEST2
|
||||||
|
init: ENUM_CONSTRUCTOR_CALL TEST2 TEST2
|
||||||
|
class: CLASS ENUM_ENTRY TEST2
|
||||||
|
FUN private constructor TEST2()
|
||||||
|
BLOCK_BODY
|
||||||
|
ENUM_CONSTRUCTOR_CALL TestEnum4 super
|
||||||
|
x: CONST Int type=kotlin.Int value='2'
|
||||||
|
BLOCK type=kotlin.Unit operator=null
|
||||||
|
SET_BACKING_FIELD z type=kotlin.Unit operator=null
|
||||||
|
CALL .<get-x> type=kotlin.Int operator=GET_PROPERTY
|
||||||
|
$this: THIS enum entry TEST2 type=TestEnum4.TEST2
|
||||||
|
PROPERTY public final val z: kotlin.Int
|
||||||
|
FUN public open override /*1*/ fun foo(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .println type=kotlin.Unit operator=null
|
||||||
|
message: GET_ENUM_VALUE TEST2 type=TestEnum4
|
||||||
|
FUN public abstract fun foo(): kotlin.Unit
|
||||||
|
|||||||
Reference in New Issue
Block a user