[JS IR BE] Enum class lowering

This commit is contained in:
Svyatoslav Kuzmich
2018-07-19 14:57:27 +03:00
parent 668708170f
commit 625983b28a
98 changed files with 397 additions and 108 deletions
@@ -17,14 +17,9 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.SymbolTable
@@ -60,6 +55,7 @@ class JsIrBackendContext(
data class SecondaryCtorPair(val delegate: IrSimpleFunctionSymbol, val stub: IrSimpleFunctionSymbol)
val secondaryConstructorsMap = mutableMapOf<IrConstructorSymbol, SecondaryCtorPair>()
val enumEntryToGetInstanceFunction = mutableMapOf<IrEnumEntrySymbol, IrSimpleFunctionSymbol>()
fun getOperatorByName(name: Name, type: IrType) = operatorMap[name]?.get(type.toKotlinType())
@@ -88,6 +88,8 @@ private fun JsIrBackendContext.lower(file: IrFile) {
DefaultArgumentStubGenerator(this).runOnFilePostfix(file)
DefaultParameterInjector(this).runOnFilePostfix(file)
SharedVariablesLowering(this).runOnFilePostfix(file)
EnumClassLowering(this).runOnFilePostfix(file)
EnumUsageLowering(this).lower(file)
ReturnableBlockLowering(this).lower(file)
LocalDeclarationsLowering(this).runOnFilePostfix(file)
InnerClassesLowering(this).runOnFilePostfix(file)
@@ -128,6 +128,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
// TODO: Support offsets for debug info
val irFunction = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, bridgeDescriptorForIrFunction)
irFunction.createParameterDeclarations()
irFunction.returnType = bridge.returnType
// TODO: Add type casts
context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) {
@@ -0,0 +1,339 @@
/*
* 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.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder
import org.jetbrains.kotlin.ir.backend.js.symbols.initialize
import org.jetbrains.kotlin.ir.backend.js.utils.createValueParameter
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import java.util.*
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]!!)
})
}
}
class EnumClassLowering(val context: JsIrBackendContext) : DeclarationContainerLoweringPass {
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat { declaration ->
if (declaration is IrClass && declaration.isEnumClass)
EnumClassTransformer(context, declaration).transform()
else
listOf(declaration)
}
}
}
class EnumClassTransformer(val context: JsIrBackendContext, private val irClass: IrClass) {
private val builder = context.createIrBuilder(irClass.symbol)
private val enumEntries = irClass.declarations.filterIsInstance<IrEnumEntry>()
private val loweredEnumConstructors = HashMap<IrConstructorSymbol, IrConstructor>()
private val enumName = irClass.name.identifier
fun transform(): List<IrDeclaration> {
// Add `name` and `ordinal` parameters to enum class constructors
lowerEnumConstructorsSignature()
// Pass these parameters to delegating constructor calls
lowerEnumConstructorsBody()
// Create instance variable for each enum entry initialized with `null`
val entryInstances = createEnumEntryInstanceVariables()
// Lower `IrEnumConstructorCall`s inside of enum entry class constructors to corresponding `IrDelegatingConstructorCall`s.
// Add `name` and `ordinal` parameters.
lowerEnumEntryClassConstructors(entryInstances)
// Lower `IrEnumConstructorCall`s to corresponding `IrCall`s.
// Add `name` and `ordinal` constant parameters only for calls to the "enum class" constructors ("enum entry class" constructors
// already delegate these parameters)
lowerEnumEntryInitializerExpression()
// Create boolean flag that indicates if entry instances were initialized.
val entryInstancesInitializedVar = createEntryInstancesInitializedVar()
// Create function that initializes all enum entry instances using `IrEnumEntry.initializationExpression`.
// It should be called on the first `IrGetEnumValue`, consecutive calls to this function will do nothing.
val initEntryInstancesFun = createInitEntryInstancesFun(entryInstancesInitializedVar, entryInstances)
// Create entry instance getters. These are used to lower `IrGetEnumValue`.
val entryGetInstanceFuns = createGetEntryInstanceFuns(initEntryInstancesFun, entryInstances)
// Create body for `values` and `valueOf` functions
lowerSyntheticFunctions()
// Remove IrEnumEntry nodes from class declarations. Replace them with corresponding class declarations (if they have them).
replaceIrEntriesWithCorrespondingClasses()
return listOf(irClass) + entryInstances + listOf(entryInstancesInitializedVar, initEntryInstancesFun) + entryGetInstanceFuns
}
private fun createEnumValueOfBody(): IrBody {
val valueOfFun = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF)
val nameParameter = valueOfFun.valueParameters[0]
val entryInstanceToFunction = context.enumEntryToGetInstanceFunction
return context.createIrBuilder(valueOfFun.symbol).run {
irBlockBody {
+irReturn(
irWhen(
irClass.defaultType,
enumEntries.map {
val getInstance = entryInstanceToFunction[it.symbol]!!
irBranch(
irEquals(irString(it.name.identifier), irGet(nameParameter)), irCall(getInstance)
)
} + irElseBranch(irCall(context.irBuiltIns.throwIseSymbol))
)
)
}
}
}
private fun lowerEnumConstructorsSignature() {
irClass.declarations.transform { declaration ->
if (declaration is IrConstructor) {
transformEnumConstructor(declaration, irClass)
} else
declaration
}
}
private fun lowerEnumConstructorsBody() {
irClass.declarations.filterIsInstance<IrConstructor>().forEach {
IrEnumClassConstructorTransformer(it).transformBody()
}
}
private fun lowerEnumEntryClassConstructors(entryInstances: List<IrVariable>) {
for ((entry, instance) in enumEntries.zip(entryInstances)) {
entry.correspondingClass?.constructors?.forEach {
it.transformChildrenVoid(IrEnumEntryClassConstructorTransformer(entry, true))
// Initialize entry instance at the beginning of constructor so it can be used inside constructor body
(it.body as? IrBlockBody)?.apply {
statements.add(0, context.createIrBuilder(it.symbol).run {
irSetVar(instance.symbol, irGet(entry.correspondingClass!!.thisReceiver!!))
})
}
}
}
}
private fun lowerEnumEntryInitializerExpression() {
for (entry in enumEntries) {
entry.initializerExpression =
entry.initializerExpression?.transform(IrEnumEntryClassConstructorTransformer(entry, false), null)
}
}
private fun createEnumEntryInstanceVariables() = enumEntries.map { enumEntry ->
val type = enumEntry.getType().makeNullable()
val name = "${enumName}_${enumEntry.name.identifier}_instance"
builder.run {
scope.createTemporaryVariable(irImplicitCast(irNull(), type), name)
}
}
private fun replaceIrEntriesWithCorrespondingClasses() {
irClass.declarations.transformFlat {
listOfNotNull(if (it is IrEnumEntry) it.correspondingClass else it)
}
}
private fun lowerSyntheticFunctions() {
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitSyntheticBody(body: IrSyntheticBody): IrBody {
return when (body.kind) {
IrSyntheticBodyKind.ENUM_VALUES -> builder.irBlockBody { } // TODO: Implement
IrSyntheticBodyKind.ENUM_VALUEOF -> createEnumValueOfBody()
}
}
})
}
private fun createGetEntryInstanceFuns(
initEntryInstancesFun: IrFunctionImpl,
entryInstances: List<IrVariable>
) = enumEntries.mapIndexed { index, enumEntry ->
buildFunction(
name = "${enumName}_${enumEntry.name.identifier}_getInstance",
returnType = enumEntry.getType()
) {
+irCall(initEntryInstancesFun)
+irReturn(irGet(entryInstances[index]))
}.apply {
context.enumEntryToGetInstanceFunction[enumEntry.symbol] = this@apply.symbol
}
}
private fun createInitEntryInstancesFun(
entryInstancesInitializedVar: IrVariable,
entryInstances: List<IrVariable>
) = buildFunction("${enumName}_initEntries") {
+irIfThen(irGet(entryInstancesInitializedVar), irReturnUnit())
+irSetVar(entryInstancesInitializedVar.symbol, irBoolean(true))
for ((entry, instanceVar) in enumEntries.zip(entryInstances)) {
+irSetVar(instanceVar.symbol, entry.initializerExpression!!)
}
}
private fun createEntryInstancesInitializedVar(): IrVariable {
return builder.scope.createTemporaryVariable(
builder.irBoolean(false),
"${enumName}_entriesInitialized"
)
}
private inner class IrEnumClassConstructorTransformer(val constructor: IrConstructor) : IrElementTransformerVoid() {
val builder = context.createIrBuilder(constructor.symbol)
fun transformBody() {
constructor.body?.transformChildrenVoid(this)
}
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) =
builder.irDelegatingConstructorCall(expression.symbol.owner).apply {
for (i in 0..1) {
putValueArgument(i, builder.irGet(constructor.valueParameters[i]))
}
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
var constructor = expression.symbol.owner
val constructorWasTransformed = constructor.symbol in loweredEnumConstructors
if (constructorWasTransformed)
constructor = loweredEnumConstructors[constructor.symbol]!!
return builder.irDelegatingConstructorCall(constructor).apply {
var valueArgIdx = 0
for (i in 0..1) {
putValueArgument(valueArgIdx++, builder.irGet(constructor.valueParameters[i]))
}
for (i in 0 until expression.valueArgumentsCount) {
putValueArgument(valueArgIdx++, expression.getValueArgument(i))
}
}
}
}
private inner class IrEnumEntryClassConstructorTransformer(val entry: IrEnumEntry, val isInsideConstructor: Boolean) :
IrElementTransformerVoid() {
private fun buildConstructorCall(constructor: IrConstructor) =
if (isInsideConstructor)
builder.irDelegatingConstructorCall(constructor)
else
builder.irCall(constructor)
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
var constructor = expression.symbol.owner
val constructorWasTransformed = constructor.symbol in loweredEnumConstructors
// Enum entry class constructors are not transformed
if (constructorWasTransformed)
constructor = loweredEnumConstructors[constructor.symbol]!!
return buildConstructorCall(constructor).apply {
var valueArgIdx = 0
// Enum entry class constructors already delegate name and ordinal parameters in their body
if (constructorWasTransformed) {
putValueArgument(valueArgIdx++, entry.getNameExpression())
putValueArgument(valueArgIdx++, entry.getOrdinalExpression())
}
for (i in 0 until expression.valueArgumentsCount) {
putValueArgument(valueArgIdx++, expression.getValueArgument(i))
}
}
}
}
private fun transformEnumConstructor(enumConstructor: IrConstructor, enumClass: IrClass): IrConstructor {
val loweredConstructorSymbol = lowerEnumConstructor(enumConstructor)
return IrConstructorImpl(
enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin,
loweredConstructorSymbol,
enumConstructor.body // will be transformed later
).apply {
parent = enumClass
returnType = enumConstructor.returnType
createParameterDeclarations()
loweredEnumConstructors[enumConstructor.symbol] = this
}
}
private fun lowerEnumConstructor(enumConstructor: IrConstructor): IrConstructorSymbol {
val constructorDescriptor = enumConstructor.descriptor
val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
constructorDescriptor.containingDeclaration,
constructorDescriptor.annotations,
constructorDescriptor.isPrimary,
constructorDescriptor.source
)
val valueParameters =
listOf(
createValueParameter(loweredConstructorDescriptor, 0, "name", context.builtIns.stringType),
createValueParameter(loweredConstructorDescriptor, 1, "ordinal", context.builtIns.intType)
) + constructorDescriptor.valueParameters.map {
it.copy(loweredConstructorDescriptor, it.name, it.index + 2)
}
loweredConstructorDescriptor.initialize(valueParameters, Visibilities.PROTECTED)
loweredConstructorDescriptor.returnType = constructorDescriptor.returnType
return IrConstructorSymbolImpl(loweredConstructorDescriptor)
}
private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): IrFunction =
irClass.declarations.asSequence().filterIsInstance<IrFunction>()
.first {
it.body.let { body ->
body is IrSyntheticBody && body.kind == kind
}
}
private fun buildFunction(
name: String,
returnType: IrType = context.irBuiltIns.unitType,
bodyBuilder: IrBlockBodyBuilder.() -> Unit
) = JsIrBuilder.buildFunction(
symbol = JsSymbolBuilder.buildSimpleFunction(irClass.descriptor.containingDeclaration, name)
.initialize(returnType = returnType),
returnType = returnType
).apply {
body = context.createIrBuilder(this.symbol).irBlockBody(this, bodyBuilder)
}
private fun IrEnumEntry.getNameExpression() = builder.irString(this.name.identifier)
private fun IrEnumEntry.getOrdinalExpression() = builder.irInt(enumEntries.indexOf(this))
private fun IrEnumEntry.getType() = (correspondingClass ?: irClass).defaultType
}
@@ -174,7 +174,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
typeParameters += ctorOrig.typeParameters
// parent = ctorOrig.parent
val returnType = type
returnType = type
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
val irCreateCall = JsIrBuilder.buildCall(
createFunctionIntrinsic.symbol,
@@ -8,16 +8,10 @@ package org.jetbrains.kotlin.ir.builders
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
@@ -80,6 +74,9 @@ fun <T : IrElement> IrStatementsBuilder<T>.defineTemporaryVar(value: IrExpressio
fun IrBuilderWithScope.irExprBody(value: IrExpression) =
IrExpressionBodyImpl(startOffset, endOffset, value)
fun IrBuilderWithScope.irWhen(type: IrType, branches: List<IrBranch>) =
IrWhenImpl(startOffset, endOffset, type, null, branches)
fun IrBuilderWithScope.irReturn(value: IrExpression) =
IrReturnImpl(
startOffset, endOffset,
@@ -93,10 +90,17 @@ fun IrBuilderWithScope.irReturn(value: IrExpression) =
fun IrBuilderWithScope.irBoolean(value: Boolean) =
IrConstImpl(startOffset, endOffset, context.irBuiltIns.booleanType, IrConstKind.Boolean, value)
fun IrBuilderWithScope.irUnit() =
irGetObjectValue(context.irBuiltIns.unitType, context.irBuiltIns.unitClass)
fun IrBuilderWithScope.irTrue() = irBoolean(true)
fun IrBuilderWithScope.irFalse() = irBoolean(false)
fun IrBuilderWithScope.irReturnTrue() = irReturn(irTrue())
fun IrBuilderWithScope.irReturnFalse() = irReturn(irFalse())
fun IrBuilderWithScope.irReturnUnit() = irReturn(irUnit())
fun IrBuilderWithScope.irBranch(condition: IrExpression, result: IrExpression) =
IrBranchImpl(startOffset, endOffset, condition, result)
fun IrBuilderWithScope.irElseBranch(expression: IrExpression) =
IrElseBranchImpl(startOffset, endOffset, irTrue(), expression)
@@ -141,6 +145,9 @@ fun IrBuilderWithScope.irSetVar(variable: IrVariableSymbol, value: IrExpression)
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, field: IrField) =
IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver)
fun IrBuilderWithScope.irGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
IrGetObjectValueImpl(startOffset, endOffset, type, classSymbol)
fun IrBuilderWithScope.irEqeqeq(arg1: IrExpression, arg2: IrExpression) =
context.eqeqeq(startOffset, endOffset, arg1, arg2)
@@ -153,13 +160,16 @@ fun IrBuilderWithScope.irEqualsNull(argument: IrExpression) =
argument, irNull()
)
fun IrBuilderWithScope.irEquals(arg1: IrExpression, arg2: IrExpression) =
primitiveOp2(
startOffset, endOffset, context.irBuiltIns.eqeqSymbol, IrStatementOrigin.EXCLEQ,
arg1, arg2
)
fun IrBuilderWithScope.irNotEquals(arg1: IrExpression, arg2: IrExpression) =
primitiveOp1(
startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCLEQ,
primitiveOp2(
startOffset, endOffset, context.irBuiltIns.eqeqSymbol, IrStatementOrigin.EXCLEQ,
arg1, arg2
)
irEquals(arg1, arg2)
)
fun IrBuilderWithScope.irGet(type: IrType, receiver: IrExpression, getterSymbol: IrFunctionSymbol): IrCall =
@@ -185,6 +195,8 @@ fun IrBuilderWithScope.irCall(callee: IrFunctionSymbol, descriptor: FunctionDesc
fun IrBuilderWithScope.irCall(callee: IrFunction): IrCall =
irCall(callee.symbol, callee.descriptor, callee.returnType)
fun IrBuilderWithScope.irDelegatingConstructorCall(callee: IrConstructor): IrDelegatingConstructorCall =
IrDelegatingConstructorCallImpl(startOffset, endOffset, callee.returnType, callee.symbol, callee.descriptor, callee.typeParameters.size)
fun IrBuilderWithScope.irCallOp(
callee: IrFunctionSymbol,
@@ -147,6 +147,7 @@ class IrBuiltIns(
val eqeqFun = defineOperator("EQEQ", bool, listOf(anyN, anyN))
val throwNpeFun = defineOperator("THROW_NPE", nothing, listOf())
val throwCceFun = defineOperator("THROW_CCE", nothing, listOf())
val throwIseFun = defineOperator("THROW_ISE", nothing, listOf())
val booleanNotFun = defineOperator("NOT", bool, listOf(bool))
val noWhenBranchMatchedExceptionFun = defineOperator("noWhenBranchMatchedException", nothing, listOf())
@@ -161,6 +162,7 @@ class IrBuiltIns(
val eqeqSymbol = eqeqFun.symbol
val throwNpeSymbol = throwNpeFun.symbol
val throwCceSymbol = throwCceFun.symbol
val throwIseSymbol = throwIseFun.symbol
val booleanNotSymbol = booleanNotFun.symbol
val noWhenBranchMatchedExceptionSymbol = noWhenBranchMatchedExceptionFun.symbol
@@ -1,6 +1,5 @@
// !LANGUAGE: +NestedClassesInAnnotations
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
annotation class Foo(val kind: Kind) {
enum class Kind { FAIL, OK }
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
interface A<T> {
open fun foo(t: T) = "A"
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
interface A<T> {
open fun foo(t: T) = "A"
}
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS
enum class E {
A, B;
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class E {
ENTRY
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
interface Named {
val name: String
}
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class E {
I
}
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
package example2
fun box() = Context.OsType.OK.toString()
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
abstract class Base(val fn: () -> Test)
enum class Test(val ok: String) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class A {
ONE,
TWO;
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class A {
ONE,
TWO
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
import A.ONE
enum class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
import A.ONE
enum class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class A() {
ENTRY(){ override fun t() = "OK"};
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class E {
ENTRY;
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// http://youtrack.jetbrains.com/issue/KT-2167
enum class Season {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
enum class A {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
enum class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class Test(val x: Int, val str: String) {
OK;
constructor(x: Int = 0) : this(x, "OK")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
package test
enum class My(val s: String) {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
interface IFoo {
fun foo(): String
}
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
interface IFoo {
fun foo(): String
}
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
interface IFoo {
fun foo(): String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
package test
fun box() = MyEnum.E1.f() + MyEnum.E2.f()
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class Color(val rgb: Int) {
RED(0xff0000),
GREEN(0x00ff00),
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
package test
enum class Season {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
fun box() = if(Context.operatingSystemType == Context.Companion.OsType.OTHER) "OK" else "fail"
public class Context
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
class A {
enum class E {
OK
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
enum class A {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
enum class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
enum class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
class A {
companion object {}
enum class E {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class Direction() {
NORTH {
val someSpecialValue = "OK"
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class Bar {
ONE,
TWO
-1
View File
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class Test(val x: String, val closure1: () -> String) {
FOO("O", { FOO.x }) {
override val y: String = "K"
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class A(val b: String) {
E1("OK"){ override fun t() = b };
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class X {
B {
val value2 = "K"
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class X {
B {
val value2 = "K"
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
enum class X {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class X {
B {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
enum class X {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class X {
B {
override val value2 = "K"
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class X {
B {
override val value2 = "K"
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class X {
B {
val value2 = "K"
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
fun <T, R> T.letNoInline(fn: (T) -> R) =
fn(this)
-1
View File
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
enum class X {
B {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class E {
ENTRY,
SUBCLASS {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class State {
_0,
_1,
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class Season {
WINTER,
SPRING,
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
package test
fun box() = E.E1.f() + E.E2.f()
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class State {
O,
K
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
class Outer {
enum class Nested {
O,
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class Color(val rgb : Int) {
RED(0xFF0000),
GREEN(0x00FF00),
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class Test {
A,
B,
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
package test
import test.C.E1
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
interface Ordinaled {
val ordinal: Int
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class MyEnum {
O;
companion object {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class A { X1, X2 }
fun box(): String {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// CHECK_CASES_COUNT: function=box$lambda count=0
// CHECK_IF_COUNT: function=box$lambda count=1
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// CHECK_CASES_COUNT: function=box count=6
// CHECK_IF_COUNT: function=box count=1
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// CHECK_CASES_COUNT: function=box count=18
// CHECK_IF_COUNT: function=box count=3
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// CHECK_CASES_COUNT: function=doTheThing count=2
// CHECK_IF_COUNT: function=doTheThing count=2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// CHECK_CASES_COUNT: function=box count=0
// CHECK_IF_COUNT: function=box count=1
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// CHECK_CASES_COUNT: function=test count=0
// CHECK_IF_COUNT: function=test count=3
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class A { V }
fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class A { V }
fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class En {
A,
B
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class En {
A,
B
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
enum class En {
A,
B
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// FILE: 1.kt
package test
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// FILE: 1.kt
package test
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// FILE: 1.kt
package test
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR
// FILE: 1.kt
package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1141
// See KT-6326, KT-6777
package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1153
package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1148
package foo
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1155
package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1150
package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1167
package foo
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1154
package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1141
enum class A {
X,
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1144
package foo
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1133
package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1150
package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1133
external enum class X {
A, B
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1137
/*
* Copy of JVM-backend test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1159
package foo
+19
View File
@@ -0,0 +1,19 @@
/*
* 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 kotlin
public class Enum<T : Enum<T>>(val name: String, val ordinal: Int) : Comparable<Enum<T>> {
override fun compareTo(other: Enum<T>) = ordinal.compareTo(other.ordinal)
override fun equals(other: Any?) = this === other
override fun hashCode(): Int = identityHashCode(this)
override fun toString() = name
companion object
}
+3
View File
@@ -102,3 +102,6 @@ fun hashCode(obj: dynamic): Int {
"""
).unsafeCast<Int>()
}
// TODO: Use getObjectHashCode instead
fun identityHashCode(obj: dynamic): Int = hashCode(obj)
@@ -61,6 +61,9 @@ open class NoSuchElementException(message: String?, cause: Throwable?) : Runtime
}
// TODO: fix function names to satisfy style convention (depends on built-in names)
fun THROW_ISE() {
throw IllegalStateException()
}
fun THROW_CCE() {
throw ClassCastException()
}