[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.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
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.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
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.SymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertyDeclaration
|
import org.jetbrains.kotlin.ir.util.getPropertyDeclaration
|
||||||
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -110,7 +110,7 @@ class JsIrBackendContext(
|
|||||||
private val coroutinePackage = module.getPackage(COROUTINE_PACKAGE_FQNAME)
|
private val coroutinePackage = module.getPackage(COROUTINE_PACKAGE_FQNAME)
|
||||||
private val coroutineIntrinsicsPackage = module.getPackage(COROUTINE_INTRINSICS_PACKAGE_FQNAME)
|
private val coroutineIntrinsicsPackage = module.getPackage(COROUTINE_INTRINSICS_PACKAGE_FQNAME)
|
||||||
|
|
||||||
val enumEntryToGetInstanceFunction = mutableMapOf<IrEnumEntrySymbol, IrSimpleFunctionSymbol>()
|
val enumEntryToGetInstanceFunction = mutableMapOf<IrEnumEntrySymbol, () -> IrExpression>()
|
||||||
|
|
||||||
val coroutineGetContext: IrFunctionSymbol
|
val coroutineGetContext: IrFunctionSymbol
|
||||||
get() {
|
get() {
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ fun compile(
|
|||||||
moduleFragment.files.forEach { irFile -> extension.generate(irFile, context, psi2IrContext.bindingContext) }
|
moduleFragment.files.forEach { irFile -> extension.generate(irFile, context, psi2IrContext.bindingContext) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExternalEnumLowering(context).runOnFilesPostfix(moduleFragment)
|
||||||
MoveExternalDeclarationsToSeparatePlace().lower(moduleFragment)
|
MoveExternalDeclarationsToSeparatePlace().lower(moduleFragment)
|
||||||
ExpectDeclarationsRemoving(context).lower(moduleFragment)
|
ExpectDeclarationsRemoving(context).lower(moduleFragment)
|
||||||
CoroutineIntrinsicLowering(context).lower(moduleFragment)
|
CoroutineIntrinsicLowering(context).lower(moduleFragment)
|
||||||
|
|||||||
+7
-9
@@ -35,7 +35,7 @@ class EnumUsageLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
override fun visitGetEnumValue(expression: IrGetEnumValue) =
|
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 {
|
} else {
|
||||||
EnumClassTransformer(context, declaration).transform()
|
EnumClassTransformer(context, declaration).transform()
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
listOf(declaration)
|
listOf(declaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,9 +137,9 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
irWhen(
|
irWhen(
|
||||||
irClass.defaultType,
|
irClass.defaultType,
|
||||||
enumEntries.map {
|
enumEntries.map {
|
||||||
val getInstance = entryInstanceToFunction[it.symbol]!!
|
|
||||||
irBranch(
|
irBranch(
|
||||||
irEquals(irString(it.name.identifier), irGet(nameParameter)), irCall(getInstance)
|
irEquals(irString(it.name.identifier), irGet(nameParameter)),
|
||||||
|
entryInstanceToFunction[it.symbol]!!.invoke()
|
||||||
)
|
)
|
||||||
} + irElseBranch(irCall(throwISESymbol))
|
} + irElseBranch(irCall(throwISESymbol))
|
||||||
)
|
)
|
||||||
@@ -163,10 +163,8 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
return context.createIrBuilder(valuesFun.symbol).run {
|
return context.createIrBuilder(valuesFun.symbol).run {
|
||||||
irBlockBody {
|
irBlockBody {
|
||||||
+irReturn(
|
+irReturn(
|
||||||
enumEntries.map {
|
enumEntries.map { entryInstanceToFunction[it.symbol]!!.invoke() }
|
||||||
val function = entryInstanceToFunction[it.symbol]!!
|
.toArrayLiteral(valuesFun.returnType, irClass.defaultType)
|
||||||
irCall(function)
|
|
||||||
}.toArrayLiteral(valuesFun.returnType, irClass.defaultType)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +244,7 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
|
|||||||
+irCall(initEntryInstancesFun)
|
+irCall(initEntryInstancesFun)
|
||||||
+irReturn(irGet(entryInstances[index]))
|
+irReturn(irGet(entryInstances[index]))
|
||||||
}.apply {
|
}.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? {
|
private fun IrType.findEqualsMethod(): IrSimpleFunction? {
|
||||||
val klass = getClass() ?: return null
|
val klass = getClass() ?: return null
|
||||||
|
if (klass.isEnumClass && klass.isExternal) return null
|
||||||
return klass.declarations
|
return klass.declarations
|
||||||
.filterIsInstance<IrSimpleFunction>()
|
.filterIsInstance<IrSimpleFunction>()
|
||||||
.filter { it.isEqualsInheritedFromAny() && !it.isFakeOverriddenFromAny() }
|
.filter { it.isEqualsInheritedFromAny() && !it.isFakeOverriddenFromAny() }
|
||||||
|
|||||||
Reference in New Issue
Block a user