K2 Scripting, IR: non-class based scripts support in IR
This commit is contained in:
committed by
Space Team
parent
cc9a7480a2
commit
4af32b8d36
@@ -192,7 +192,7 @@ private open class BodyLoweringVisitor(
|
||||
}
|
||||
|
||||
override fun visitScript(declaration: IrScript, data: IrDeclaration?) {
|
||||
declaration.thisReceiver.accept(this, declaration)
|
||||
declaration.thisReceiver?.accept(this, declaration)
|
||||
ArrayList(declaration.statements).forEach { it.accept(this, declaration) }
|
||||
}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ interface DeclarationTransformer : FileLoweringPass {
|
||||
}
|
||||
declaration.statements.transformSubsetFlat(transformer::transformFlatRestricted)
|
||||
|
||||
declaration.thisReceiver.accept(this, null)
|
||||
declaration.thisReceiver?.accept(this, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ class ScriptRemoveReceiverLowering(val context: CommonBackendContext) : FileLowe
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
return if (expression.symbol === script.thisReceiver.symbol) expression.nullConst()
|
||||
return if (expression.symbol === script.thisReceiver?.symbol) expression.nullConst()
|
||||
else expression
|
||||
}
|
||||
|
||||
|
||||
+55
-7
@@ -32,18 +32,22 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.toIrConst
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmBackendErrors
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
@@ -88,12 +92,16 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner
|
||||
startOffset = 0
|
||||
endOffset = fileEntry.maxOffset
|
||||
origin = IrDeclarationOrigin.SCRIPT_CLASS
|
||||
name = irScript.name
|
||||
name = irScript.name.let {
|
||||
if (it.isSpecial) {
|
||||
NameUtils.getScriptNameForFile(irScript.name.asStringStripSpecialMarkers().removePrefix("script-"))
|
||||
} else it
|
||||
}
|
||||
kind = ClassKind.CLASS
|
||||
visibility = DescriptorVisibilities.PUBLIC
|
||||
modality = Modality.FINAL
|
||||
}.also { irScriptClass ->
|
||||
irScriptClass.superTypes += irScript.baseClass
|
||||
irScriptClass.superTypes += (irScript.baseClass ?: context.irBuiltIns.anyNType)
|
||||
irScriptClass.parent = irFile
|
||||
irScriptClass.metadata = irScript.metadata
|
||||
irScript.targetClass = irScriptClass.symbol
|
||||
@@ -111,8 +119,10 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
if (declaration is IrClassImpl && !declaration.isInner) {
|
||||
val closure = annotator.getClassClosure(declaration)
|
||||
val scriptsReceivers = mutableSetOf(irScript.thisReceiver.type)
|
||||
irScript.earlierScripts?.forEach { scriptsReceivers.add(it.owner.thisReceiver.type) }
|
||||
val scriptsReceivers = mutableSetOf<IrType>().also {
|
||||
it.addIfNotNull(irScript.thisReceiver?.type)
|
||||
}
|
||||
irScript.earlierScripts?.forEach { scriptsReceivers.addIfNotNull(it.owner.thisReceiver?.type) }
|
||||
irScript.implicitReceiversParameters.forEach {
|
||||
scriptsReceivers.add(it.type)
|
||||
scriptsReceivers.add(typeRemapper.remapType(it.type))
|
||||
@@ -208,14 +218,14 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner
|
||||
.transform(lambdaPatcher, ScriptFixLambdasTransformerContext())
|
||||
}
|
||||
|
||||
irScript.constructor?.patchForClass()?.safeAs<IrConstructor>()!!.also { constructor ->
|
||||
(irScript.constructor?.patchForClass()?.safeAs<IrConstructor>() ?: createConstructor(irScriptClass, irScript)).also { constructor ->
|
||||
val explicitParamsStartIndex = if (irScript.earlierScriptsParameter == null) 0 else 1
|
||||
val explicitParameters = constructor.valueParameters.subList(
|
||||
explicitParamsStartIndex,
|
||||
irScript.explicitCallParameters.size + explicitParamsStartIndex
|
||||
)
|
||||
constructor.body = context.createIrBuilder(constructor.symbol).irBlockBody {
|
||||
val baseClassCtor = irScript.baseClass.classOrNull?.owner?.constructors?.firstOrNull()
|
||||
val baseClassCtor = irScript.baseClass?.classOrNull?.owner?.constructors?.firstOrNull()
|
||||
// TODO: process situation with multiple constructors (should probably be an error)
|
||||
if (baseClassCtor == null) {
|
||||
+irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single())
|
||||
@@ -297,6 +307,32 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner
|
||||
}
|
||||
}
|
||||
|
||||
private fun createConstructor(
|
||||
irScriptClass: IrClass,
|
||||
irScript: IrScript
|
||||
): IrConstructor =
|
||||
with(IrFunctionBuilder().apply {
|
||||
isPrimary = true
|
||||
returnType = irScriptClass.thisReceiver!!.type as IrSimpleType
|
||||
}) {
|
||||
irScriptClass.factory.createConstructor(
|
||||
startOffset, endOffset, origin,
|
||||
IrConstructorSymbolImpl(),
|
||||
SpecialNames.INIT,
|
||||
visibility, returnType,
|
||||
isInline = isInline, isExternal = isExternal, isPrimary = isPrimary, isExpect = isExpect,
|
||||
containerSource = containerSource
|
||||
)
|
||||
}.also { irConstructor ->
|
||||
irConstructor.valueParameters = buildList {
|
||||
addIfNotNull(irScript.earlierScriptsParameter)
|
||||
addAll(irScript.explicitCallParameters)
|
||||
addAll(irScript.implicitReceiversParameters)
|
||||
addAll(irScript.providedPropertiesParameters)
|
||||
}
|
||||
irConstructor.parent = irScript
|
||||
}
|
||||
|
||||
private val scriptingJvmPackage by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment(context.state.module, FqName("kotlin.script.experimental.jvm"))
|
||||
}
|
||||
@@ -419,7 +455,19 @@ private class ScriptToClassTransformer(
|
||||
}
|
||||
|
||||
val scriptClassReceiver =
|
||||
irScript.thisReceiver.transform(this, ScriptToClassTransformerContext(null, null, null, false))
|
||||
irScript.thisReceiver?.transform(this, ScriptToClassTransformerContext(null, null, null, false)) ?: run {
|
||||
context.symbolTable.enterScope(irScriptClass)
|
||||
val thisType = IrSimpleTypeImpl(irScriptClass.symbol, false, emptyList(), emptyList())
|
||||
context.symbolTable.irFactory.createValueParameter(
|
||||
irScriptClass.startOffset, irScriptClass.endOffset, IrDeclarationOrigin.INSTANCE_RECEIVER, IrValueParameterSymbolImpl(),
|
||||
SpecialNames.THIS, UNDEFINED_PARAMETER_INDEX, thisType,
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false,
|
||||
isHidden = false, isAssignable = false
|
||||
).also {
|
||||
it.parent = irScriptClass
|
||||
context.symbolTable.leaveScope(irScriptClass)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrDeclaration.transformParent() {
|
||||
if (parent == irScript) {
|
||||
|
||||
@@ -86,7 +86,7 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
||||
it.owner != irScript && it.descriptor !in importedScripts
|
||||
}
|
||||
irScript.earlierScripts?.forEach {
|
||||
context.symbolTable.introduceValueParameter(it.owner.thisReceiver)
|
||||
context.symbolTable.introduceValueParameter(it.owner.thisReceiver!!)
|
||||
}
|
||||
|
||||
fun createValueParameter(valueParameterDescriptor: ValueParameterDescriptor): IrValueParameter {
|
||||
@@ -142,7 +142,7 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
||||
|
||||
irScript.constructor = with(IrFunctionBuilder().apply {
|
||||
isPrimary = true
|
||||
returnType = irScript.thisReceiver.type as IrSimpleType
|
||||
returnType = irScript.thisReceiver!!.type as IrSimpleType
|
||||
}) {
|
||||
irScript.factory.createConstructor(
|
||||
startOffset, endOffset, origin,
|
||||
@@ -240,7 +240,7 @@ class ScriptGenerator(declarationGenerator: DeclarationGenerator) : DeclarationG
|
||||
).apply {
|
||||
value = irComponentCall
|
||||
receiver = IrGetValueImpl(
|
||||
ktEntry.startOffsetSkippingComments, ktEntry.endOffset, irScript.thisReceiver.symbol
|
||||
ktEntry.startOffsetSkippingComments, ktEntry.endOffset, irScript.thisReceiver!!.symbol
|
||||
)
|
||||
}
|
||||
irBlock.statements.add(irComponentInitializer)
|
||||
|
||||
@@ -26,9 +26,9 @@ abstract class IrScript : IrDeclarationBase(), IrDeclarationWithName, IrDeclarat
|
||||
IrStatementContainer, IrMetadataSourceOwner {
|
||||
abstract override val symbol: IrScriptSymbol
|
||||
|
||||
abstract var thisReceiver: IrValueParameter
|
||||
abstract var thisReceiver: IrValueParameter?
|
||||
|
||||
abstract var baseClass: IrType
|
||||
abstract var baseClass: IrType?
|
||||
|
||||
abstract var explicitCallParameters: List<IrValueParameter>
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class IrScript : IrDeclarationBase(), IrDeclarationWithName, IrDeclarat
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
statements.forEach { it.accept(visitor, data) }
|
||||
thisReceiver.accept(visitor, data)
|
||||
thisReceiver?.accept(visitor, data)
|
||||
explicitCallParameters.forEach { it.accept(visitor, data) }
|
||||
implicitReceiversParameters.forEach { it.accept(visitor, data) }
|
||||
providedPropertiesParameters.forEach { it.accept(visitor, data) }
|
||||
@@ -62,7 +62,7 @@ abstract class IrScript : IrDeclarationBase(), IrDeclarationWithName, IrDeclarat
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
statements.transformInPlace(transformer, data)
|
||||
thisReceiver = thisReceiver.transform(transformer, data)
|
||||
thisReceiver = thisReceiver?.transform(transformer, data)
|
||||
explicitCallParameters = explicitCallParameters.transformIfNeeded(transformer, data)
|
||||
implicitReceiversParameters = implicitReceiversParameters.transformIfNeeded(transformer,
|
||||
data)
|
||||
|
||||
@@ -43,9 +43,9 @@ class IrScriptImpl(
|
||||
|
||||
override var metadata: MetadataSource? = null
|
||||
|
||||
override lateinit var thisReceiver: IrValueParameter
|
||||
override var thisReceiver: IrValueParameter? = null
|
||||
override var baseClass: IrType? = null
|
||||
|
||||
override lateinit var baseClass: IrType
|
||||
override lateinit var explicitCallParameters: List<IrValueParameter>
|
||||
override lateinit var implicitReceiversParameters: List<IrValueParameter>
|
||||
override lateinit var providedProperties: List<IrPropertySymbol>
|
||||
|
||||
@@ -130,7 +130,7 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
declaration.startOffset,
|
||||
declaration.endOffset
|
||||
).also { scriptCopy ->
|
||||
scriptCopy.thisReceiver = declaration.thisReceiver.transform()
|
||||
scriptCopy.thisReceiver = declaration.thisReceiver?.transform()
|
||||
declaration.statements.mapTo(scriptCopy.statements) { it.transform() }
|
||||
scriptCopy.earlierScripts = declaration.earlierScripts
|
||||
scriptCopy.earlierScriptsParameter = declaration.earlierScriptsParameter
|
||||
|
||||
@@ -398,8 +398,8 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+symbol(scriptSymbolType)
|
||||
// NOTE: is the result of the FE conversion, because there script interpreted as a class and has receiver
|
||||
// TODO: consider removing from here and handle appropriately in the lowering
|
||||
+field("thisReceiver", valueParameter, mutable = true, isChild = true)
|
||||
+field("baseClass", irTypeType, mutable = true)
|
||||
+field("thisReceiver", valueParameter, mutable = true, isChild = true, nullable = true) // K1
|
||||
+field("baseClass", irTypeType, mutable = true, nullable = true) // K1
|
||||
+listField("explicitCallParameters", valueParameter, mutability = Var, isChild = true)
|
||||
+listField("implicitReceiversParameters", valueParameter, mutability = Var, isChild = true)
|
||||
+listField("providedProperties", propertySymbolType, mutability = Var)
|
||||
@@ -408,7 +408,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+field("earlierScriptsParameter", valueParameter, mutable = true, nullable = true, isChild = true)
|
||||
+listField("earlierScripts", scriptSymbolType, mutability = Var, nullable = true)
|
||||
+field("targetClass", classSymbolType, mutable = true, nullable = true)
|
||||
+field("constructor", constructor, mutable = true, nullable = true)
|
||||
+field("constructor", constructor, mutable = true, nullable = true) // K1
|
||||
}
|
||||
val simpleFunction: ElementConfig by element(Declaration) {
|
||||
visitorParent = function
|
||||
|
||||
Reference in New Issue
Block a user