K2 Scripting: fix script this receiver handling in IR

also fix accessor lowering
This commit is contained in:
Ilya Chernikov
2023-05-03 15:54:13 +02:00
committed by Space Team
parent 07df03dbec
commit 02e2438d37
11 changed files with 48 additions and 23 deletions
@@ -206,7 +206,7 @@ fun FirReference.toSymbolForCall(
val property = declarationStorage.getIrPropertySymbol(boundSymbol).owner as? IrProperty
property?.let { conversionScope.parentAccessorOfPropertyFromStack(it) }?.symbol
}
is FirScriptSymbol -> declarationStorage.getCachedIrScript(boundSymbol.fir)?.thisReceiver?.symbol
else -> null
}
}
@@ -21,10 +21,7 @@ import org.jetbrains.kotlin.fir.backend.generators.OperatorExpressionGenerator
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.declarations.utils.isSealed
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.deserialization.toQualifiedPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
@@ -41,10 +38,12 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
import org.jetbrains.kotlin.ir.util.constructors
@@ -208,9 +207,25 @@ class Fir2IrVisitor(
return declarationStorage.getCachedIrScript(script)!!.also { irScript ->
irScript.parent = conversionScope.parentFromStack()
declarationStorage.enterScope(irScript)
irScript.explicitCallParameters = script.parameters.map { parameter ->
declarationStorage.createIrVariable(parameter, irScript)
declarationStorage.createIrVariable(parameter, irScript, givenOrigin = IrDeclarationOrigin.SCRIPT_CALL_PARAMETER)
}
irScript.thisReceiver = script.contextReceivers.find { it.customLabelName?.asString() == SCRIPT_SPECIAL_NAME_STRING }?.let { receiver ->
receiver.convertWithOffsets { startOffset, endOffset ->
irFactory.createValueParameter(
startOffset, endOffset, IrDeclarationOrigin.INSTANCE_RECEIVER, SpecialNames.THIS, receiver.typeRef.toIrType(),
isAssignable = false, IrValueParameterSymbolImpl(), UNDEFINED_PARAMETER_INDEX,
varargElementType = null,
isCrossinline = false, isNoinline = false,
isHidden = false,
).also {
it.parent = irScript
}
}
}
conversionScope.withParent(irScript) {
for (statement in script.statements) {
val irStatement = if (statement is FirDeclaration) {
@@ -0,0 +1,9 @@
/*
* Copyright 2010-2023 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.fir.declarations.utils
const val SCRIPT_SPECIAL_NAME_STRING = "<script>"
const val SCRIPT_RECEIVER_NAME_PREFIX = "\$script_receiver"
@@ -445,9 +445,9 @@ private class ScriptsToClassesLowering(val context: JvmBackendContext, val inner
if (initializer != null) {
field.initializer = initializer
}
property.addDefaultGetter(this, context.irBuiltIns)
}
property.addDefaultGetter(this, context.irBuiltIns)
}
}
}
@@ -488,11 +488,14 @@ private class ScriptToClassTransformer(
}
}
val scriptThisType = IrSimpleTypeImpl(irScriptClass.symbol, false, emptyList(), emptyList())
val scriptClassReceiver =
irScript.thisReceiver?.transform(this, ScriptToClassTransformerContext(null, null, null, false)) ?: run {
irScript.thisReceiver?.let {
it.type = scriptThisType
it.transform(this, ScriptToClassTransformerContext(null, null, null, false))
} ?: run {
context.symbolTable.enterScope(irScriptClass)
val thisType = IrSimpleTypeImpl(irScriptClass.symbol, false, emptyList(), emptyList())
val newReceiver = irScriptClass.createThisReceiverParameter(IrDeclarationOrigin.INSTANCE_RECEIVER, thisType)
val newReceiver = irScriptClass.createThisReceiverParameter(IrDeclarationOrigin.INSTANCE_RECEIVER, scriptThisType)
context.symbolTable.leaveScope(irScriptClass)
newReceiver
}
@@ -689,14 +692,14 @@ private class ScriptToClassTransformer(
return super.visitMemberAccess(expression, data) as IrExpression
}
override fun visitGetField(expression: IrGetField, data: ScriptToClassTransformerContext): IrExpression {
if (expression.receiver == null && expression.symbol.owner.needsScriptReceiver()) {
override fun visitFieldAccess(expression: IrFieldAccessExpression, data: ScriptToClassTransformerContext): IrExpression {
if (expression.receiver == null && expression.symbol.owner.parent.let { it == irScript || it == irScriptClass }) {
expression.receiver =
getAccessCallForScriptInstance(
data, expression.startOffset, expression.endOffset, expression.origin, originalReceiverParameter = null
)
}
return super.visitGetField(expression, data)
return super.visitFieldAccess(expression, data)
}
override fun visitConstructorCall(expression: IrConstructorCall, data: ScriptToClassTransformerContext): IrExpression {
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND_K2: JVM_IR
// expected: rv: 42
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND_K2: JVM_IR
// expected: rv: abc
@@ -1,6 +1,5 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_K2: JVM_IR
// expected: rv: 42
@@ -1,6 +1,5 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_K2: JVM_IR
// expected: rv: 42
@@ -1,6 +1,5 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_K2: JVM_IR
// expected: rv: 42
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND_K2: JVM_IR
// expected: rv: abc!
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.primaryConstructorIfAny
import org.jetbrains.kotlin.fir.declarations.utils.SCRIPT_SPECIAL_NAME_STRING
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
@@ -52,7 +53,7 @@ class FirScriptConfiguratorExtensionImpl(
// TODO: rewrite/extract decision logic for clarity
configuration[ScriptCompilationConfiguration.baseClass]?.let { baseClass ->
val baseClassFqn = FqName.fromSegments(baseClass.typeName.split("."))
contextReceivers.add(buildContextReceiverWithFqName(baseClassFqn))
contextReceivers.add(buildContextReceiverWithFqName(baseClassFqn, Name.special(SCRIPT_SPECIAL_NAME_STRING)))
val baseClassSymbol =
session.dependenciesSymbolProvider.getClassLikeSymbolByClassId(ClassId(baseClassFqn.parent(), baseClassFqn.shortName()))
@@ -138,16 +139,19 @@ class FirScriptConfiguratorExtensionImpl(
configuration?.let { body.invoke(it) }
}
private fun buildContextReceiverWithFqName(baseClassFqn: FqName) =
private fun buildContextReceiverWithFqName(classFqn: FqName, customName: Name? = null) =
buildContextReceiver {
typeRef = buildUserTypeRef {
isMarkedNullable = false
qualifier.addAll(
baseClassFqn.pathSegments().map {
classFqn.pathSegments().map {
FirQualifierPartImpl(null, it, FirTypeArgumentListImpl(null))
}
)
}
if (customName != null) {
customLabelName = customName
}
}
private val _knownAnnotationsForSamWithReceiver = hashSetOf<String>()