Underlying classes for enum entries.

This commit is contained in:
Dmitry Petrov
2016-08-31 15:46:47 +03:00
committed by Dmitry Petrov
parent bd76e39a8c
commit 9eeb492fe3
7 changed files with 133 additions and 24 deletions
@@ -146,39 +146,65 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
private fun generateSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject) {
val classDescriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
if (classDescriptor.kind == ClassKind.ENUM_CLASS) {
val kotlinEnumConstructor = context.builtIns.enum.unsubstitutedPrimaryConstructor!!
irBlockBody.addStatement(IrEnumConstructorCallImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset, kotlinEnumConstructor))
return
}
val ktSuperTypeList = ktClassOrObject.getSuperTypeList() ?: return
for (ktSuperTypeListEntry in ktSuperTypeList.entries) {
if (ktSuperTypeListEntry is KtSuperTypeCallEntry) {
val statementGenerator = createStatementGenerator()
val superConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperTypeListEntry)!!)
val irSuperConstructorCall = CallGenerator(statementGenerator).generateCall(
ktSuperTypeListEntry, superConstructorCall, IrOperator.SUPER_CONSTRUCTOR_CALL)
irBlockBody.addStatement(irSuperConstructorCall)
when (classDescriptor.kind) {
ClassKind.ENUM_CLASS -> {
val kotlinEnumConstructor = context.builtIns.enum.unsubstitutedPrimaryConstructor!!
irBlockBody.addStatement(IrEnumConstructorCallImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset,
kotlinEnumConstructor, null))
}
ClassKind.ENUM_ENTRY -> {
irBlockBody.addStatement(generateEnumEntrySuperConstructorCall(ktClassOrObject as KtEnumEntry, classDescriptor))
}
else -> {
val ktSuperTypeList = ktClassOrObject.getSuperTypeList() ?: return
for (ktSuperTypeListEntry in ktSuperTypeList.entries) {
if (ktSuperTypeListEntry is KtSuperTypeCallEntry) {
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 {
// 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 ktSuperCallElement = ktEnumEntry.getSuperTypeListEntries().firstOrNull()
if (ktSuperCallElement != null) {
// Entry constructor with argument(s)
ktEnumEntry.getSuperTypeListEntries().firstOrNull()?.let { ktSuperCallElement ->
val enumConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperCallElement)!!)
return CallGenerator(statementGenerator).generateEnumConstructorSuperCall(
ktEnumEntry.startOffset, ktEnumEntry.endOffset, enumConstructorCall, enumEntryDescriptor)
ktEnumEntry.startOffset, ktEnumEntry.endOffset,
enumConstructorCall, enumEntryOrNull)
}
// No-argument enum entry constructor
val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
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 {
@@ -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
if (constructorDescriptor !is ConstructorDescriptor) throw AssertionError("Constructor expected: $constructorDescriptor")
val classDescriptor = constructorDescriptor.containingDeclaration
@@ -111,8 +111,8 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
BodyGenerator(enumEntryDescriptor.containingDeclaration, context)
.generateEnumEntryInitializer(ktEnumEntry, enumEntryDescriptor)
ktEnumEntry.getBody()?.let { ktEnumEntryBody ->
// TODO
if (ktEnumEntry.getBody() != null) {
irEnumEntry.correspondingClass = generateClass(ktEnumEntry)
}
return irEnumEntry
@@ -43,6 +43,7 @@ enum class IrDeclarationKind {
enum class IrDeclarationOrigin {
DEFINED,
CLASS_FOR_ENUM_ENTRY,
GENERATED_DATA_CLASS_MEMBER,
LOCAL_FUNCTION_FOR_LAMBDA,
IR_TEMPORARY_VARIABLE,
@@ -26,7 +26,7 @@ interface IrEnumConstructorCall : IrGeneralCall {
val enumEntryDescriptor: ClassDescriptor?
}
val IrEnumConstructorCall.isDelegating: Boolean
val IrEnumConstructorCall.isSuper: Boolean
get() = enumEntryDescriptor == null
class IrEnumConstructorCallImpl(
+29
View File
@@ -6,4 +6,33 @@ enum class TestEnum2(val x: Int) {
TEST1(1),
TEST2(2),
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
View File
@@ -25,3 +25,55 @@ FILE /enum.kt
ENUM_ENTRY enum entry TEST3
init: ENUM_CONSTRUCTOR_CALL TestEnum2 TEST3
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