[JS IR BE] Codegen class model refactorings

Reduce JsScope usage
This commit is contained in:
Svyatoslav Kuzmich
2019-06-24 15:07:59 +03:00
parent e7a5e5b4a0
commit 685597d20a
9 changed files with 43 additions and 48 deletions
@@ -128,14 +128,14 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
override fun visitWhileLoop(loop: IrWhileLoop, context: JsGenerationContext): JsStatement {
//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))
return label?.let { JsLabel(it, loopStatement) } ?: loopStatement
}
override fun visitDoWhileLoop(loop: IrDoWhileLoop, context: JsGenerationContext): JsStatement {
//TODO what if body null?
val label = context.getNameForLoop(loop)?.let { context.staticContext.rootScope.declareName(it) }
val label = context.getNameForLoop(loop)
val loopStatement =
JsDoWhile(loop.condition.accept(IrElementToJsExpressionTransformer(), context), loop.body?.accept(this, context))
return label?.let { JsLabel(it, loopStatement) } ?: loopStatement
@@ -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.utils.*
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.isObject
import org.jetbrains.kotlin.js.backend.ast.*
@@ -120,8 +121,6 @@ class IrModuleToJsTransformer(
return JsExpressionStatement(expression)
}
private fun generateModule(module: IrModuleFragment): JsProgram {
val additionalPackages = with(backendContext) {
externalPackageFragment.values + listOf(
@@ -135,13 +134,11 @@ class IrModuleToJsTransformer(
val program = JsProgram()
val nameGenerator = IrNamerImpl(
newNameTables = namer,
rootScope = program.rootScope
newNameTables = namer
)
val staticContext = JsStaticContext(
backendContext = backendContext,
irNamer = nameGenerator,
rootScope = program.rootScope
irNamer = nameGenerator
)
val rootContext = JsGenerationContext(
parent = null,
@@ -261,13 +258,13 @@ class IrModuleToJsTransformer(
generateModule(declaration)
private fun processClassModels(
classModelMap: Map<JsName, JsClassModel>,
classModelMap: Map<IrClassSymbol, JsIrClassModel>,
preDeclarationBlock: JsBlock,
postDeclarationBlock: JsBlock
) {
val declarationHandler = object : DFS.AbstractNodeHandler<JsName, Unit>() {
val declarationHandler = object : DFS.AbstractNodeHandler<IrClassSymbol, Unit>() {
override fun result() {}
override fun afterChildren(current: JsName) {
override fun afterChildren(current: IrClassSymbol) {
classModelMap[current]?.let {
preDeclarationBlock.statements += it.preDeclarationBlock.statements
postDeclarationBlock.statements += it.postDeclarationBlock.statements
@@ -275,13 +272,10 @@ class IrModuleToJsTransformer(
}
}
DFS.dfs(classModelMap.keys, {
val neighbors = mutableListOf<JsName>()
classModelMap[it]?.run {
if (superName != null) neighbors += superName!!
neighbors += interfaces
}
neighbors
}, declarationHandler)
DFS.dfs(
classModelMap.keys,
{ klass -> classModelMap[klass]?.superClasses ?: emptyList() },
declarationHandler
)
}
}
@@ -31,7 +31,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
}
private val classPrototypeRef = prototypeOf(classNameRef)
private val classBlock = JsGlobalBlock()
private val classModel = JsClassModel(className, baseClassName)
private val classModel = JsIrClassModel(irClass)
fun generate(): JsStatement {
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
}
@@ -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.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 getNameForProperty(property: IrProperty): JsName
fun getRefForExternalClass(klass: IrClass): JsNameRef
fun getNameForLoop(loop: IrLoop): String?
fun getNameForLoop(loop: IrLoop): JsName?
}
@@ -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.JsRootScope
class IrNamerImpl(
private val newNameTables: NameTables,
private val rootScope: JsRootScope // TODO: Don't use scopes
) : IrNamer {
class IrNamerImpl(private val newNameTables: NameTables) : IrNamer {
override fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName {
val name = newNameTables.getNameForStaticDeclaration(declaration)
return rootScope.declareName(name)
}
private fun String.toJsName() = JsName(this)
override fun getNameForLoop(loop: IrLoop): String? =
newNameTables.getNameForLoop(loop)
override fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName =
newNameTables.getNameForStaticDeclaration(declaration).toJsName()
override fun getNameForLoop(loop: IrLoop): JsName? =
newNameTables.getNameForLoop(loop)?.toJsName()
override fun getNameForConstructor(constructor: IrConstructor): JsName {
return getNameForStaticDeclaration(constructor.parentAsClass)
@@ -31,12 +28,12 @@ class IrNamerImpl(
override fun getNameForMemberFunction(function: IrSimpleFunction): JsName {
require(function.dispatchReceiverParameter != null)
return rootScope.declareName(newNameTables.getNameForMemberFunction(function))
return newNameTables.getNameForMemberFunction(function).toJsName()
}
override fun getNameForMemberField(field: IrField): JsName {
require(!field.isStatic)
return rootScope.declareName(newNameTables.getNameForMemberField(field))
return newNameTables.getNameForMemberField(field).toJsName()
}
override fun getNameForField(field: IrField): JsName {
@@ -56,9 +53,8 @@ class IrNamerImpl(
override fun getNameForStaticFunction(function: IrSimpleFunction): JsName =
getNameForStaticDeclaration(function)
override fun getNameForProperty(property: IrProperty): JsName {
return rootScope.declareName(property.getJsNameOrKotlinName().asString())
}
override fun getNameForProperty(property: IrProperty): JsName =
property.getJsNameOrKotlinName().asString().toJsName()
override fun getRefForExternalClass(klass: IrClass): JsNameRef {
val parent = klass.parent
@@ -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.transformers.irToJs.JsIntrinsicTransformers
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIrClassModel
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.JsName
import org.jetbrains.kotlin.js.backend.ast.JsRootScope
class JsStaticContext(
val rootScope: JsRootScope,
val backendContext: JsIrBackendContext,
private val irNamer: IrNamer
) : IrNamer by irNamer {
val intrinsics = JsIntrinsicTransformers(backendContext)
// TODO: use IrSymbol instead of JsName
val classModels = mutableMapOf<JsName, JsClassModel>()
val classModels = mutableMapOf<IrClassSymbol, JsIrClassModel>()
val coroutineImplDeclaration = backendContext.ir.symbols.coroutineImpl.owner
val doResumeFunctionSymbol = coroutineImplDeclaration.declarations
.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?) {
val interfaces: MutableSet<JsName> = mutableSetOf()
val preDeclarationBlock = JsGlobalBlock() // TODO only used in IR backend => hide from current backend
val postDeclarationBlock = JsGlobalBlock()
}
@@ -20,11 +20,15 @@ public class JsName extends HasMetadata implements Symbol {
/**
* @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.temporary = temporary;
}
public JsName(@NotNull String ident) {
this(ident, false);
}
public boolean isTemporary() {
return temporary;
}
@@ -137,9 +137,7 @@ class ImportIntoFragmentInliningScope private constructor(
get() = JsBlock(
JsBlock(fragment.inlinedLocalDeclarations.values.toList()),
fragment.declarationBlock,
JsBlock(fragment.classes.values.flatMap {
listOf(it.preDeclarationBlock, it.postDeclarationBlock)
}),
JsBlock(fragment.classes.values.map { it.postDeclarationBlock }),
fragment.exportBlock,
JsExpressionStatement(JsFunction(JsDynamicScope, fragment.initializerBlock, ""))
).also { block ->