[IR JS BE] update NameTables for working with repl
This commit is contained in:
committed by
romanart
parent
184ae2fa43
commit
24cfd0e88c
@@ -262,12 +262,18 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
||||
|
||||
// TODO move CharSequence-related stiff to IntrinsifyCallsLowering
|
||||
val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence")))
|
||||
val charSequenceLengthPropertyGetterSymbol =
|
||||
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "length" }.getter!!.symbol
|
||||
val charSequenceGetFunctionSymbol =
|
||||
val charSequenceLengthPropertyGetterSymbol by lazy {
|
||||
with(charSequenceClassSymbol.owner.declarations) {
|
||||
filterIsInstance<IrProperty>().firstOrNull { it.name.asString() == "length" }?.getter ?:
|
||||
filterIsInstance<IrFunction>().first { it.name.asString() == "<get-length>" }
|
||||
}.symbol
|
||||
}
|
||||
val charSequenceGetFunctionSymbol by lazy {
|
||||
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "get" }.symbol
|
||||
val charSequenceSubSequenceFunctionSymbol =
|
||||
}
|
||||
val charSequenceSubSequenceFunctionSymbol by lazy {
|
||||
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "subSequence" }.symbol
|
||||
}
|
||||
|
||||
|
||||
val jsCharSequenceGet = getInternalFunction("charSequenceGet")
|
||||
|
||||
+23
-15
@@ -73,7 +73,7 @@ class IrModuleToJsTransformer(
|
||||
|
||||
module.files.forEach { StaticMembersLowering(backendContext).lower(it) }
|
||||
|
||||
val namer = NameTables(module.files + additionalPackages)
|
||||
namer.merge(module.files, additionalPackages)
|
||||
|
||||
val program = JsProgram()
|
||||
|
||||
@@ -102,25 +102,33 @@ class IrModuleToJsTransformer(
|
||||
val exportStatements = ExportModelToJsStatements(internalModuleName, namer)
|
||||
.generateModuleExport(exportedModule)
|
||||
|
||||
with(rootFunction) {
|
||||
parameters += JsParameter(internalModuleName)
|
||||
parameters += importedJsModules.map { JsParameter(it.internalName) }
|
||||
with(body) {
|
||||
if (generateScriptModule) {
|
||||
with(program.globalBlock) {
|
||||
statements += importStatements
|
||||
statements += moduleBody
|
||||
statements += exportStatements
|
||||
statements += generateCallToMain(rootContext)
|
||||
statements += JsReturn(internalModuleName.makeRef())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
with(rootFunction) {
|
||||
parameters += JsParameter(internalModuleName)
|
||||
parameters += importedJsModules.map { JsParameter(it.internalName) }
|
||||
with(body) {
|
||||
statements += importStatements
|
||||
statements += moduleBody
|
||||
statements += exportStatements
|
||||
statements += generateCallToMain(rootContext)
|
||||
statements += JsReturn(internalModuleName.makeRef())
|
||||
}
|
||||
}
|
||||
|
||||
program.globalBlock.statements += ModuleWrapperTranslation.wrap(
|
||||
moduleName,
|
||||
rootFunction,
|
||||
importedJsModules,
|
||||
program,
|
||||
kind = moduleKind
|
||||
)
|
||||
program.globalBlock.statements += ModuleWrapperTranslation.wrap(
|
||||
moduleName,
|
||||
rootFunction,
|
||||
importedJsModules,
|
||||
program,
|
||||
kind = moduleKind
|
||||
)
|
||||
}
|
||||
|
||||
return CompilerResult(program.toString(), dts)
|
||||
}
|
||||
|
||||
+115
-46
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
||||
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsMangler
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
@@ -21,10 +22,24 @@ import org.jetbrains.kotlin.js.naming.isES5IdentifierStart
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
|
||||
fun <T> mapToKey(declaration: T): String {
|
||||
return with(JsMangler) {
|
||||
if (declaration is IrDeclaration && isPublic(declaration)) {
|
||||
declaration.hashedMangle.toString()
|
||||
} else if (declaration is Signature) {
|
||||
declaration.toString().hashMangle.toString()
|
||||
} else "key_have_not_generated"
|
||||
}
|
||||
}
|
||||
|
||||
fun JsMangler.isPublic(declaration: IrDeclaration) =
|
||||
declaration.isExported() && declaration !is IrScript && declaration !is IrVariable && declaration !is IrValueParameter
|
||||
|
||||
class NameTable<T>(
|
||||
val parent: NameTable<*>? = null,
|
||||
private val reserved: MutableSet<String> = mutableSetOf(),
|
||||
val sanitizer: (String) -> String = ::sanitizeName
|
||||
val reserved: MutableSet<String> = mutableSetOf(),
|
||||
val sanitizer: (String) -> String = ::sanitizeName,
|
||||
val mappedNames: MutableMap<String, String> = mutableMapOf()
|
||||
) {
|
||||
var finished = false
|
||||
val names = mutableMapOf<T, String>()
|
||||
@@ -40,6 +55,7 @@ class NameTable<T>(
|
||||
assert(!finished)
|
||||
names[declaration] = name
|
||||
reserved.add(name)
|
||||
mappedNames[mapToKey(declaration)] = name
|
||||
}
|
||||
|
||||
fun declareFreshName(declaration: T, suggestedName: String): String {
|
||||
@@ -134,7 +150,12 @@ fun functionSignature(declaration: IrFunction): Signature {
|
||||
return ParameterTypeBasedSignature(signature, declarationName)
|
||||
}
|
||||
|
||||
class NameTables(packages: List<IrPackageFragment>) {
|
||||
class NameTables(
|
||||
packages: List<IrPackageFragment>,
|
||||
reservedForGlobal: MutableSet<String> = mutableSetOf(),
|
||||
reservedForMember: MutableSet<String> = mutableSetOf(),
|
||||
val mappedNames: MutableMap<String, String> = mutableMapOf()
|
||||
) {
|
||||
val globalNames: NameTable<IrDeclaration>
|
||||
private val memberNames: NameTable<Signature>
|
||||
private val localNames = mutableMapOf<IrDeclaration, NameTable<IrDeclaration>>()
|
||||
@@ -144,61 +165,108 @@ class NameTables(packages: List<IrPackageFragment>) {
|
||||
val stableNamesCollector = StableNamesCollector()
|
||||
packages.forEach { it.acceptChildrenVoid(stableNamesCollector) }
|
||||
|
||||
globalNames = NameTable(reserved = stableNamesCollector.staticNames)
|
||||
memberNames = NameTable(reserved = stableNamesCollector.memberNames)
|
||||
globalNames = NameTable(
|
||||
reserved = (stableNamesCollector.staticNames + reservedForGlobal).toMutableSet(),
|
||||
mappedNames = mappedNames
|
||||
)
|
||||
|
||||
memberNames = NameTable(
|
||||
reserved = (stableNamesCollector.memberNames + reservedForMember).toMutableSet(),
|
||||
mappedNames = mappedNames
|
||||
)
|
||||
|
||||
mappedNames.addAllIfAbsent(mappedNames)
|
||||
|
||||
val classDeclaration = mutableListOf<IrClass>()
|
||||
for (p in packages) {
|
||||
for (declaration in p.declarations) {
|
||||
generateNamesForTopLevelDecl(declaration)
|
||||
if (declaration is IrScript) {
|
||||
for (memberDecl in declaration.declarations) {
|
||||
generateNamesForTopLevelDecl(memberDecl)
|
||||
if (memberDecl is IrClass) {
|
||||
classDeclaration += memberDecl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globalNames.finished = true
|
||||
|
||||
for (declaration in classDeclaration) {
|
||||
acceptDeclaration(declaration)
|
||||
}
|
||||
|
||||
for (p in packages) {
|
||||
for (declaration in p.declarations) {
|
||||
val localNameGenerator = LocalNameGenerator(declaration)
|
||||
|
||||
if (declaration is IrClass) {
|
||||
if (declaration.isEffectivelyExternal()) {
|
||||
declaration.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||
val parent = declaration.parent
|
||||
if (parent is IrClass && !parent.isEnumClass) {
|
||||
generateNameForMemberFunction(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
val parent = declaration.parent
|
||||
if (parent is IrClass && !parent.isEnumClass) {
|
||||
generateNameForMemberField(declaration)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
declaration.thisReceiver!!.acceptVoid(localNameGenerator)
|
||||
for (memberDecl in declaration.declarations) {
|
||||
memberDecl.acceptChildrenVoid(LocalNameGenerator(memberDecl))
|
||||
when (memberDecl) {
|
||||
is IrSimpleFunction ->
|
||||
generateNameForMemberFunction(memberDecl)
|
||||
is IrField ->
|
||||
generateNameForMemberField(memberDecl)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
declaration.acceptChildrenVoid(localNameGenerator)
|
||||
}
|
||||
acceptDeclaration(declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun acceptDeclaration(declaration: IrDeclaration) {
|
||||
val localNameGenerator = LocalNameGenerator(declaration)
|
||||
|
||||
if (declaration is IrClass) {
|
||||
if (declaration.isEffectivelyExternal()) {
|
||||
declaration.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||
val parent = declaration.parent
|
||||
if (parent is IrClass && !parent.isEnumClass) {
|
||||
generateNameForMemberFunction(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
val parent = declaration.parent
|
||||
if (parent is IrClass && !parent.isEnumClass) {
|
||||
generateNameForMemberField(declaration)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
declaration.thisReceiver!!.acceptVoid(localNameGenerator)
|
||||
for (memberDecl in declaration.declarations) {
|
||||
memberDecl.acceptChildrenVoid(LocalNameGenerator(memberDecl))
|
||||
when (memberDecl) {
|
||||
is IrSimpleFunction ->
|
||||
generateNameForMemberFunction(memberDecl)
|
||||
is IrField ->
|
||||
generateNameForMemberField(memberDecl)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
declaration.acceptChildrenVoid(localNameGenerator)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T, K> MutableMap<T, K>.addAllIfAbsent(other: Map<T, K>) {
|
||||
this += other.filter { it.key !in this }
|
||||
}
|
||||
|
||||
private fun packagesAdded() = mappedNames.isEmpty()
|
||||
|
||||
fun merge(files: List<IrPackageFragment>, additionalPackages: List<IrPackageFragment>) {
|
||||
val packages = mutableListOf<IrPackageFragment>().also { it.addAll(files) }
|
||||
if (packagesAdded()) packages.addAll(additionalPackages)
|
||||
|
||||
val table = NameTables(packages, globalNames.reserved, memberNames.reserved, mappedNames)
|
||||
|
||||
globalNames.names.addAllIfAbsent(table.globalNames.names)
|
||||
memberNames.names.addAllIfAbsent(table.memberNames.names)
|
||||
localNames.addAllIfAbsent(table.localNames)
|
||||
loopNames.addAllIfAbsent(table.loopNames)
|
||||
|
||||
globalNames.reserved.addAll(table.globalNames.reserved)
|
||||
memberNames.reserved.addAll(table.memberNames.reserved)
|
||||
}
|
||||
|
||||
private fun generateNameForMemberField(field: IrField) {
|
||||
require(!field.isTopLevel)
|
||||
require(!field.isStatic)
|
||||
@@ -257,12 +325,13 @@ class NameTables(packages: List<IrPackageFragment>) {
|
||||
parent = parent.parent
|
||||
}
|
||||
|
||||
error("Can't find name for declaration ${declaration.fqNameWhenAvailable}")
|
||||
return mappedNames[mapToKey(declaration)] ?: error("Can't find name for declaration ${declaration.fqNameWhenAvailable}")
|
||||
}
|
||||
|
||||
fun getNameForMemberField(field: IrField): String {
|
||||
val signature = fieldSignature(field)
|
||||
val name = memberNames.names[signature]
|
||||
val name = memberNames.names[signature] ?: mappedNames[mapToKey(signature)]
|
||||
|
||||
require(name != null) {
|
||||
"Can't find name for member field $field"
|
||||
}
|
||||
@@ -271,7 +340,7 @@ class NameTables(packages: List<IrPackageFragment>) {
|
||||
|
||||
fun getNameForMemberFunction(function: IrSimpleFunction): String {
|
||||
val signature = functionSignature(function)
|
||||
val name = memberNames.names[signature]
|
||||
val name = memberNames.names[signature] ?: mappedNames[mapToKey(signature)]
|
||||
|
||||
// TODO: Fix hack: Coroutines runtime currently relies on stable names
|
||||
// of `invoke` functions in FunctionN interfaces
|
||||
|
||||
Reference in New Issue
Block a user