[JS IR] move JsGenerationContext towards it's use

This commit is contained in:
Anton Bannykh
2021-09-15 16:01:03 +03:00
committed by teamcityserver
parent e9c9d5731e
commit d595264cc8
4 changed files with 26 additions and 35 deletions
@@ -167,22 +167,14 @@ class IrToJs(
globalNameScope = nameGenerator.staticNames globalNameScope = nameGenerator.staticNames
) )
val rootContext = JsGenerationContext(
currentFunction = null,
currentFile = null,
staticContext = staticContext,
localNames = LocalNameGenerator(NameTable())
)
val declarationStatements: List<JsStatement> = unit.packageFragments.flatMap { val declarationStatements: List<JsStatement> = unit.packageFragments.flatMap {
StaticMembersLowering(backendContext).lower(it as IrFile) StaticMembersLowering(backendContext).lower(it as IrFile)
it.accept(IrFileToJsTransformer(), rootContext).statements it.accept(IrFileToJsTransformer(), staticContext).statements
} }
val preDeclarationBlock = JsGlobalBlock() val preDeclarationBlock = JsGlobalBlock()
val postDeclarationBlock = JsGlobalBlock() val postDeclarationBlock = JsGlobalBlock()
processClassModels(rootContext.staticContext.classModels, preDeclarationBlock, postDeclarationBlock) processClassModels(staticContext.classModels, preDeclarationBlock, postDeclarationBlock)
val statements = mutableListOf<JsStatement>() val statements = mutableListOf<JsStatement>()
statements += nameGenerator.internalImports.values statements += nameGenerator.internalImports.values
@@ -192,7 +184,7 @@ class IrToJs(
// Generate module initialization // Generate module initialization
val initializerBlock = rootContext.staticContext.initializerBlock val initializerBlock = staticContext.initializerBlock
when (unit) { when (unit) {
is WholeProgramUnit, is ModuleUnit -> { is WholeProgramUnit, is ModuleUnit -> {
// Run initialization during ES module initialization // Run initialization during ES module initialization
@@ -6,14 +6,19 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.JsStaticContext
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.js.backend.ast.JsBlock import org.jetbrains.kotlin.js.backend.ast.JsBlock
import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock
class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsBlock, JsGenerationContext> { class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsBlock, JsStaticContext> {
override fun visitFile(declaration: IrFile, data: JsGenerationContext): JsBlock { override fun visitFile(declaration: IrFile, data: JsStaticContext): JsBlock {
val fileContext = data.newFile(declaration) val fileContext = JsGenerationContext(
currentFile = declaration,
currentFunction = null,
staticContext = data,
)
val block = JsGlobalBlock() val block = JsGlobalBlock()
declaration.declarations.forEach { declaration.declarations.forEach {
@@ -143,20 +143,14 @@ class IrModuleToJsTransformer(
irNamer = nameGenerator, irNamer = nameGenerator,
globalNameScope = namer.globalNames globalNameScope = namer.globalNames
) )
val rootContext = JsGenerationContext(
currentFile = null,
currentFunction = null,
staticContext = staticContext,
localNames = LocalNameGenerator(NameTable())
)
val (importStatements, importedJsModules) = val (importStatements, importedJsModules) =
generateImportStatements( generateImportStatements(
getNameForExternalDeclaration = { rootContext.getNameForStaticDeclaration(it) }, getNameForExternalDeclaration = { staticContext.getNameForStaticDeclaration(it) },
declareFreshGlobal = { JsName(sanitizeName(it)) } // TODO: Declare fresh name declareFreshGlobal = { JsName(sanitizeName(it)) } // TODO: Declare fresh name
) )
val moduleBody = generateModuleBody(modules, rootContext) val moduleBody = generateModuleBody(modules, staticContext)
val internalModuleName = JsName("_") val internalModuleName = JsName("_")
val globalNames = NameTable<String>(namer.globalNames) val globalNames = NameTable<String>(namer.globalNames)
@@ -182,7 +176,7 @@ class IrModuleToJsTransformer(
statements += moduleBody statements += moduleBody
statements.addWithComment("block: exports", exportStatements + crossModuleExports) statements.addWithComment("block: exports", exportStatements + crossModuleExports)
if (generateMainCall) { if (generateMainCall) {
statements += generateCallToMain(modules, rootContext) statements += generateCallToMain(modules, staticContext)
} }
statements += JsReturn(internalModuleName.makeRef()) statements += JsReturn(internalModuleName.makeRef())
} }
@@ -288,7 +282,7 @@ class IrModuleToJsTransformer(
} }
} }
private fun generateModuleBody(modules: Iterable<IrModuleFragment>, context: JsGenerationContext): List<JsStatement> { private fun generateModuleBody(modules: Iterable<IrModuleFragment>, staticContext: JsStaticContext): List<JsStatement> {
val statements = mutableListOf<JsStatement>().also { val statements = mutableListOf<JsStatement>().also {
if (!generateScriptModule) it += JsStringLiteral("use strict").makeStmt() if (!generateScriptModule) it += JsStringLiteral("use strict").makeStmt()
} }
@@ -303,7 +297,7 @@ class IrModuleToJsTransformer(
modules.forEach { module -> modules.forEach { module ->
module.files.forEach { module.files.forEach {
val fileStatements = it.accept(IrFileToJsTransformer(), context).statements val fileStatements = it.accept(IrFileToJsTransformer(), staticContext).statements
if (fileStatements.isNotEmpty()) { if (fileStatements.isNotEmpty()) {
var startComment = "" var startComment = ""
@@ -332,15 +326,15 @@ class IrModuleToJsTransformer(
} }
// sort member forwarding code // sort member forwarding code
processClassModels(context.staticContext.classModels, preDeclarationBlock, postDeclarationBlock) processClassModels(staticContext.classModels, preDeclarationBlock, postDeclarationBlock)
statements.addWithComment("block: post-declaration", postDeclarationBlock.statements) statements.addWithComment("block: post-declaration", postDeclarationBlock.statements)
statements.addWithComment("block: init", context.staticContext.initializerBlock.statements) statements.addWithComment("block: init", staticContext.initializerBlock.statements)
modules.forEach { modules.forEach {
backendContext.testRoots[it]?.let { testContainer -> backendContext.testRoots[it]?.let { testContainer ->
statements.startRegion("block: tests") statements.startRegion("block: tests")
statements += JsInvocation(context.getNameForStaticFunction(testContainer).makeRef()).makeStmt() statements += JsInvocation(staticContext.getNameForStaticFunction(testContainer).makeRef()).makeStmt()
statements.endRegion() statements.endRegion()
} }
} }
@@ -351,7 +345,7 @@ class IrModuleToJsTransformer(
private fun generateMainArguments( private fun generateMainArguments(
generateArgv: Boolean, generateArgv: Boolean,
generateContinuation: Boolean, generateContinuation: Boolean,
rootContext: JsGenerationContext staticContext: JsStaticContext,
): List<JsExpression> { ): List<JsExpression> {
val mainArguments = this.mainArguments!! val mainArguments = this.mainArguments!!
val mainArgumentsArray = val mainArgumentsArray =
@@ -360,22 +354,22 @@ class IrModuleToJsTransformer(
val continuation = if (generateContinuation) { val continuation = if (generateContinuation) {
backendContext.coroutineEmptyContinuation.owner backendContext.coroutineEmptyContinuation.owner
.let { it.getter!! } .let { it.getter!! }
.let { rootContext.getNameForStaticFunction(it) } .let { staticContext.getNameForStaticFunction(it) }
.let { JsInvocation(it.makeRef()) } .let { JsInvocation(it.makeRef()) }
} else null } else null
return listOfNotNull(mainArgumentsArray, continuation) return listOfNotNull(mainArgumentsArray, continuation)
} }
private fun generateCallToMain(modules: Iterable<IrModuleFragment>, rootContext: JsGenerationContext): List<JsStatement> { private fun generateCallToMain(modules: Iterable<IrModuleFragment>, staticContext: JsStaticContext): List<JsStatement> {
// TODO: Generate calls to main as IR->IR lowering // TODO: Generate calls to main as IR->IR lowering
if (mainArguments == null) return emptyList() // in case `NO_MAIN` and `main(..)` exists if (mainArguments == null) return emptyList() // in case `NO_MAIN` and `main(..)` exists
val mainFunction = JsMainFunctionDetector(backendContext).getMainFunctionOrNull(modules.last()) val mainFunction = JsMainFunctionDetector(backendContext).getMainFunctionOrNull(modules.last())
return mainFunction?.let { return mainFunction?.let {
val jsName = rootContext.getNameForStaticFunction(it) val jsName = staticContext.getNameForStaticFunction(it)
val generateArgv = it.valueParameters.firstOrNull()?.isStringArrayParameter() ?: false val generateArgv = it.valueParameters.firstOrNull()?.isStringArrayParameter() ?: false
val generateContinuation = it.isLoweredSuspendFunction(backendContext) val generateContinuation = it.isLoweredSuspendFunction(backendContext)
listOf(JsInvocation(jsName.makeRef(), generateMainArguments(generateArgv, generateContinuation, rootContext)).makeStmt()) listOf(JsInvocation(jsName.makeRef(), generateMainArguments(generateArgv, generateContinuation, staticContext)).makeStmt())
} ?: emptyList() } ?: emptyList()
} }
@@ -26,12 +26,12 @@ val emptyScope: JsScope
} }
class JsGenerationContext( class JsGenerationContext(
val currentFile: IrFile?, val currentFile: IrFile,
val currentFunction: IrFunction?, val currentFunction: IrFunction?,
val staticContext: JsStaticContext, val staticContext: JsStaticContext,
val localNames: LocalNameGenerator? = null val localNames: LocalNameGenerator? = null
): IrNamer by staticContext { ): IrNamer by staticContext {
fun newFile(file: IrFile? = null, func: IrFunction? = null, localNames: LocalNameGenerator? = null): JsGenerationContext { fun newFile(file: IrFile, func: IrFunction? = null, localNames: LocalNameGenerator? = null): JsGenerationContext {
return JsGenerationContext( return JsGenerationContext(
currentFile = file, currentFile = file,
currentFunction = func, currentFunction = func,