From 240abdb75000c299e635c9c977c6e74c641d001f Mon Sep 17 00:00:00 2001 From: "Vitaliy.Tikhonov" Date: Fri, 30 Aug 2019 15:15:46 +0300 Subject: [PATCH] [JS IR BE] update current lowerings for IrScript --- .../kotlin/backend/common/BackendContext.kt | 3 ++ .../backend/common/CommonBackendContext.kt | 1 + .../IrElementTransformerVoidWithContext.kt | 17 +++++++--- .../jetbrains/kotlin/backend/common/Lower.kt | 27 +++++++++++++++ .../lower/DefaultArgumentStubGenerator.kt | 4 ++- .../lower/InlineClassDeclarationLowering.kt | 7 ++-- .../common/lower/LocalClassPopupLowering.kt | 5 +-- .../ir/backend/js/JsIrBackendContext.kt | 4 ++- .../js/lower/BlockDecomposerLowering.kt | 34 ++++++++++++++++++- .../js/lower/PrimitiveCompanionLowering.kt | 7 +++- .../kotlin/backend/jvm/JvmBackendContext.kt | 5 +++ .../kotlin/backend/wasm/WasmBackendContext.kt | 4 +++ .../scripting-compiler-impl/build.gradle.kts | 2 ++ .../scripting/resolve/LazyScriptDescriptor.kt | 16 +++++---- 14 files changed, 116 insertions(+), 20 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/BackendContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/BackendContext.kt index a28ba189fa7..2101abe71bb 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/BackendContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/BackendContext.kt @@ -21,6 +21,8 @@ import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.name.FqName interface BackendContext { @@ -30,4 +32,5 @@ interface BackendContext { val sharedVariablesManager: SharedVariablesManager val declarationFactory: DeclarationFactory val internalPackageFqn: FqName + val transformedFunction: MutableMap } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt index 4bc108dbe77..fb58f30d888 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt @@ -23,4 +23,5 @@ interface CommonBackendContext : BackendContext, LoggingContext { fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean) val configuration: CompilerConfiguration + val scriptMode: Boolean } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt index ad511d172be..cf1b2de8fc6 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt @@ -20,10 +20,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.symbols.IrFileSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid @@ -71,7 +68,15 @@ abstract class IrElementTransformerVoidWithContext : IrElementTransformerVoid() return result } + final override fun visitScript(declaration: IrScript): IrStatement { + scopeStack.push(createScope(declaration)) + val result = visitScriptNew(declaration) + scopeStack.pop() + return result + } + protected val currentFile get() = scopeStack.lastOrNull { it.irElement is IrFile }!!.irElement as IrFile + protected val currentScript get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrScriptSymbol } protected val currentClass get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrClassSymbol } protected val currentFunction get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrFunctionSymbol } protected val currentProperty get() = scopeStack.lastOrNull { it.scope.scopeOwnerSymbol is IrPropertySymbol } @@ -102,6 +107,10 @@ abstract class IrElementTransformerVoidWithContext : IrElementTransformerVoid() open fun visitFieldNew(declaration: IrField): IrStatement { return super.visitField(declaration) } + + open fun visitScriptNew(declaration: IrScript): IrStatement { + return super.visitScript(declaration) + } } abstract class IrElementVisitorVoidWithContext : IrElementVisitorVoid { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/Lower.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/Lower.kt index 43a86009cb1..c9ca06e24e8 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/Lower.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/Lower.kt @@ -39,6 +39,12 @@ interface ClassLoweringPass : FileLoweringPass { override fun lower(irFile: IrFile) = runOnFilePostfix(irFile) } +interface ScriptLoweringPass : FileLoweringPass { + fun lower(irScript: IrScript) + + override fun lower(irFile: IrFile) = runOnFilePostfix(irFile) +} + interface DeclarationContainerLoweringPass : FileLoweringPass { fun lower(irDeclarationContainer: IrDeclarationContainer) @@ -72,14 +78,35 @@ fun ClassLoweringPass.runOnFilePostfix(irFile: IrFile) { }) } +fun ScriptLoweringPass.runOnFilePostfix(irFile: IrFile) { + irFile.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitScript(declaration: IrScript) { + declaration.acceptChildrenVoid(this) + lower(declaration) + } + }) +} + fun DeclarationContainerLoweringPass.asClassLoweringPass() = object : ClassLoweringPass { override fun lower(irClass: IrClass) { this@asClassLoweringPass.lower(irClass) } } +fun DeclarationContainerLoweringPass.asScriptLoweringPass() = object : ScriptLoweringPass { + override fun lower(irScript: IrScript) { + this@asScriptLoweringPass.lower(irScript) + } +} + fun DeclarationContainerLoweringPass.runOnFilePostfix(irFile: IrFile) { this.asClassLoweringPass().runOnFilePostfix(irFile) + this.asScriptLoweringPass().runOnFilePostfix(irFile) + this.lower(irFile as IrDeclarationContainer) } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index 4564559f536..ef4268c2866 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -412,7 +412,9 @@ open class DefaultParameterInjector( class DefaultParameterCleaner constructor(val context: CommonBackendContext) : FunctionLoweringPass { override fun lower(irFunction: IrFunction) { - irFunction.valueParameters.forEach { it.defaultValue = null } + if (!context.scriptMode) { + irFunction.valueParameters.forEach { it.defaultValue = null } + } } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt index f611c1f2d0f..42dac91e4a8 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt @@ -5,15 +5,14 @@ package org.jetbrains.kotlin.backend.common.lower -import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.ir.createStaticFunctionWithReceivers import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -23,8 +22,8 @@ import org.jetbrains.kotlin.name.Name private const val INLINE_CLASS_IMPL_SUFFIX = "-impl" // TODO: Support incremental compilation -class InlineClassLowering(val context: BackendContext) { - private val transformedFunction = mutableMapOf() +class InlineClassLowering(val context: CommonBackendContext) { + private val transformedFunction = if (context.scriptMode) context.transformedFunction else mutableMapOf() val inlineClassDeclarationLowering = object : ClassLoweringPass { override fun lower(irClass: IrClass) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalClassPopupLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalClassPopupLowering.kt index 5f34692f490..42d96652902 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalClassPopupLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalClassPopupLowering.kt @@ -8,6 +8,7 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrScript import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl //This lower takes part of old LocalDeclarationLowering job to pop up local classes from functions @@ -27,8 +28,8 @@ class LocalClassPopupLowering(val context: BackendContext) : FileLoweringPass { val newContainer = allScopes.asReversed().drop(1/*skip self*/).firstOrNull { //find first class local or not; // to reproduce original LocalDeclarationLowering behaviour add: '&& !it.irElement.isLocal' condition - it.irElement is IrClass - }?.irElement as? IrClass ?: currentFile + it.irElement is IrClass || it.irElement is IrScript + }?.irElement?.let { it as? IrClass ?: it as? IrScript } ?: currentFile extractedLocalClasses.add(newDeclaration to newContainer) return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index b018332ea88..6f560518646 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -44,8 +44,10 @@ class JsIrBackendContext( val symbolTable: SymbolTable, irModuleFragment: IrModuleFragment, val additionalExportedDeclarations: Set, - override val configuration: CompilerConfiguration + override val configuration: CompilerConfiguration, + override val scriptMode: Boolean = false ) : CommonBackendContext { + override val transformedFunction = mutableMapOf() override val builtIns = module.builtIns diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt index 9fa8c92f0e7..ca1049b519d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt @@ -39,6 +39,10 @@ abstract class AbstractBlockDecomposerLowering(context: CommonBackendContext) : override fun lower(irDeclarationContainer: IrDeclarationContainer) { irDeclarationContainer.transformDeclarationsFlat { declaration -> when (declaration) { + is IrScript -> { + lower(declaration) + listOf(declaration) + } is IrFunction -> { lower(declaration) listOf(declaration) @@ -49,6 +53,10 @@ abstract class AbstractBlockDecomposerLowering(context: CommonBackendContext) : } } + fun lower(irScript: IrScript) { + irScript.transform(decomposerTransformer, null) + } + fun lower(irFunction: IrFunction) { (irFunction.body as? IrExpressionBody)?.apply { irFunction.body = toBlockBody(irFunction) @@ -94,7 +102,7 @@ class BlockDecomposerTransformer( private val context: CommonBackendContext, private val unreachableExpression: () -> IrExpression ) : IrElementTransformerVoid() { - private lateinit var function: IrFunction + private lateinit var function: IrDeclarationParent private var tmpVarCounter: Int = 0 private val statementTransformer = StatementTransformer() @@ -109,6 +117,30 @@ class BlockDecomposerTransformer( private val booleanNotSymbol = context.irBuiltIns.booleanNotSymbol + override fun visitScript(declaration: IrScript): IrStatement { + function = declaration + + with(declaration) { + val transformedDeclarations = declarations.map { it.transform(statementTransformer, null) as IrDeclaration } + declarations.clear() + declarations.addAll(transformedDeclarations) + + val transformedStatements = mutableListOf() + statements.forEach { + val transformer = if (it === statements.last()) expressionTransformer else statementTransformer + val s = it.transform(transformer, null) + if (s is IrComposite) { + transformedStatements.addAll(s.statements) + } else { + transformedStatements.add(s) + } + } + statements.clear() + statements.addAll(transformedStatements) + } + return declaration + } + override fun visitFunction(declaration: IrFunction): IrStatement { function = declaration tmpVarCounter = 0 diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimitiveCompanionLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimitiveCompanionLowering.kt index 6072e602b57..5124e7ee6fe 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimitiveCompanionLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/PrimitiveCompanionLowering.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile @@ -27,7 +28,11 @@ class PrimitiveCompanionLowering(val context: JsIrBackendContext) : FileLowering if (!irClass.isCompanion) return null - val parent = irClass.parent as IrClass + //TODO: Figure out how to check for primitive companion in case similar to REPL in better way + val parent = irClass.parent as? IrClass + ?: context.symbolTable.referenceClass(irClass.descriptor.containingDeclaration as ClassDescriptor).owner.also { + assert(context.scriptMode) + } if (!parent.defaultType.isPrimitiveType() && !parent.defaultType.isString()) return null diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 3f1706e47ff..a190eb4b39d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.name.FqName @@ -49,6 +50,10 @@ class JvmBackendContext( val phaseConfig: PhaseConfig, private val firMode: Boolean ) : CommonBackendContext { + override val transformedFunction: MutableMap + get() = TODO("not implemented") + override val scriptMode: Boolean = false + override val builtIns = state.module.builtIns val typeMapper = IrTypeMapper(this) val methodSignatureMapper = MethodSignatureMapper(this) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt index 4375cd2e3f0..ddadee8584c 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt @@ -19,6 +19,8 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl import org.jetbrains.kotlin.ir.util.SymbolTable @@ -34,6 +36,8 @@ class WasmBackendContext( ) : CommonBackendContext { override val builtIns = module.builtIns override var inVerbosePhase: Boolean = false + override val scriptMode = false + override val transformedFunction = mutableMapOf() // Place to store declarations excluded from code generation val excludedDeclarations: IrPackageFragment by lazy { diff --git a/plugins/scripting/scripting-compiler-impl/build.gradle.kts b/plugins/scripting/scripting-compiler-impl/build.gradle.kts index f5787e86e89..caf225de6b7 100644 --- a/plugins/scripting/scripting-compiler-impl/build.gradle.kts +++ b/plugins/scripting/scripting-compiler-impl/build.gradle.kts @@ -11,6 +11,8 @@ dependencies { compileOnly(project(":compiler:frontend.java")) compileOnly(project(":compiler:psi")) compileOnly(project(":compiler:plugin-api")) + compileOnly(project(":compiler:cli")) + compileOnly(project(":compiler:ir.serialization.js")) compile(project(":kotlin-scripting-common")) compile(project(":kotlin-scripting-jvm")) compile(kotlinStdlib()) diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt index 04cb507e254..3faffabd65d 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/LazyScriptDescriptor.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors.MISSING_IMPORTED_SCRIPT_FILE import org.jetbrains.kotlin.diagnostics.Errors.MISSING_IMPORTED_SCRIPT_PSI import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getChildOfType @@ -156,13 +157,16 @@ class LazyScriptDescriptor( override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!! internal val baseClassDescriptor: () -> ClassDescriptor? = resolveSession.storageManager.createNullableLazyValue { - val baseClass = getScriptingClass( - scriptCompilationConfiguration()[ScriptCompilationConfiguration.baseClass] - ?: throw IllegalStateException("Base class is not configured for the script ${scriptInfo.script.containingFile}") - ) + val scriptBaseType = scriptCompilationConfiguration()[ScriptCompilationConfiguration.baseClass] + ?: error("Base class is not configured for the script ${scriptInfo.script.containingFile}") + val typeName = scriptBaseType.run { fromClass?.toString()?.replace("class ", "") ?: typeName } + val fqnName = FqName(typeName) + val classId = ClassId.topLevel(fqnName) + findTypeDescriptor( - baseClass, - if (baseClass.qualifiedName?.startsWith("kotlin.script.templates.standard") == true) Errors.MISSING_SCRIPT_STANDARD_TEMPLATE + classId, + typeName, + if (fqnName.parent().asString().startsWith("kotlin.script.templates.standard")) Errors.MISSING_SCRIPT_STANDARD_TEMPLATE else Errors.MISSING_SCRIPT_BASE_CLASS ) }