'?:' (currently represented as binary expression with operator ELVIS)
This commit is contained in:
committed by
Dmitry Petrov
parent
0d94c3aeb4
commit
8de21aadfa
+9
-1
@@ -54,7 +54,12 @@ internal val KT_TOKEN_TO_IR_OPERATOR =
|
||||
KtTokens.EXCLEQEQEQ to IrOperator.EXCLEQEQ,
|
||||
|
||||
KtTokens.IN_KEYWORD to IrOperator.IN,
|
||||
KtTokens.NOT_IN to IrOperator.NOT_IN
|
||||
KtTokens.NOT_IN to IrOperator.NOT_IN,
|
||||
|
||||
KtTokens.ANDAND to IrOperator.ANDAND,
|
||||
KtTokens.OROR to IrOperator.OROR,
|
||||
|
||||
KtTokens.ELVIS to IrOperator.ELVIS
|
||||
)
|
||||
|
||||
internal val AUGMENTED_ASSIGNMENTS =
|
||||
@@ -74,3 +79,6 @@ internal val IDENTITY_OPERATORS =
|
||||
|
||||
internal val IN_OPERATORS =
|
||||
setOf(IrOperator.IN, IrOperator.NOT_IN)
|
||||
|
||||
internal val BINARY_BOOLEAN_OPERATORS =
|
||||
setOf(IrOperator.ANDAND, IrOperator.OROR)
|
||||
+23
@@ -44,16 +44,39 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
return when (irOperator) {
|
||||
null -> createDummyExpression(expression, ktOperator.toString())
|
||||
IrOperator.EQ -> generateAssignment(expression)
|
||||
IrOperator.ELVIS -> generateElvis(expression)
|
||||
in AUGMENTED_ASSIGNMENTS -> generateAugmentedAssignment(expression, irOperator)
|
||||
in BINARY_OPERATORS_DESUGARED_TO_CALLS -> generateBinaryOperatorWithConventionalCall(expression, irOperator)
|
||||
in COMPARISON_OPERATORS -> generateComparisonOperator(expression, irOperator)
|
||||
in EQUALITY_OPERATORS -> generateEqualityOperator(expression, irOperator)
|
||||
in IDENTITY_OPERATORS -> generateIdentityOperator(expression, irOperator)
|
||||
in IN_OPERATORS -> generateInOperator(expression, irOperator)
|
||||
in BINARY_BOOLEAN_OPERATORS -> generateBinaryBooleanOperator(expression, irOperator)
|
||||
else -> createDummyExpression(expression, ktOperator.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateElvis(expression: KtBinaryExpression): IrExpression {
|
||||
// TODO desugar '?:' to 'if'?
|
||||
val specialCallForElvis = getResolvedCall(expression)!!
|
||||
val returnType = specialCallForElvis.resultingDescriptor.returnType!!
|
||||
val irArgument0 = irStatementGenerator.generateExpression(expression.left!!).toExpectedType(returnType.makeNullable())
|
||||
val irArgument1 = irStatementGenerator.generateExpression(expression.right!!).toExpectedType(returnType)
|
||||
return IrBinaryOperatorExpressionImpl(
|
||||
expression.startOffset, expression.endOffset, returnType,
|
||||
IrOperator.ELVIS, null, irArgument0, irArgument1
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateBinaryBooleanOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression {
|
||||
val irArgument0 = irStatementGenerator.generateExpression(expression.left!!).toExpectedType(context.builtIns.booleanType)
|
||||
val irArgument1 = irStatementGenerator.generateExpression(expression.right!!).toExpectedType(context.builtIns.booleanType)
|
||||
return IrBinaryOperatorExpressionImpl(
|
||||
expression.startOffset, expression.endOffset, context.builtIns.booleanType,
|
||||
irOperator, null, irArgument0, irArgument1
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateInOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression {
|
||||
val operatorCall = getResolvedCall(expression)!!
|
||||
|
||||
|
||||
+4
-2
@@ -102,10 +102,12 @@ class IrStatementGenerator(
|
||||
|
||||
override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrStatement {
|
||||
val returnTarget = getReturnExpressionTarget(expression)
|
||||
val irReturnedExpression = expression.returnedExpression?.let {
|
||||
it.genExpr().toExpectedType(returnTarget.returnType)
|
||||
}
|
||||
return IrReturnExpressionImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
returnTarget,
|
||||
expression.returnedExpression?.let { it.genExpr().toExpectedType(returnTarget.returnType) }
|
||||
returnTarget, irReturnedExpression
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
fun test1(a: Any?, b: Any) = a ?: b
|
||||
fun test2(a: String?, b: Any) = a ?: b
|
||||
|
||||
fun test3(a: Any?, b: Any?): String {
|
||||
if (b !is String) return ""
|
||||
if (a !is String?) return ""
|
||||
return a ?: b
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
IrFile /elvis.kt
|
||||
IrFunction public fun test1(/*0*/ a: kotlin.Any?, /*1*/ b: kotlin.Any): kotlin.Any
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
BINARY_OP operator=ELVIS type=kotlin.Any related=null
|
||||
GET_VAR a type=kotlin.Any?
|
||||
GET_VAR b type=kotlin.Any
|
||||
IrFunction public fun test2(/*0*/ a: kotlin.String?, /*1*/ b: kotlin.Any): kotlin.Any
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
BINARY_OP operator=ELVIS type=kotlin.Any related=null
|
||||
GET_VAR a type=kotlin.String?
|
||||
GET_VAR b type=kotlin.Any
|
||||
IrFunction public fun test3(/*0*/ a: kotlin.Any?, /*1*/ b: kotlin.Any?): kotlin.String
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=false
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
RETURN type=<no-type>
|
||||
BINARY_OP operator=ELVIS type=kotlin.String related=null
|
||||
TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String?
|
||||
GET_VAR a type=kotlin.Any?
|
||||
TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||
GET_VAR b type=kotlin.Any?
|
||||
@@ -107,6 +107,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("elvis.kt")
|
||||
public void testElvis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/elvis.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("equality.kt")
|
||||
public void testEquality() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/equality.kt");
|
||||
|
||||
Reference in New Issue
Block a user