[JS IR BE] Codegen class model refactorings
Reduce JsScope usage
This commit is contained in:
+2
-2
@@ -128,14 +128,14 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
|||||||
|
|
||||||
override fun visitWhileLoop(loop: IrWhileLoop, context: JsGenerationContext): JsStatement {
|
override fun visitWhileLoop(loop: IrWhileLoop, context: JsGenerationContext): JsStatement {
|
||||||
//TODO what if body null?
|
//TODO what if body null?
|
||||||
val label = context.getNameForLoop(loop)?.let { context.staticContext.rootScope.declareName(it) }
|
val label = context.getNameForLoop(loop)
|
||||||
val loopStatement = JsWhile(loop.condition.accept(IrElementToJsExpressionTransformer(), context), loop.body?.accept(this, context))
|
val loopStatement = JsWhile(loop.condition.accept(IrElementToJsExpressionTransformer(), context), loop.body?.accept(this, context))
|
||||||
return label?.let { JsLabel(it, loopStatement) } ?: loopStatement
|
return label?.let { JsLabel(it, loopStatement) } ?: loopStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDoWhileLoop(loop: IrDoWhileLoop, context: JsGenerationContext): JsStatement {
|
override fun visitDoWhileLoop(loop: IrDoWhileLoop, context: JsGenerationContext): JsStatement {
|
||||||
//TODO what if body null?
|
//TODO what if body null?
|
||||||
val label = context.getNameForLoop(loop)?.let { context.staticContext.rootScope.declareName(it) }
|
val label = context.getNameForLoop(loop)
|
||||||
val loopStatement =
|
val loopStatement =
|
||||||
JsDoWhile(loop.condition.accept(IrElementToJsExpressionTransformer(), context), loop.body?.accept(this, context))
|
JsDoWhile(loop.condition.accept(IrElementToJsExpressionTransformer(), context), loop.body?.accept(this, context))
|
||||||
return label?.let { JsLabel(it, loopStatement) } ?: loopStatement
|
return label?.let { JsLabel(it, loopStatement) } ?: loopStatement
|
||||||
|
|||||||
+11
-17
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.ir.util.isObject
|
import org.jetbrains.kotlin.ir.util.isObject
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
@@ -120,8 +121,6 @@ class IrModuleToJsTransformer(
|
|||||||
return JsExpressionStatement(expression)
|
return JsExpressionStatement(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun generateModule(module: IrModuleFragment): JsProgram {
|
private fun generateModule(module: IrModuleFragment): JsProgram {
|
||||||
val additionalPackages = with(backendContext) {
|
val additionalPackages = with(backendContext) {
|
||||||
externalPackageFragment.values + listOf(
|
externalPackageFragment.values + listOf(
|
||||||
@@ -135,13 +134,11 @@ class IrModuleToJsTransformer(
|
|||||||
val program = JsProgram()
|
val program = JsProgram()
|
||||||
|
|
||||||
val nameGenerator = IrNamerImpl(
|
val nameGenerator = IrNamerImpl(
|
||||||
newNameTables = namer,
|
newNameTables = namer
|
||||||
rootScope = program.rootScope
|
|
||||||
)
|
)
|
||||||
val staticContext = JsStaticContext(
|
val staticContext = JsStaticContext(
|
||||||
backendContext = backendContext,
|
backendContext = backendContext,
|
||||||
irNamer = nameGenerator,
|
irNamer = nameGenerator
|
||||||
rootScope = program.rootScope
|
|
||||||
)
|
)
|
||||||
val rootContext = JsGenerationContext(
|
val rootContext = JsGenerationContext(
|
||||||
parent = null,
|
parent = null,
|
||||||
@@ -261,13 +258,13 @@ class IrModuleToJsTransformer(
|
|||||||
generateModule(declaration)
|
generateModule(declaration)
|
||||||
|
|
||||||
private fun processClassModels(
|
private fun processClassModels(
|
||||||
classModelMap: Map<JsName, JsClassModel>,
|
classModelMap: Map<IrClassSymbol, JsIrClassModel>,
|
||||||
preDeclarationBlock: JsBlock,
|
preDeclarationBlock: JsBlock,
|
||||||
postDeclarationBlock: JsBlock
|
postDeclarationBlock: JsBlock
|
||||||
) {
|
) {
|
||||||
val declarationHandler = object : DFS.AbstractNodeHandler<JsName, Unit>() {
|
val declarationHandler = object : DFS.AbstractNodeHandler<IrClassSymbol, Unit>() {
|
||||||
override fun result() {}
|
override fun result() {}
|
||||||
override fun afterChildren(current: JsName) {
|
override fun afterChildren(current: IrClassSymbol) {
|
||||||
classModelMap[current]?.let {
|
classModelMap[current]?.let {
|
||||||
preDeclarationBlock.statements += it.preDeclarationBlock.statements
|
preDeclarationBlock.statements += it.preDeclarationBlock.statements
|
||||||
postDeclarationBlock.statements += it.postDeclarationBlock.statements
|
postDeclarationBlock.statements += it.postDeclarationBlock.statements
|
||||||
@@ -275,13 +272,10 @@ class IrModuleToJsTransformer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DFS.dfs(classModelMap.keys, {
|
DFS.dfs(
|
||||||
val neighbors = mutableListOf<JsName>()
|
classModelMap.keys,
|
||||||
classModelMap[it]?.run {
|
{ klass -> classModelMap[klass]?.superClasses ?: emptyList() },
|
||||||
if (superName != null) neighbors += superName!!
|
declarationHandler
|
||||||
neighbors += interfaces
|
)
|
||||||
}
|
|
||||||
neighbors
|
|
||||||
}, declarationHandler)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+9
-2
@@ -31,7 +31,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
}
|
}
|
||||||
private val classPrototypeRef = prototypeOf(classNameRef)
|
private val classPrototypeRef = prototypeOf(classNameRef)
|
||||||
private val classBlock = JsGlobalBlock()
|
private val classBlock = JsGlobalBlock()
|
||||||
private val classModel = JsClassModel(className, baseClassName)
|
private val classModel = JsIrClassModel(irClass)
|
||||||
|
|
||||||
fun generate(): JsStatement {
|
fun generate(): JsStatement {
|
||||||
assert(!irClass.descriptor.isExpect)
|
assert(!irClass.descriptor.isExpect)
|
||||||
@@ -103,7 +103,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.staticContext.classModels[className] = classModel
|
context.staticContext.classModels[irClass.symbol] = classModel
|
||||||
return classBlock
|
return classBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,3 +278,10 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
|
|
||||||
private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true
|
private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true
|
||||||
private val IrClassifierSymbol.isEffectivelyExternal get() = (owner as? IrDeclaration)?.isEffectivelyExternal() == true
|
private val IrClassifierSymbol.isEffectivelyExternal get() = (owner as? IrDeclaration)?.isEffectivelyExternal() == true
|
||||||
|
|
||||||
|
class JsIrClassModel(val klass: IrClass) {
|
||||||
|
val superClasses = klass.superTypes.map { it.classifierOrFail as IrClassSymbol }
|
||||||
|
|
||||||
|
val preDeclarationBlock = JsGlobalBlock()
|
||||||
|
val postDeclarationBlock = JsGlobalBlock()
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,5 +21,5 @@ interface IrNamer {
|
|||||||
fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName
|
fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName
|
||||||
fun getNameForProperty(property: IrProperty): JsName
|
fun getNameForProperty(property: IrProperty): JsName
|
||||||
fun getRefForExternalClass(klass: IrClass): JsNameRef
|
fun getRefForExternalClass(klass: IrClass): JsNameRef
|
||||||
fun getNameForLoop(loop: IrLoop): String?
|
fun getNameForLoop(loop: IrLoop): JsName?
|
||||||
}
|
}
|
||||||
+11
-15
@@ -12,18 +12,15 @@ import org.jetbrains.kotlin.js.backend.ast.JsName
|
|||||||
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
|
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsRootScope
|
import org.jetbrains.kotlin.js.backend.ast.JsRootScope
|
||||||
|
|
||||||
class IrNamerImpl(
|
class IrNamerImpl(private val newNameTables: NameTables) : IrNamer {
|
||||||
private val newNameTables: NameTables,
|
|
||||||
private val rootScope: JsRootScope // TODO: Don't use scopes
|
|
||||||
) : IrNamer {
|
|
||||||
|
|
||||||
override fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName {
|
private fun String.toJsName() = JsName(this)
|
||||||
val name = newNameTables.getNameForStaticDeclaration(declaration)
|
|
||||||
return rootScope.declareName(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getNameForLoop(loop: IrLoop): String? =
|
override fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName =
|
||||||
newNameTables.getNameForLoop(loop)
|
newNameTables.getNameForStaticDeclaration(declaration).toJsName()
|
||||||
|
|
||||||
|
override fun getNameForLoop(loop: IrLoop): JsName? =
|
||||||
|
newNameTables.getNameForLoop(loop)?.toJsName()
|
||||||
|
|
||||||
override fun getNameForConstructor(constructor: IrConstructor): JsName {
|
override fun getNameForConstructor(constructor: IrConstructor): JsName {
|
||||||
return getNameForStaticDeclaration(constructor.parentAsClass)
|
return getNameForStaticDeclaration(constructor.parentAsClass)
|
||||||
@@ -31,12 +28,12 @@ class IrNamerImpl(
|
|||||||
|
|
||||||
override fun getNameForMemberFunction(function: IrSimpleFunction): JsName {
|
override fun getNameForMemberFunction(function: IrSimpleFunction): JsName {
|
||||||
require(function.dispatchReceiverParameter != null)
|
require(function.dispatchReceiverParameter != null)
|
||||||
return rootScope.declareName(newNameTables.getNameForMemberFunction(function))
|
return newNameTables.getNameForMemberFunction(function).toJsName()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNameForMemberField(field: IrField): JsName {
|
override fun getNameForMemberField(field: IrField): JsName {
|
||||||
require(!field.isStatic)
|
require(!field.isStatic)
|
||||||
return rootScope.declareName(newNameTables.getNameForMemberField(field))
|
return newNameTables.getNameForMemberField(field).toJsName()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNameForField(field: IrField): JsName {
|
override fun getNameForField(field: IrField): JsName {
|
||||||
@@ -56,9 +53,8 @@ class IrNamerImpl(
|
|||||||
override fun getNameForStaticFunction(function: IrSimpleFunction): JsName =
|
override fun getNameForStaticFunction(function: IrSimpleFunction): JsName =
|
||||||
getNameForStaticDeclaration(function)
|
getNameForStaticDeclaration(function)
|
||||||
|
|
||||||
override fun getNameForProperty(property: IrProperty): JsName {
|
override fun getNameForProperty(property: IrProperty): JsName =
|
||||||
return rootScope.declareName(property.getJsNameOrKotlinName().asString())
|
property.getJsNameOrKotlinName().asString().toJsName()
|
||||||
}
|
|
||||||
|
|
||||||
override fun getRefForExternalClass(klass: IrClass): JsNameRef {
|
override fun getRefForExternalClass(klass: IrClass): JsNameRef {
|
||||||
val parent = klass.parent
|
val parent = klass.parent
|
||||||
|
|||||||
+3
-6
@@ -7,22 +7,19 @@ package org.jetbrains.kotlin.ir.backend.js.utils
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIntrinsicTransformers
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIntrinsicTransformers
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIrClassModel
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsClassModel
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock
|
import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsName
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsRootScope
|
|
||||||
|
|
||||||
|
|
||||||
class JsStaticContext(
|
class JsStaticContext(
|
||||||
val rootScope: JsRootScope,
|
|
||||||
val backendContext: JsIrBackendContext,
|
val backendContext: JsIrBackendContext,
|
||||||
private val irNamer: IrNamer
|
private val irNamer: IrNamer
|
||||||
) : IrNamer by irNamer {
|
) : IrNamer by irNamer {
|
||||||
|
|
||||||
val intrinsics = JsIntrinsicTransformers(backendContext)
|
val intrinsics = JsIntrinsicTransformers(backendContext)
|
||||||
// TODO: use IrSymbol instead of JsName
|
val classModels = mutableMapOf<IrClassSymbol, JsIrClassModel>()
|
||||||
val classModels = mutableMapOf<JsName, JsClassModel>()
|
|
||||||
val coroutineImplDeclaration = backendContext.ir.symbols.coroutineImpl.owner
|
val coroutineImplDeclaration = backendContext.ir.symbols.coroutineImpl.owner
|
||||||
val doResumeFunctionSymbol = coroutineImplDeclaration.declarations
|
val doResumeFunctionSymbol = coroutineImplDeclaration.declarations
|
||||||
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "doResume" }.symbol
|
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "doResume" }.symbol
|
||||||
|
|||||||
@@ -18,6 +18,5 @@ package org.jetbrains.kotlin.js.backend.ast
|
|||||||
|
|
||||||
class JsClassModel(val name: JsName, val superName: JsName?) {
|
class JsClassModel(val name: JsName, val superName: JsName?) {
|
||||||
val interfaces: MutableSet<JsName> = mutableSetOf()
|
val interfaces: MutableSet<JsName> = mutableSetOf()
|
||||||
val preDeclarationBlock = JsGlobalBlock() // TODO only used in IR backend => hide from current backend
|
|
||||||
val postDeclarationBlock = JsGlobalBlock()
|
val postDeclarationBlock = JsGlobalBlock()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,15 @@ public class JsName extends HasMetadata implements Symbol {
|
|||||||
/**
|
/**
|
||||||
* @param ident the unmangled ident to use for this name
|
* @param ident the unmangled ident to use for this name
|
||||||
*/
|
*/
|
||||||
JsName(@NotNull String ident, boolean temporary) {
|
public JsName(@NotNull String ident, boolean temporary) {
|
||||||
this.ident = ident;
|
this.ident = ident;
|
||||||
this.temporary = temporary;
|
this.temporary = temporary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JsName(@NotNull String ident) {
|
||||||
|
this(ident, false);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isTemporary() {
|
public boolean isTemporary() {
|
||||||
return temporary;
|
return temporary;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,9 +137,7 @@ class ImportIntoFragmentInliningScope private constructor(
|
|||||||
get() = JsBlock(
|
get() = JsBlock(
|
||||||
JsBlock(fragment.inlinedLocalDeclarations.values.toList()),
|
JsBlock(fragment.inlinedLocalDeclarations.values.toList()),
|
||||||
fragment.declarationBlock,
|
fragment.declarationBlock,
|
||||||
JsBlock(fragment.classes.values.flatMap {
|
JsBlock(fragment.classes.values.map { it.postDeclarationBlock }),
|
||||||
listOf(it.preDeclarationBlock, it.postDeclarationBlock)
|
|
||||||
}),
|
|
||||||
fragment.exportBlock,
|
fragment.exportBlock,
|
||||||
JsExpressionStatement(JsFunction(JsDynamicScope, fragment.initializerBlock, ""))
|
JsExpressionStatement(JsFunction(JsDynamicScope, fragment.initializerBlock, ""))
|
||||||
).also { block ->
|
).also { block ->
|
||||||
|
|||||||
Reference in New Issue
Block a user