[FIR2IR] Simplify elvis conversion

This commit is contained in:
Mikhail Glukhikh
2020-07-01 12:23:31 +03:00
committed by Dmitriy Novozhilov
parent 68b84722c4
commit f46970219f
@@ -16,14 +16,11 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement import org.jetbrains.kotlin.fir.expressions.impl.FirStubStatement
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.isIteratorNext import org.jetbrains.kotlin.fir.resolve.isIteratorNext
import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.scope
@@ -556,72 +553,56 @@ class Fir2IrVisitor(
} }
override fun visitElvisCall(elvisCall: FirElvisCall, data: Any?): IrElement { override fun visitElvisCall(elvisCall: FirElvisCall, data: Any?): IrElement {
val subjectName = Name.special("<elvis>") val firLhsVariable = buildProperty {
val firSubjectVariable = buildProperty {
source = elvisCall.source source = elvisCall.source
session = this@Fir2IrVisitor.session session = this@Fir2IrVisitor.session
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
returnTypeRef = elvisCall.lhs.typeRef returnTypeRef = elvisCall.lhs.typeRef
name = subjectName name = Name.special("<elvis>")
initializer = elvisCall.lhs initializer = elvisCall.lhs
symbol = FirPropertySymbol(name) symbol = FirPropertySymbol(name)
isVar = false isVar = false
isLocal = true isLocal = true
status = FirDeclarationStatusImpl(Visibilities.LOCAL, Modality.FINAL) status = FirDeclarationStatusImpl(Visibilities.LOCAL, Modality.FINAL)
} }
val subjectVariable = firSubjectVariable.accept(this, null) as IrVariable val irLhsVariable = firLhsVariable.accept(this, null) as IrVariable
return conversionScope.withWhenSubject(subjectVariable) { return elvisCall.convertWithOffsets { startOffset, endOffset ->
elvisCall.convertWithOffsets { startOffset, endOffset -> fun irGetLhsValue(): IrGetValue =
IrGetValueImpl(startOffset, endOffset, irLhsVariable.type, irLhsVariable.symbol)
// TODO: replace with .coneType
val originalType = firLhsVariable.returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
val notNullType = originalType.withNullability(ConeNullability.NOT_NULL)
val irBranches = listOf( val irBranches = listOf(
IrBranchImpl( IrBranchImpl(
startOffset, endOffset, primitiveOp2( startOffset, endOffset, primitiveOp2(
startOffset, endOffset, irBuiltIns.eqeqSymbol, startOffset, endOffset, irBuiltIns.eqeqSymbol,
irBuiltIns.booleanType, IrStatementOrigin.EQEQ, irBuiltIns.booleanType, IrStatementOrigin.EQEQ,
IrGetValueImpl( irGetLhsValue(),
startOffset, endOffset, IrConstImpl.constNull(startOffset, endOffset, irBuiltIns.nothingNType)
subjectVariable.type,
subjectVariable.symbol
),
IrConstImpl(
startOffset, endOffset,
irBuiltIns.nothingNType,
IrConstKind.Null,
value = null
)
), ),
convertToIrExpression(elvisCall.rhs) convertToIrExpression(elvisCall.rhs)
), ),
buildWhenBranch { IrElseBranchImpl(
condition = buildElseIfTrueCondition {} IrConstImpl.boolean(startOffset, endOffset, irBuiltIns.booleanType, true),
var resultExpression = buildQualifiedAccessExpression { if (notNullType == originalType) {
calleeReference = buildResolvedNamedReference { irGetLhsValue()
name = subjectVariable.name } else {
resolvedSymbol = firSubjectVariable.symbol implicitCastOrExpression(
irGetLhsValue(),
firLhsVariable.returnTypeRef.resolvedTypeFromPrototype(notNullType).toIrType()
)
} }
typeRef = firSubjectVariable.returnTypeRef )
}
// TODO: replace with .coneType
val originalType = resultExpression.typeRef.coneTypeUnsafe<ConeKotlinType>()
val notNullType = originalType.withNullability(ConeNullability.NOT_NULL)
if (notNullType != originalType) {
resultExpression = buildExpressionWithSmartcast {
originalExpression = resultExpression
typeRef = resultExpression.typeRef.resolvedTypeFromPrototype(notNullType)
typesFromSmartCast = setOf(notNullType)
}
}
result = buildSingleExpressionBlock(resultExpression)
}.toIrWhenBranch()
) )
generateWhen( generateWhen(
startOffset, endOffset, IrStatementOrigin.ELVIS, startOffset, endOffset, IrStatementOrigin.ELVIS,
subjectVariable, irBranches, irLhsVariable, irBranches,
elvisCall.typeRef.toIrType() elvisCall.typeRef.toIrType()
) )
} }
} }
}
override fun visitWhenExpression(whenExpression: FirWhenExpression, data: Any?): IrElement { override fun visitWhenExpression(whenExpression: FirWhenExpression, data: Any?): IrElement {
val subjectVariable = generateWhenSubjectVariable(whenExpression) val subjectVariable = generateWhenSubjectVariable(whenExpression)