[JS IR BE] Properly handle primary constructors
- force primary constructor to be created by codegen - make sure initializer is invoked once in primary constructor - make one of coroutine constructor primary - remove hack from codegen
This commit is contained in:
+1
-1
@@ -392,7 +392,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
||||
coroutineClass.defaultType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isPrimary = false
|
||||
isPrimary = true
|
||||
).apply {
|
||||
d.bind(this)
|
||||
parent = coroutineClass
|
||||
|
||||
@@ -275,9 +275,7 @@ class JsIrBackendContext(
|
||||
}
|
||||
|
||||
val throwableConstructors by lazy { throwableClass.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol } }
|
||||
val defaultThrowableCtor by lazy { throwableConstructors.single { it.owner.valueParameters.size == 0 } }
|
||||
|
||||
|
||||
val defaultThrowableCtor by lazy { throwableConstructors.single { !it.owner.isPrimary && it.owner.valueParameters.size == 0 } }
|
||||
|
||||
private fun referenceOperators(): Map<Name, MutableMap<IrClassifierSymbol, IrSimpleFunctionSymbol>> {
|
||||
val primitiveIrSymbols = irBuiltIns.primitiveIrTypes.map { it.classifierOrFail as IrClassSymbol }
|
||||
|
||||
@@ -260,11 +260,18 @@ private val propertiesLoweringPhase = makeJsModulePhase(
|
||||
description = "Move fields and accessors out from its property"
|
||||
)
|
||||
|
||||
private val primaryConstructorLoweringPhase = makeJsModulePhase(
|
||||
::PrimaryConstructorLowering,
|
||||
name = "PrimaryConstructorLowering",
|
||||
description = "Creates primary constructor if it doesn't exist",
|
||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||
)
|
||||
|
||||
private val initializersLoweringPhase = makeCustomJsModulePhase(
|
||||
{ context, module -> InitializersLowering(context, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).lower(module) },
|
||||
name = "InitializersLowering",
|
||||
description = "Merge init block and field initializers into [primary] constructor",
|
||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||
prerequisite = setOf(enumClassConstructorLoweringPhase, primaryConstructorLoweringPhase)
|
||||
)
|
||||
|
||||
private val multipleCatchesLoweringPhase = makeJsModulePhase(
|
||||
@@ -394,6 +401,7 @@ val jsPhases = namedIrModulePhase(
|
||||
innerClassesLoweringPhase then
|
||||
innerClassConstructorCallsLoweringPhase then
|
||||
propertiesLoweringPhase then
|
||||
primaryConstructorLoweringPhase then
|
||||
initializersLoweringPhase then
|
||||
// Common prefix ends
|
||||
moveBodilessDeclarationsToSeparatePlacePhase then
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.CommonBackendContext
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
|
||||
// Create primary constructor if it doesn't exist
|
||||
class PrimaryConstructorLowering(context: CommonBackendContext) : ClassLoweringPass {
|
||||
private val unitType = context.irBuiltIns.unitType
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
val constructors = irClass.declarations.filterIsInstance<IrConstructor>()
|
||||
|
||||
if (constructors.any { it.isPrimary }) return
|
||||
|
||||
val primary = createPrimaryConstructor(irClass)
|
||||
|
||||
val initializeTransformer = object : IrElementTransformerVoid() {
|
||||
override fun visitDeclaration(declaration: IrDeclaration) = declaration // optimize visiting
|
||||
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) = expression.run {
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, primary.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
constructors.forEach { it.transformChildrenVoid(initializeTransformer) }
|
||||
}
|
||||
|
||||
private object SYNTHETIC_PRIMARY_CONSTRUCTOR : IrDeclarationOriginImpl("SYNTHETIC_PRIMARY_CONSTRUCTOR")
|
||||
|
||||
private fun createPrimaryConstructor(irClass: IrClass): IrConstructor {
|
||||
val declaration = irClass.addConstructor {
|
||||
origin = SYNTHETIC_PRIMARY_CONSTRUCTOR
|
||||
isPrimary = true
|
||||
visibility = Visibilities.PRIVATE
|
||||
}
|
||||
|
||||
declaration.body = irClass.run {
|
||||
IrBlockBodyImpl(startOffset, endOffset, listOf(IrInstanceInitializerCallImpl(startOffset, endOffset, symbol, unitType)))
|
||||
}
|
||||
|
||||
return declaration
|
||||
}
|
||||
}
|
||||
-10
@@ -35,7 +35,6 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
fun generate(): JsStatement {
|
||||
assert(!irClass.descriptor.isExpect)
|
||||
|
||||
maybeGeneratePrimaryConstructor()
|
||||
val transformer = IrDeclarationToJsTransformer()
|
||||
|
||||
// Properties might be lowered out of classes
|
||||
@@ -134,15 +133,6 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
return null
|
||||
}
|
||||
|
||||
private fun maybeGeneratePrimaryConstructor() {
|
||||
if (!irClass.declarations.any { it is IrConstructor }) {
|
||||
val func = JsFunction(emptyScope, JsBlock(), "Ctor for ${irClass.name}")
|
||||
func.name = className
|
||||
classBlock.statements += func.makeStmt()
|
||||
classModel.preDeclarationBlock.statements += generateInheritanceCode()
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateInheritanceCode(): List<JsStatement> {
|
||||
if (baseClass == null || baseClass.isAny()) {
|
||||
return emptyList()
|
||||
|
||||
Reference in New Issue
Block a user