diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt index c7ae4c40975..a7c1b8f7a4e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt @@ -53,6 +53,12 @@ class PropertiesLowering( return declaration } + override fun visitScript(declaration: IrScript): IrStatement { + declaration.transformChildrenVoid(this) + declaration.transformDeclarationsFlat { lowerProperty(it, ClassKind.CLASS) } + return declaration + } + private fun lowerProperty(declaration: IrDeclaration, kind: ClassKind): List? = if (declaration is IrProperty) if (skipExternalProperties && declaration.isEffectivelyExternal()) listOf(declaration) else { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrDeclarationToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrDeclarationToJsTransformer.kt index a09ff04aa0a..43b7e17d8ad 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrDeclarationToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrDeclarationToJsTransformer.kt @@ -7,7 +7,10 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.js.backend.ast.JsEmpty +import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock +import org.jetbrains.kotlin.js.backend.ast.JsStatement +import org.jetbrains.kotlin.js.backend.ast.JsVars @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer { @@ -44,4 +47,11 @@ class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer { override fun visitFile(declaration: IrFile, data: JsGenerationContext): JsBlock { val fileContext = data.newDeclaration() - val block = JsBlock() + val block = JsGlobalBlock() declaration.declarations.forEach { block.statements.add(it.accept(IrDeclarationToJsTransformer(), fileContext)) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt index b4516591316..442428e776f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt @@ -25,15 +25,17 @@ import org.jetbrains.kotlin.utils.DFS class IrModuleToJsTransformer( private val backendContext: JsIrBackendContext, private val mainFunction: IrSimpleFunction?, - private val mainArguments: List? + private val mainArguments: List?, + private val generateScriptModule: Boolean = false, + var namer: NameTables = NameTables(emptyList()) ) { val moduleName = backendContext.configuration[CommonConfigurationKeys.MODULE_NAME]!! private val moduleKind = backendContext.configuration[JSConfigurationKeys.MODULE_KIND]!! private fun generateModuleBody(module: IrModuleFragment, context: JsGenerationContext): List { - val statements = mutableListOf( - JsStringLiteral("use strict").makeStmt() - ) + val statements = mutableListOf().also { + if (!generateScriptModule) it += JsStringLiteral("use strict").makeStmt() + } val preDeclarationBlock = JsBlock() val postDeclarationBlock = JsBlock() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrNamerImpl.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrNamerImpl.kt index 967ca584f23..b1fe1a2ba68 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrNamerImpl.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrNamerImpl.kt @@ -37,7 +37,7 @@ class IrNamerImpl(private val newNameTables: NameTables) : IrNamer { } override fun getNameForField(field: IrField): JsName { - return if (field.isStatic) { + return if (field.isStatic || field.parent is IrScript) { getNameForStaticDeclaration(field) } else { getNameForMemberField(field) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrScript.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrScript.kt new file mode 100644 index 00000000000..f24b333c717 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrScript.kt @@ -0,0 +1,18 @@ +/* + * 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.declarations + +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol + +//TODO: make IrScript as IrPackageFragment, because script is used as a file, not as a class +//NOTE: declarations and statements stored separately +interface IrScript : IrSymbolDeclaration, IrDeclarationContainer, IrDeclarationWithName, IrDeclarationParent { + val statements: MutableList + + // NOTE: is the result of the FE conversion, because there script interpreted as a class and has receiver + var thisReceiver: IrValueParameter +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrScriptImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrScriptImpl.kt new file mode 100644 index 00000000000..95bf4dbac43 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrScriptImpl.kt @@ -0,0 +1,49 @@ +/* + * 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.declarations.impl + +import org.jetbrains.kotlin.descriptors.ScriptDescriptor +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol +import org.jetbrains.kotlin.ir.util.transform +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.Name + +private val SCRIPT_ORIGIN = object : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE") {} + +class IrScriptImpl( + override val symbol: IrScriptSymbol, + override val name: Name +) : IrScript, IrDeclarationBase(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SCRIPT_ORIGIN) { + override val declarations: MutableList = mutableListOf() + override val statements: MutableList = mutableListOf() + + override lateinit var thisReceiver: IrValueParameter + override val descriptor: ScriptDescriptor = symbol.descriptor + + init { + symbol.bind(this) + } + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitScript(this, data) + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + declarations.forEach { it.accept(visitor, data) } + statements.forEach { it.accept(visitor, data) } + thisReceiver.accept(visitor, data) + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + declarations.transform { it.transform(transformer, data) } + statements.transform { it.transform(transformer, data) } + thisReceiver = thisReceiver.transform(transformer, data) + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt index cbed2fb1550..c802e5e6283 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.ir.symbols import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.IrScript import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock import org.jetbrains.kotlin.ir.util.IrSymbolVisitor import org.jetbrains.kotlin.types.model.TypeConstructorMarker @@ -96,6 +97,13 @@ interface IrClassSymbol : visitor.visitClassSymbol(this, data) } +interface IrScriptSymbol : + IrSymbol, IrBindableSymbol { + + override fun accept(visitor: IrSymbolVisitor, data: D): R = + visitor.visitSymbol(this, data) +} + interface IrTypeParameterSymbol : IrClassifierSymbol, IrBindableSymbol, TypeParameterMarker { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrScriptSymbolImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrScriptSymbolImpl.kt new file mode 100644 index 00000000000..131eaabf425 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/impl/IrScriptSymbolImpl.kt @@ -0,0 +1,13 @@ +/* + * 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.symbols.impl + +import org.jetbrains.kotlin.descriptors.ScriptDescriptor +import org.jetbrains.kotlin.ir.declarations.IrScript +import org.jetbrains.kotlin.ir.symbols.IrScriptSymbol + +class IrScriptSymbolImpl(descriptor: ScriptDescriptor) : + IrScriptSymbol, IrBindableSymbolBase(descriptor) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index 9c55d255f80..dc3babd0f0b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -345,6 +345,8 @@ class RenderIrElementVisitor : IrElementVisitor { "FUN ${renderOriginIfNonTrivial()}" } + override fun visitScript(declaration: IrScript, data: Nothing?) = "SCRIPT" + override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Nothing?): String = declaration.runTrimEnd { "FUN ${renderOriginIfNonTrivial()}" + diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 96fa87a42ce..afbabb0e8a5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -192,7 +192,9 @@ open class SymbolTable : ReferenceSymbolTable { currentScope?.dump() ?: "" } - private val externalPackageFragmentTable = FlatSymbolTable() + private val externalPackageFragmentTable = + FlatSymbolTable() + private val scriptSymbolTable = FlatSymbolTable() private val classSymbolTable = FlatSymbolTable() private val constructorSymbolTable = FlatSymbolTable() private val enumEntrySymbolTable = FlatSymbolTable() @@ -232,6 +234,21 @@ open class SymbolTable : ReferenceSymbolTable { IrAnonymousInitializerSymbolImpl(descriptor) ) + fun listExistedScripts() = scriptSymbolTable.descriptorToSymbol.map { it.value } + + fun declareScript( + descriptor: ScriptDescriptor, + scriptFactory: (IrScriptSymbol) -> IrScript = { symbol: IrScriptSymbol -> + IrScriptImpl(symbol, descriptor.name) + } + ): IrScript { + return scriptSymbolTable.declare( + descriptor, + { IrScriptSymbolImpl(descriptor) }, + scriptFactory + ) + } + fun declareClass( startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor, modality: Modality = descriptor.modality, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt index cd41a520755..0d13fcfc674 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt @@ -37,6 +37,7 @@ interface IrElementTransformer : IrElementVisitor { override fun visitDeclaration(declaration: IrDeclaration, data: D): IrStatement = declaration.also { it.transformChildren(this, data) } + override fun visitScript(declaration: IrScript, data: D) = visitDeclaration(declaration, data) override fun visitClass(declaration: IrClass, data: D) = visitDeclaration(declaration, data) override fun visitFunction(declaration: IrFunction, data: D) = visitDeclaration(declaration, data) override fun visitSimpleFunction(declaration: IrSimpleFunction, data: D) = visitFunction(declaration, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt index 837d9617511..8f90f8cce3d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt @@ -46,6 +46,9 @@ abstract class IrElementTransformerVoid : IrElementTransformer { open fun visitDeclaration(declaration: IrDeclaration): IrStatement = declaration.transformChildren() final override fun visitDeclaration(declaration: IrDeclaration, data: Nothing?): IrStatement = visitDeclaration(declaration) + open fun visitScript(declaration: IrScript) = visitDeclaration(declaration) + final override fun visitScript(declaration: IrScript, data: Nothing?) = visitScript(declaration) + open fun visitClass(declaration: IrClass) = visitDeclaration(declaration) final override fun visitClass(declaration: IrClass, data: Nothing?) = visitClass(declaration) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt index e0190280cb5..26a497fa67d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt @@ -26,6 +26,7 @@ interface IrElementVisitor { fun visitPackageFragment(declaration: IrPackageFragment, data: D) = visitElement(declaration, data) fun visitFile(declaration: IrFile, data: D) = visitPackageFragment(declaration, data) fun visitExternalPackageFragment(declaration: IrExternalPackageFragment, data: D) = visitPackageFragment(declaration, data) + fun visitScript(declaration: IrScript, data: D) = visitDeclaration(declaration, data) fun visitDeclaration(declaration: IrDeclaration, data: D) = visitElement(declaration, data) fun visitClass(declaration: IrClass, data: D) = visitDeclaration(declaration, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt index 2285b98c073..5394eb267a0 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt @@ -43,6 +43,9 @@ interface IrElementVisitorVoid : IrElementVisitor { fun visitClass(declaration: IrClass) = visitDeclaration(declaration) override fun visitClass(declaration: IrClass, data: Nothing?) = visitClass(declaration) + fun visitScript(declaration: IrScript) = visitDeclaration(declaration) + override fun visitScript(declaration: IrScript, data: Nothing?) = visitScript(declaration) + fun visitFunction(declaration: IrFunction) = visitDeclaration(declaration) override fun visitFunction(declaration: IrFunction, data: Nothing?) = visitFunction(declaration)