[FIR] Don't create member function for each when and try expression

Use one function (per session) instead
This commit is contained in:
Dmitriy Novozhilov
2019-09-10 12:00:49 +03:00
parent 996d9a5d90
commit ef5ac7df93
3 changed files with 32 additions and 49 deletions
@@ -26,8 +26,7 @@ interface SyntheticSymbol : ConeSymbol
class SyntheticPropertySymbol(callableId: CallableId) : FirPropertySymbol(callableId), SyntheticSymbol
class FirSyntheticFunctionSymbol(
callableId: CallableId,
val file: FirFile
callableId: CallableId
) : FirNamedFunctionSymbol(callableId), SyntheticSymbol
class FirSyntheticPropertiesScope(
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.references.FirStubReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.SyntheticCallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
@@ -31,14 +32,19 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.types.Variance
class FirSyntheticCallGenerator(private val transformer: FirBodyResolveTransformer) : BodyResolveComponents by transformer {
private val whenSelectFunction: FirMemberFunctionImpl = generateSyntheticSelectFunction(SyntheticCallableId.WHEN)
private val trySelectFunction: FirMemberFunctionImpl = generateSyntheticSelectFunction(SyntheticCallableId.TRY)
fun generateCalleeForWhenExpression(whenExpression: FirWhenExpression): FirWhenExpression? {
val stubReference = whenExpression.calleeReference
assert(stubReference is FirStubReference)
val function = generateWhenCallDeclaration()
val arguments = whenExpression.branches.map { it.result }
val reference = generateCalleeReferenceWithCandidate(function, arguments, SyntheticCallableId.WHEN.callableName) ?: return null // TODO
val reference = generateCalleeReferenceWithCandidate(
whenSelectFunction,
arguments,
SyntheticCallableId.WHEN.callableName
) ?: return null // TODO
return whenExpression.copy(calleeReference = reference)
}
@@ -47,61 +53,24 @@ class FirSyntheticCallGenerator(private val transformer: FirBodyResolveTransform
val stubReference = tryExpression.calleeReference
assert(stubReference is FirStubReference)
val function = generateTryCallDeclaration(tryExpression)
val arguments = mutableListOf<FirExpression>()
with(tryExpression) {
arguments += tryBlock
catches.map {
catches.forEach {
arguments += it.block
}
}
val reference = generateCalleeReferenceWithCandidate(function, arguments, SyntheticCallableId.TRY.callableName) ?: return null // TODO
val reference = generateCalleeReferenceWithCandidate(
trySelectFunction,
arguments,
SyntheticCallableId.TRY.callableName
) ?: return null // TODO
return tryExpression.copy(calleeReference = reference)
}
private fun generateTryCallDeclaration(tryExpression: FirTryExpression): FirMemberFunctionImpl {
val functionSymbol = FirSyntheticFunctionSymbol(SyntheticCallableId.TRY, file)
val typeParameterSymbol = FirTypeParameterSymbol()
val typeParameter = FirTypeParameterImpl(session, null, typeParameterSymbol, Name.identifier("K"), Variance.INVARIANT, false)
val returnType = FirResolvedTypeRefImpl(null, ConeTypeParameterTypeImpl(typeParameterSymbol.toLookupTag(), false))
val tryType = FirResolvedTypeRefImpl(null, returnType.coneTypeUnsafe())
val catchTypes = tryExpression.catches.map {
FirResolvedTypeRefImpl(null, returnType.coneTypeUnsafe())
}
val typeArgument = FirTypeProjectionWithVarianceImpl(null, Variance.INVARIANT, returnType)
return generateMemberFunction(session, functionSymbol, SyntheticCallableId.TRY.callableName, typeArgument.typeRef).apply {
typeParameters += typeParameter
valueParameters += tryType.toValueParameter(session, "tryBlock")
catchTypes.forEachIndexed { i, type ->
valueParameters += type.toValueParameter(session, "catchBlock_$i")
}
}
}
private fun generateWhenCallDeclaration(): FirMemberFunctionImpl {
val functionSymbol = FirSyntheticFunctionSymbol(SyntheticCallableId.WHEN, file)
val typeParameterSymbol = FirTypeParameterSymbol()
val typeParameter = FirTypeParameterImpl(session, null, typeParameterSymbol, Name.identifier("K"), Variance.INVARIANT, false)
val returnType = FirResolvedTypeRefImpl(null, ConeTypeParameterTypeImpl(typeParameterSymbol.toLookupTag(), false))
val branchType = FirResolvedTypeRefImpl(null, returnType.coneTypeUnsafe<ConeKotlinType>().createArrayOf(session))
val typeArgument = FirTypeProjectionWithVarianceImpl(null, Variance.INVARIANT, returnType)
return generateMemberFunction(session, functionSymbol, SyntheticCallableId.WHEN.callableName, typeArgument.typeRef).apply {
typeParameters += typeParameter
valueParameters += branchType.toValueParameter(session, "branches", true)
}
}
private fun generateCalleeReferenceWithCandidate(
function: FirMemberFunctionImpl,
arguments: List<FirExpression>,
@@ -136,6 +105,22 @@ class FirSyntheticCallGenerator(private val transformer: FirBodyResolveTransform
container = container
) { it.resultType }
private fun generateSyntheticSelectFunction(callableId: CallableId): FirMemberFunctionImpl {
val functionSymbol = FirSyntheticFunctionSymbol(callableId)
val typeParameterSymbol = FirTypeParameterSymbol()
val typeParameter = FirTypeParameterImpl(session, null, typeParameterSymbol, Name.identifier("K"), Variance.INVARIANT, false)
val returnType = FirResolvedTypeRefImpl(null, ConeTypeParameterTypeImpl(typeParameterSymbol.toLookupTag(), false))
val argumentType = FirResolvedTypeRefImpl(null, returnType.coneTypeUnsafe<ConeKotlinType>().createArrayOf(session))
val typeArgument = FirTypeProjectionWithVarianceImpl(null, Variance.INVARIANT, returnType)
return generateMemberFunction(session, functionSymbol, callableId.callableName, typeArgument.typeRef).apply {
typeParameters += typeParameter
valueParameters += argumentType.toValueParameter(session, "branches", isVararg = true)
}
}
private fun generateMemberFunction(session: FirSession, symbol: FirNamedFunctionSymbol, name: Name, returnType: FirTypeRef) =
FirMemberFunctionImpl(
session = session,
@@ -25,7 +25,6 @@ fun <D> AbstractFirBasedSymbol<D>.phasedFir(
if (availablePhase < requiredPhase) {
val provider = FirProvider.getInstance(session)
val containingFile = when (this) {
is FirSyntheticFunctionSymbol -> file
is ConeCallableSymbol -> provider.getFirCallableContainerFile(this)
is ConeClassLikeSymbol -> provider.getFirClassifierContainerFile(this)
else -> null