[JS IR BE] Support external enum classes
* add lowering pass * fix EQEQ operator
This commit is contained in:
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
@@ -34,7 +35,6 @@ import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.getPropertyDeclaration
|
||||
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
|
||||
import org.jetbrains.kotlin.ir.util.referenceFunction
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -110,7 +110,7 @@ class JsIrBackendContext(
|
||||
private val coroutinePackage = module.getPackage(COROUTINE_PACKAGE_FQNAME)
|
||||
private val coroutineIntrinsicsPackage = module.getPackage(COROUTINE_INTRINSICS_PACKAGE_FQNAME)
|
||||
|
||||
val enumEntryToGetInstanceFunction = mutableMapOf<IrEnumEntrySymbol, IrSimpleFunctionSymbol>()
|
||||
val enumEntryToGetInstanceFunction = mutableMapOf<IrEnumEntrySymbol, () -> IrExpression>()
|
||||
|
||||
val coroutineGetContext: IrFunctionSymbol
|
||||
get() {
|
||||
|
||||
@@ -73,6 +73,7 @@ fun compile(
|
||||
moduleFragment.files.forEach { irFile -> extension.generate(irFile, context, psi2IrContext.bindingContext) }
|
||||
}
|
||||
|
||||
ExternalEnumLowering(context).runOnFilesPostfix(moduleFragment)
|
||||
MoveExternalDeclarationsToSeparatePlace().lower(moduleFragment)
|
||||
ExpectDeclarationsRemoving(context).lower(moduleFragment)
|
||||
CoroutineIntrinsicLowering(context).lower(moduleFragment)
|
||||
|
||||
+7
-9
@@ -35,7 +35,7 @@ class EnumUsageLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitGetEnumValue(expression: IrGetEnumValue) =
|
||||
JsIrBuilder.buildCall(context.enumEntryToGetInstanceFunction[expression.symbol]!!)
|
||||
context.enumEntryToGetInstanceFunction[expression.symbol]!!.invoke()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ class EnumClassLowering(val context: JsIrBackendContext) : DeclarationContainerL
|
||||
} else {
|
||||
EnumClassTransformer(context, declaration).transform()
|
||||
}
|
||||
} else
|
||||
} else
|
||||
listOf(declaration)
|
||||
}
|
||||
}
|
||||
@@ -137,9 +137,9 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
||||
irWhen(
|
||||
irClass.defaultType,
|
||||
enumEntries.map {
|
||||
val getInstance = entryInstanceToFunction[it.symbol]!!
|
||||
irBranch(
|
||||
irEquals(irString(it.name.identifier), irGet(nameParameter)), irCall(getInstance)
|
||||
irEquals(irString(it.name.identifier), irGet(nameParameter)),
|
||||
entryInstanceToFunction[it.symbol]!!.invoke()
|
||||
)
|
||||
} + irElseBranch(irCall(throwISESymbol))
|
||||
)
|
||||
@@ -163,10 +163,8 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
||||
return context.createIrBuilder(valuesFun.symbol).run {
|
||||
irBlockBody {
|
||||
+irReturn(
|
||||
enumEntries.map {
|
||||
val function = entryInstanceToFunction[it.symbol]!!
|
||||
irCall(function)
|
||||
}.toArrayLiteral(valuesFun.returnType, irClass.defaultType)
|
||||
enumEntries.map { entryInstanceToFunction[it.symbol]!!.invoke() }
|
||||
.toArrayLiteral(valuesFun.returnType, irClass.defaultType)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -246,7 +244,7 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
||||
+irCall(initEntryInstancesFun)
|
||||
+irReturn(irGet(entryInstances[index]))
|
||||
}.apply {
|
||||
context.enumEntryToGetInstanceFunction[enumEntry.symbol] = this@apply.symbol
|
||||
context.enumEntryToGetInstanceFunction[enumEntry.symbol] = { JsIrBuilder.buildCall(this@apply.symbol) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.isEnumClass
|
||||
|
||||
// TODO: Shouldn't it be lazy pass?
|
||||
class ExternalEnumLowering(val context: JsIrBackendContext) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
if (!irClass.isExternal) return
|
||||
if (!irClass.isEnumClass) return
|
||||
|
||||
irClass.declarations.filterIsInstance<IrEnumEntry>().forEach {
|
||||
val enumField = createFieldForEntry(it, irClass)
|
||||
context.enumEntryToGetInstanceFunction[it.symbol] = {
|
||||
JsIrBuilder.buildGetField(enumField.symbol, classAsReceiver(irClass), null, irClass.defaultType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun classAsReceiver(irClass: IrClass): IrExpression {
|
||||
val intrinsic = context.intrinsics.jsClass
|
||||
return JsIrBuilder.buildCall(intrinsic, context.irBuiltIns.anyType, listOf(irClass.defaultType))
|
||||
}
|
||||
|
||||
|
||||
private fun createFieldForEntry(entry: IrEnumEntry, irClass: IrClass): IrField {
|
||||
val descriptor = WrappedPropertyDescriptor()
|
||||
val symbol = IrFieldSymbolImpl(descriptor)
|
||||
return entry.run {
|
||||
IrFieldImpl(startOffset, endOffset, origin, symbol, name, irClass.defaultType, Visibilities.DEFAULT_VISIBILITY, false, true, true ).also { f ->
|
||||
descriptor.bind(f)
|
||||
f.parent = irClass
|
||||
irClass.declarations += f
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+1
@@ -142,6 +142,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
|
||||
|
||||
private fun IrType.findEqualsMethod(): IrSimpleFunction? {
|
||||
val klass = getClass() ?: return null
|
||||
if (klass.isEnumClass && klass.isExternal) return null
|
||||
return klass.declarations
|
||||
.filterIsInstance<IrSimpleFunction>()
|
||||
.filter { it.isEqualsInheritedFromAny() && !it.isFakeOverriddenFromAny() }
|
||||
|
||||
Reference in New Issue
Block a user