[FIR2IR] Re-use applyCallArguments for IrDelegatedConstructorCall

This commit is contained in:
Mikhail Glukhikh
2020-04-13 12:01:56 +03:00
parent 1ba160b3de
commit 1500131eb0
7 changed files with 60 additions and 78 deletions
@@ -62,10 +62,10 @@ class Fir2IrVisitor(
private val conversionScope = Fir2IrConversionScope() private val conversionScope = Fir2IrConversionScope()
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope, fakeOverrideMode)
private val callGenerator = CallAndReferenceGenerator(components, this, conversionScope) private val callGenerator = CallAndReferenceGenerator(components, this, conversionScope)
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope, callGenerator, fakeOverrideMode)
private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() } private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration) private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration)
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.psi.KtPropertyDelegate import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
import java.lang.IllegalArgumentException
internal class CallAndReferenceGenerator( internal class CallAndReferenceGenerator(
private val components: Fir2IrComponents, private val components: Fir2IrComponents,
@@ -292,7 +293,7 @@ internal class CallAndReferenceGenerator(
} }
} }
private fun IrExpression.applyCallArguments(call: FirCall?): IrExpression { internal fun IrExpression.applyCallArguments(call: FirCall?): IrExpression {
if (call == null) return this if (call == null) return this
return when (this) { return when (this) {
is IrCallWithIndexedArgumentsBase -> { is IrCallWithIndexedArgumentsBase -> {
@@ -301,15 +302,16 @@ internal class CallAndReferenceGenerator(
apply { apply {
val argumentMapping = call.argumentMapping val argumentMapping = call.argumentMapping
if (argumentMapping != null && argumentMapping.isNotEmpty()) { if (argumentMapping != null && argumentMapping.isNotEmpty()) {
require(call is FirFunctionCall) val calleeReference = when (call) {
val function = is FirFunctionCall -> call.calleeReference
((call.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir is FirDelegatedConstructorCall -> call.calleeReference
else -> throw IllegalArgumentException("Unsupported call: ${call.render()}")
} as? FirResolvedNamedReference
val function = (calleeReference?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir
val valueParameters = function?.valueParameters val valueParameters = function?.valueParameters
if (valueParameters != null) { if (valueParameters != null) {
return applyArgumentsWithReordering( return applyArgumentsWithReorderingIfNeeded(argumentMapping, valueParameters)
argumentMapping, valueParameters, visitor, conversionScope, declarationStorage
)
} }
} }
for ((index, argument) in call.arguments.withIndex()) { for ((index, argument) in call.arguments.withIndex()) {
@@ -338,6 +340,50 @@ internal class CallAndReferenceGenerator(
} }
} }
private fun IrCallWithIndexedArgumentsBase.applyArgumentsWithReorderingIfNeeded(
argumentMapping: Map<FirExpression, FirValueParameter>,
valueParameters: List<FirValueParameter>,
): IrExpressionBase {
if (needArgumentReordering(argumentMapping.values, valueParameters)) {
return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply {
for ((argument, parameter) in argumentMapping) {
val parameterIndex = valueParameters.indexOf(parameter)
val irArgument = visitor.convertToIrExpression(argument)
if (irArgument.hasNoSideEffects()) {
putValueArgument(parameterIndex, irArgument)
} else {
val tempVar = declarationStorage.declareTemporaryVariable(irArgument, parameter.name.asString()).apply {
parent = conversionScope.parentFromStack()
}
this.statements.add(tempVar)
putValueArgument(parameterIndex, IrGetValueImpl(startOffset, endOffset, tempVar.symbol, null))
}
}
this.statements.add(this@applyArgumentsWithReorderingIfNeeded)
}
} else {
for ((argument, parameter) in argumentMapping) {
val argumentExpression = visitor.convertToIrExpression(argument)
putValueArgument(valueParameters.indexOf(parameter), argumentExpression)
}
return this
}
}
private fun needArgumentReordering(
parametersInActualOrder: Collection<FirValueParameter>,
valueParameters: List<FirValueParameter>
): Boolean {
var lastValueParameterIndex = -1
for (parameter in parametersInActualOrder) {
val index = valueParameters.indexOf(parameter)
if (index < lastValueParameterIndex) {
return true
}
lastValueParameterIndex = index
}
return false
}
private fun IrExpression.applyTypeArguments(access: FirQualifiedAccess): IrExpression { private fun IrExpression.applyTypeArguments(access: FirQualifiedAccess): IrExpression {
return when (this) { return when (this) {
@@ -469,50 +515,3 @@ internal class CallAndReferenceGenerator(
} }
} }
internal fun IrCallWithIndexedArgumentsBase.applyArgumentsWithReordering(
argumentMapping: Map<FirExpression, FirValueParameter>,
valueParameters: List<FirValueParameter>,
visitor: Fir2IrVisitor,
conversionScope: Fir2IrConversionScope,
declarationStorage: Fir2IrDeclarationStorage
): IrExpressionBase {
if (needArgumentReordering(argumentMapping.values, valueParameters)) {
return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply {
for ((argument, parameter) in argumentMapping) {
val parameterIndex = valueParameters.indexOf(parameter)
val irArgument = visitor.convertToIrExpression(argument)
if (irArgument.hasNoSideEffects()) {
putValueArgument(parameterIndex, irArgument)
} else {
val tempVar = declarationStorage.declareTemporaryVariable(irArgument, parameter.name.asString()).apply {
parent = conversionScope.parentFromStack()
}
this.statements.add(tempVar)
putValueArgument(parameterIndex, IrGetValueImpl(startOffset, endOffset, tempVar.symbol, null))
}
}
this.statements.add(this@applyArgumentsWithReordering)
}
} else {
for ((argument, parameter) in argumentMapping) {
val argumentExpression = visitor.convertToIrExpression(argument)
putValueArgument(valueParameters.indexOf(parameter), argumentExpression)
}
return this
}
}
private fun needArgumentReordering(
parametersInActualOrder: Collection<FirValueParameter>,
valueParameters: List<FirValueParameter>
): Boolean {
var lastValueParameterIndex = -1
for (parameter in parametersInActualOrder) {
val index = valueParameters.indexOf(parameter)
if (index < lastValueParameterIndex) {
return true
}
lastValueParameterIndex = index
}
return false
}
@@ -12,13 +12,12 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
@@ -29,6 +28,7 @@ internal class ClassMemberGenerator(
private val components: Fir2IrComponents, private val components: Fir2IrComponents,
private val visitor: Fir2IrVisitor, private val visitor: Fir2IrVisitor,
private val conversionScope: Fir2IrConversionScope, private val conversionScope: Fir2IrConversionScope,
private val callGenerator: CallAndReferenceGenerator,
fakeOverrideMode: FakeOverrideMode fakeOverrideMode: FakeOverrideMode
) : Fir2IrComponents by components { ) : Fir2IrComponents by components {
@@ -211,7 +211,7 @@ internal class ClassMemberGenerator(
return this return this
} }
private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrExpressionBase { private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrExpression {
val constructedIrType = constructedTypeRef.toIrType() val constructedIrType = constructedTypeRef.toIrType()
val constructorSymbol = (this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol val constructorSymbol = (this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol
?: return convertWithOffsets { startOffset, endOffset -> ?: return convertWithOffsets { startOffset, endOffset ->
@@ -240,21 +240,8 @@ internal class ClassMemberGenerator(
irConstructorSymbol irConstructorSymbol
) )
}.let { }.let {
val argumentMapping = mutableMapOf<FirExpression, FirValueParameter>() with(callGenerator) {
val valueParameters = constructorSymbol.fir.valueParameters it.applyCallArguments(this@toIrDelegatingConstructorCall)
for (argument in arguments) {
if (argument is FirNamedArgumentExpression) {
valueParameters.firstOrNull { it.name == argument.name }?.let { argumentMapping[argument] = it }
}
}
if (argumentMapping.size == valueParameters.size) {
it.applyArgumentsWithReordering(argumentMapping, valueParameters, visitor, conversionScope, declarationStorage)
} else {
for ((index, argument) in arguments.withIndex()) {
val argumentExpression = visitor.convertToIrExpression(argument)
it.putValueArgument(index, argumentExpression)
}
it
} }
} }
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
enum class Foo(val a: Int = 1, val b: String) { enum class Foo(val a: Int = 1, val b: String) {
B(2, "b"), B(2, "b"),
C(b = "b") C(b = "b")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
enum class Foo(val a: Int = 1, val b: String = "a") { enum class Foo(val a: Int = 1, val b: String = "a") {
A(), A(),
B(2, "b"), B(2, "b"),
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
enum class Foo(val a: Double = 1.0, val b: Double = 1.0) { enum class Foo(val a: Double = 1.0, val b: Double = 1.0) {
A(), A(),
B(2.0, 2.0), B(2.0, 2.0),
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class A(val result: String) { open class A(val result: String) {
constructor(x: Int = 11, y: Int = 22, z: Int = 33) : this("$x$y$z") constructor(x: Int = 11, y: Int = 22, z: Int = 33) : this("$x$y$z")
} }