From 97593fa19e054600d0be65f7219776ea62930aab Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 22 Aug 2016 14:17:24 +0300 Subject: [PATCH] Make 'when' great again. --- .../psi2ir/generators/DeclarationGenerator.kt | 4 +- ...enerator.kt => ExpressionBodyGenerator.kt} | 2 +- .../psi2ir/generators/StatementGenerator.kt | 44 ++++++- .../generators/WhenExpressionGenerator.kt | 34 ++---- .../src/org/jetbrains/kotlin/ir/IrSlots.kt | 6 +- .../{IrIfThenElse.kt => IrWhen.kt} | 94 +++++++++++++-- .../jetbrains/kotlin/ir/util/DumpIrTree.kt | 10 +- .../kotlin/ir/util/RenderIrElement.kt | 4 +- .../kotlin/ir/visitors/IrElementVisitor.kt | 2 +- .../testData/ir/irText/booleanOperators.txt | 4 +- compiler/testData/ir/irText/elvis.txt | 4 +- compiler/testData/ir/irText/ifElseIf.txt | 15 ++- compiler/testData/ir/irText/smartCasts.txt | 6 +- .../ir/irText/smartCastsWithDestructuring.txt | 2 +- compiler/testData/ir/irText/when.txt | 114 ++++++++---------- 15 files changed, 213 insertions(+), 132 deletions(-) rename compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/{ExoressionBodyGenerator.kt => ExpressionBodyGenerator.kt} (97%) rename compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/{IrIfThenElse.kt => IrWhen.kt} (62%) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt index 715040b23e1..becfb115d50 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt @@ -123,9 +123,9 @@ class DeclarationGenerator(override val context: GeneratorContext) : IrGenerator private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody = IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset, - ExoressionBodyGenerator(scopeOwner, context).generateFunctionBody(ktBody)) + ExpressionBodyGenerator(scopeOwner, context).generateFunctionBody(ktBody)) private fun generateInitializerBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody = IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset, - ExoressionBodyGenerator(scopeOwner, context).generatePropertyInitializerBody(ktBody)) + ExpressionBodyGenerator(scopeOwner, context).generatePropertyInitializerBody(ktBody)) } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExoressionBodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExpressionBodyGenerator.kt similarity index 97% rename from compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExoressionBodyGenerator.kt rename to compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExpressionBodyGenerator.kt index 15cb53116c0..87d4e4ece78 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExoressionBodyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExpressionBodyGenerator.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset -class ExoressionBodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): IrBodyGenerator { +class ExpressionBodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): IrBodyGenerator { override val scope = Scope.rootScope(scopeOwner, this) fun generateFunctionBody(ktBody: KtExpression): IrExpression { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt index 8ec475d973e..07241c3fa85 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt @@ -39,11 +39,12 @@ import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils +import org.jetbrains.kotlin.utils.SmartList class StatementGenerator( override val context: GeneratorContext, val scopeOwner: DeclarationDescriptor, - val declarationBodyGenerator: ExoressionBodyGenerator, + val expressionBodyGenerator: ExpressionBodyGenerator, override val scope: Scope ) : KtVisitor(), IrBodyGenerator { fun generateExpression(ktExpression: KtExpression): IrExpression = @@ -264,11 +265,42 @@ class StatementGenerator( override fun visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement { val resultType = getInferredTypeWithSmartcasts(expression) - val irCondition = toExpectedType(expression.condition!!.genExpr(), context.builtIns.booleanType) - val irThenBranch = toExpectedType(expression.then!!.genExpr(), resultType) - val irElseBranch = toExpectedTypeOrNull(expression.`else`?.genExpr(), resultType) - return IrIfThenElseImpl(expression.startOffset, expression.endOffset, resultType, - irCondition, irThenBranch, irElseBranch, IrOperator.IF) + + var ktLastIf: KtIfExpression = expression + val irBranches = SmartList>() + var irElseBranch: IrExpression? = null + + whenBranches@while (true) { + val irCondition = generateExpressionWithExpectedType(expression.condition!!, context.builtIns.booleanType) + val irThenBranch = generateExpressionWithExpectedType(expression.then!!, resultType) + irBranches.add(Pair(irCondition, irThenBranch)) + + val ktElse = ktLastIf.`else`?.deparenthesize() + when (ktElse) { + null -> break@whenBranches + is KtIfExpression -> ktLastIf = ktElse + is KtExpression -> { + irElseBranch = generateExpressionWithExpectedType(ktElse, resultType) + break@whenBranches + } + else -> throw AssertionError("Unexpected else expression: ${ktElse.text}") + } + } + + return if (irBranches.size == 1) { + val (irCondition, irThenBranch) = irBranches[0] + IrIfThenElseImpl(expression.startOffset, expression.endOffset, resultType, + irCondition, irThenBranch, irElseBranch, IrOperator.IF) + } + else { + val irWhen = IrWhenImpl(expression.startOffset, expression.endOffset, resultType, IrOperator.WHEN) + for ((irCondition, irThenBranch) in irBranches) { + irWhen.addBranch(irCondition, irThenBranch) + } + irWhen.elseBranch = irElseBranch + irWhen + } + } override fun visitWhenExpression(expression: KtWhenExpression, data: Nothing?): IrStatement = diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt index f4a8dced6e7..e27534f5610 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt @@ -35,12 +35,11 @@ class WhenExpressionGenerator(statementGenerator: StatementGenerator) : IrChildB val resultType = getInferredTypeWithSmartcasts(expression) - val irBranches = ArrayList>(expression.entries.size) - var irElseExpression: IrExpression? = null + val irWhen = IrWhenImpl(expression.startOffset, expression.endOffset, resultType, IrOperator.WHEN) for (ktEntry in expression.entries) { if (ktEntry.isElse) { - irElseExpression = parentGenerator.generateExpressionWithExpectedType(ktEntry.expression!!, resultType) + irWhen.elseBranch = parentGenerator.generateExpressionWithExpectedType(ktEntry.expression!!, resultType) break } @@ -56,42 +55,29 @@ class WhenExpressionGenerator(statementGenerator: StatementGenerator) : IrChildB } val irBranchResult = parentGenerator.generateExpressionWithExpectedType(ktEntry.expression!!, resultType) - irBranches.add(Pair(irBranchCondition!!, irBranchResult)) + irWhen.addBranch(irBranchCondition!!, irBranchResult) } - if (irBranches.isEmpty()) return generateWhenBody(expression, irSubject) - - irBranches.reverse() - - val (irLastCondition, irLastResult) = irBranches[0] - var irTopBranch = IrIfThenElseImpl(irLastCondition.startOffset, irLastCondition.endOffset, resultType, - irLastCondition, irLastResult, irElseExpression, IrOperator.WHEN) - - for ((irBranchCondition, irBranchResult) in irBranches.subList(1, irBranches.size)) { - irTopBranch = IrIfThenElseImpl(irBranchCondition.startOffset, irBranchCondition.endOffset, resultType, - irBranchCondition, irBranchResult, irTopBranch, IrOperator.WHEN) - } - - return generateWhenBody(expression, irSubject, irTopBranch) + return generateWhenBody(expression, irSubject, irWhen) } - private fun generateWhenBody(expression: KtWhenExpression, irSubject: IrVariable?, irTopBranch: IrIfThenElse? = null): IrExpression { + private fun generateWhenBody(expression: KtWhenExpression, irSubject: IrVariable?, irWhen: IrWhen): IrExpression { if (irSubject == null) { - if (irTopBranch == null) + if (irWhen.branchesCount == 0) return IrBlockImpl(expression.startOffset, expression.endOffset, null, false, IrOperator.WHEN) else - return irTopBranch + return irWhen } else { - if (irTopBranch == null) { + if (irWhen.branchesCount == 0) { val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, null, false, IrOperator.WHEN) irBlock.addStatement(irSubject) return irBlock } else { - val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irTopBranch.type, true, IrOperator.WHEN) + val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irWhen.type, true, IrOperator.WHEN) irBlock.addStatement(irSubject) - irBlock.addStatement(irTopBranch) + irBlock.addStatement(irWhen) return irBlock } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrSlots.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrSlots.kt index 7cbaf69a161..7f248b69ed4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrSlots.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrSlots.kt @@ -25,9 +25,9 @@ const val EXTENSION_RECEIVER_SLOT = -2 const val FUNCTION_BODY_SLOT = 0 const val MODULE_SLOT = 0 const val INITIALIZER_SLOT = 0 -const val IF_CONDITION_SLOT = -1 -const val IF_THEN_SLOT = -2 -const val IF_ELSE_SLOT = -3 +const val IF_CONDITION_SLOT = 0 +const val IF_THEN_SLOT = 1 +const val IF_ELSE_SLOT = -1 const val LOOP_BODY_SLOT = -1 const val LOOP_CONDITION_SLOT = -2 const val SETTER_ARGUMENT_INDEX = 0 \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfThenElse.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrWhen.kt similarity index 62% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfThenElse.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrWhen.kt index ebd72d15e90..839e3c139e1 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfThenElse.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrWhen.kt @@ -23,19 +23,81 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.SmartList import java.util.* -interface IrIfThenElse : IrExpression { +interface IrWhen : IrExpression { val operator: IrOperator? - var condition: IrExpression - var thenBranch: IrExpression + val branchesCount: Int + fun getNthCondition(n: Int): IrExpression? + fun getNthResult(n: Int): IrExpression? var elseBranch: IrExpression? } +class IrWhenImpl( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + override val operator: IrOperator? = null +) : IrExpressionBase(startOffset, endOffset, type), IrWhen { + private val branchParts = ArrayList() + + fun addBranch(condition: IrExpression, result: IrExpression) { + condition.assertDetached() + result.assertDetached() + condition.setTreeLocation(this, branchParts.size) + branchParts.add(condition) + result.setTreeLocation(this, branchParts.size) + branchParts.add(result) + } + + override var elseBranch: IrExpression? = null + set(value) { + value?.assertDetached() + value?.detach() + field = value + value?.setTreeLocation(this, IF_ELSE_SLOT) + } + + override fun getChild(slot: Int): IrElement? { + return when (slot) { + IF_ELSE_SLOT -> elseBranch + else -> branchParts.getOrNull(slot) + } + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + IF_ELSE_SLOT -> elseBranch = newChild.assertCast() + in branchParts.indices -> { + newChild.assertDetached() + branchParts[slot].detach() + branchParts[slot] = newChild.assertCast() + newChild.setTreeLocation(this, slot) + } + } + } + + override val branchesCount: Int get() = branchParts.size / 2 + + override fun getNthCondition(n: Int): IrExpression? = + branchParts.getOrNull(n * 2) + + override fun getNthResult(n: Int): IrExpression? = + branchParts.getOrNull(n * 2 + 1) + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitWhen(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + branchParts.forEach { it.accept(visitor, data) } + elseBranch?.accept(visitor, data) + } +} + class IrIfThenElseImpl( startOffset: Int, endOffset: Int, type: KotlinType?, override val operator: IrOperator? = null -) : IrExpressionBase(startOffset, endOffset, type), IrIfThenElse { +) : IrExpressionBase(startOffset, endOffset, type), IrWhen { constructor( startOffset: Int, endOffset: Int, @@ -50,8 +112,16 @@ class IrIfThenElseImpl( this.elseBranch = elseBranch } + override val branchesCount: Int get() = 1 + + override fun getNthCondition(n: Int): IrExpression? = + if (n == 0) condition else null + + override fun getNthResult(n: Int): IrExpression? = + if (n == 0) thenBranch else null + private var conditionImpl: IrExpression? = null - override var condition: IrExpression + var condition: IrExpression get() = conditionImpl!! set(value) { value.assertDetached() @@ -61,7 +131,7 @@ class IrIfThenElseImpl( } private var thenBranchImpl: IrExpression? = null - override var thenBranch: IrExpression + var thenBranch: IrExpression get() = thenBranchImpl!! set(value) { value.assertDetached() @@ -99,7 +169,7 @@ class IrIfThenElseImpl( } override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitIf(this, data) + visitor.visitWhen(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { condition.accept(visitor, data) @@ -109,24 +179,24 @@ class IrIfThenElseImpl( companion object { // a || b == if (a) true else b - fun oror(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrIfThenElse = + fun oror(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrWhen = IrIfThenElseImpl(startOffset, endOffset, b.type!!, a, IrConstImpl.constTrue(b.startOffset, b.endOffset, b.type!!), b, operator) - fun oror(a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrIfThenElse = + fun oror(a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrWhen = oror(b.startOffset, b.endOffset, a, b, operator) - fun whenComma(a: IrExpression, b: IrExpression): IrIfThenElse = + fun whenComma(a: IrExpression, b: IrExpression): IrWhen = oror(a, b, IrOperator.WHEN_COMMA) // a && b == if (a) b else false - fun andand(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.ANDAND): IrIfThenElse = + fun andand(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.ANDAND): IrWhen = IrIfThenElseImpl(startOffset, endOffset, b.type!!, a, b, IrConstImpl.constFalse(b.startOffset, b.endOffset, b.type!!), operator) - fun andand(a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.ANDAND): IrIfThenElse = + fun andand(a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.ANDAND): IrWhen = andand(b.startOffset, b.endOffset, a, b, operator) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index 939ee8e0ef1..51020280908 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.SourceLocationManager import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrIfThenElse +import org.jetbrains.kotlin.ir.expressions.IrWhen import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.utils.Printer @@ -54,10 +54,12 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { } } - override fun visitIf(expression: IrIfThenElse, data: String) { + override fun visitWhen(expression: IrWhen, data: String) { expression.dumpLabeledElementWith(data) { - expression.condition.accept(this, "if") - expression.thenBranch.accept(this, "then") + for (i in 0 .. expression.branchesCount - 1) { + expression.getNthCondition(i)!!.accept(this, "if") + expression.getNthResult(i)!!.accept(this, "then") + } expression.elseBranch?.accept(this, "else") } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index 8f64d050eec..d7fe9953148 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -97,8 +97,8 @@ class RenderIrElementVisitor : IrElementVisitor { override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): String = "TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}" - override fun visitIf(expression: IrIfThenElse, data: Nothing?): String = - "IF type=${expression.type.render()} operator=${expression.operator}" + override fun visitWhen(expression: IrWhen, data: Nothing?): String = + "WHEN type=${expression.type.render()} operator=${expression.operator}" override fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: Nothing?): String = "DUMMY ${declaration.descriptor.name}" diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt index d288bf616d3..397e66fd19f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt @@ -56,7 +56,7 @@ interface IrElementVisitor { fun visitTypeOperator(expression: IrTypeOperatorCall, data: D) = visitExpression(expression, data) - fun visitIf(expression: IrIfThenElse, data: D) = visitExpression(expression, data) + fun visitWhen(expression: IrWhen, data: D) = visitExpression(expression, data) fun visitLoop(loop: IrLoop, data: D) = visitExpression(loop, data) fun visitWhileLoop(loop: IrWhileLoop, data: D) = visitLoop(loop, data) fun visitDoWhileLoop(loop: IrDoWhileLoop, data: D) = visitLoop(loop, data) diff --git a/compiler/testData/ir/irText/booleanOperators.txt b/compiler/testData/ir/irText/booleanOperators.txt index defcea5a186..76c6c931650 100644 --- a/compiler/testData/ir/irText/booleanOperators.txt +++ b/compiler/testData/ir/irText/booleanOperators.txt @@ -3,7 +3,7 @@ IrFile /booleanOperators.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - IF type=kotlin.Boolean operator=ANDAND + WHEN type=kotlin.Boolean operator=ANDAND if: GET_VAR a type=kotlin.Boolean operator=null then: GET_VAR b type=kotlin.Boolean operator=null else: LITERAL Boolean type=kotlin.Boolean value='false' @@ -11,7 +11,7 @@ IrFile /booleanOperators.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - IF type=kotlin.Boolean operator=OROR + WHEN type=kotlin.Boolean operator=OROR if: GET_VAR a type=kotlin.Boolean operator=null then: LITERAL Boolean type=kotlin.Boolean value='true' else: GET_VAR b type=kotlin.Boolean operator=null diff --git a/compiler/testData/ir/irText/elvis.txt b/compiler/testData/ir/irText/elvis.txt index 66e8abecfd2..82e26336210 100644 --- a/compiler/testData/ir/irText/elvis.txt +++ b/compiler/testData/ir/irText/elvis.txt @@ -12,12 +12,12 @@ IrFile /elvis.kt IrFunction public fun test3(/*0*/ a: kotlin.Any?, /*1*/ b: kotlin.Any?): kotlin.String IrExpressionBody BLOCK type= hasResult=false operator=null - IF type=kotlin.Unit operator=IF + WHEN type=kotlin.Unit operator=IF if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String GET_VAR b type=kotlin.Any? operator=null then: RETURN type= LITERAL String type=kotlin.String value='' - IF type=kotlin.Unit operator=IF + WHEN type=kotlin.Unit operator=IF if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String? GET_VAR a type=kotlin.Any? operator=null then: RETURN type= diff --git a/compiler/testData/ir/irText/ifElseIf.txt b/compiler/testData/ir/irText/ifElseIf.txt index 048fa926ff8..96275adff19 100644 --- a/compiler/testData/ir/irText/ifElseIf.txt +++ b/compiler/testData/ir/irText/ifElseIf.txt @@ -3,16 +3,15 @@ IrFile /ifElseIf.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - IF type=kotlin.Int operator=IF + WHEN type=kotlin.Int operator=WHEN if: CALL .GT0 type=kotlin.Boolean operator=GT arg0: CALL .compareTo type=kotlin.Int operator=GT $this: GET_VAR i type=kotlin.Int operator=null other: LITERAL Int type=kotlin.Int value='0' then: LITERAL Int type=kotlin.Int value='1' - else: IF type=kotlin.Int operator=IF - if: CALL .LT0 type=kotlin.Boolean operator=LT - arg0: CALL .compareTo type=kotlin.Int operator=LT - $this: GET_VAR i type=kotlin.Int operator=null - other: LITERAL Int type=kotlin.Int value='0' - then: DUMMY MINUS type=kotlin.Int - else: LITERAL Int type=kotlin.Int value='0' + if: CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR i type=kotlin.Int operator=null + other: LITERAL Int type=kotlin.Int value='0' + then: LITERAL Int type=kotlin.Int value='1' + else: LITERAL Int type=kotlin.Int value='0' diff --git a/compiler/testData/ir/irText/smartCasts.txt b/compiler/testData/ir/irText/smartCasts.txt index 5581a85caba..ef96aa06466 100644 --- a/compiler/testData/ir/irText/smartCasts.txt +++ b/compiler/testData/ir/irText/smartCasts.txt @@ -18,7 +18,7 @@ IrFile /smartCasts.kt IrFunction public fun test1(/*0*/ x: kotlin.Any): kotlin.Unit IrExpressionBody BLOCK type= hasResult=false operator=null - IF type=kotlin.Unit operator=IF + WHEN type=kotlin.Unit operator=IF if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String GET_VAR x type=kotlin.Any operator=null then: RETURN type= @@ -40,7 +40,7 @@ IrFile /smartCasts.kt IrFunction public fun test2(/*0*/ x: kotlin.Any): kotlin.String IrExpressionBody BLOCK type= hasResult=false operator=null - IF type=kotlin.Unit operator=IF + WHEN type=kotlin.Unit operator=IF if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String GET_VAR x type=kotlin.Any operator=null then: RETURN type= @@ -52,7 +52,7 @@ IrFile /smartCasts.kt IrFunction public fun test3(/*0*/ x: kotlin.Any): kotlin.String IrExpressionBody BLOCK type= hasResult=false operator=null - IF type=kotlin.Unit operator=IF + WHEN type=kotlin.Unit operator=IF if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=kotlin.String GET_VAR x type=kotlin.Any operator=null then: RETURN type= diff --git a/compiler/testData/ir/irText/smartCastsWithDestructuring.txt b/compiler/testData/ir/irText/smartCastsWithDestructuring.txt index 1aa625fa894..d5ad9930b2d 100644 --- a/compiler/testData/ir/irText/smartCastsWithDestructuring.txt +++ b/compiler/testData/ir/irText/smartCastsWithDestructuring.txt @@ -14,7 +14,7 @@ IrFile /smartCastsWithDestructuring.kt IrFunction public fun test(/*0*/ x: I1): kotlin.Unit IrExpressionBody BLOCK type= hasResult=false operator=null - IF type=kotlin.Unit operator=IF + WHEN type=kotlin.Unit operator=IF if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=I2 GET_VAR x type=I1 operator=null then: RETURN type= diff --git a/compiler/testData/ir/irText/when.txt b/compiler/testData/ir/irText/when.txt index 5c78ed8436a..a824c5f84e3 100644 --- a/compiler/testData/ir/irText/when.txt +++ b/compiler/testData/ir/irText/when.txt @@ -7,52 +7,46 @@ IrFile /when.kt BLOCK type=kotlin.String hasResult=true operator=WHEN VAR val tmp0_subject: kotlin.Any? GET_VAR x type=kotlin.Any? operator=null - IF type=kotlin.String operator=WHEN + WHEN type=kotlin.String operator=WHEN if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ arg0: GET_VAR tmp0_subject type=kotlin.Any? operator=null arg1: LITERAL Null type=kotlin.Nothing? value='null' then: LITERAL String type=kotlin.String value='null' - else: IF type=kotlin.String operator=WHEN - if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ - arg0: GET_VAR tmp0_subject type=kotlin.Any? operator=null - arg1: GET_OBJECT A type=A - then: LITERAL String type=kotlin.String value='A' - else: IF type=kotlin.String operator=WHEN - if: TYPE_OP operator=INSTANCEOF typeOperand=kotlin.String - GET_VAR tmp0_subject type=kotlin.Any? operator=null - then: LITERAL String type=kotlin.String value='String' - else: IF type=kotlin.String operator=WHEN - if: CALL .contains type=kotlin.Boolean operator=IN - $receiver: CALL .setOf type=kotlin.collections.Set operator=null - element: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Any - GET_VAR tmp0_subject type=kotlin.Any? operator=null - then: LITERAL String type=kotlin.String value='nothingness?' - else: LITERAL String type=kotlin.String value='something' + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Any? operator=null + arg1: GET_OBJECT A type=A + then: LITERAL String type=kotlin.String value='A' + if: TYPE_OP operator=INSTANCEOF typeOperand=kotlin.String + GET_VAR tmp0_subject type=kotlin.Any? operator=null + then: LITERAL String type=kotlin.String value='String' + if: CALL .contains type=kotlin.Boolean operator=IN + $receiver: CALL .setOf type=kotlin.collections.Set operator=null + element: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Any + GET_VAR tmp0_subject type=kotlin.Any? operator=null + then: LITERAL String type=kotlin.String value='nothingness?' + else: LITERAL String type=kotlin.String value='something' IrFunction public fun test(/*0*/ x: kotlin.Any?): kotlin.String IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - IF type=kotlin.String operator=WHEN + WHEN type=kotlin.String operator=WHEN if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ arg0: GET_VAR x type=kotlin.Any? operator=null arg1: LITERAL Null type=kotlin.Nothing? value='null' then: LITERAL String type=kotlin.String value='null' - else: IF type=kotlin.String operator=WHEN - if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ - arg0: GET_VAR x type=kotlin.Any? operator=null - arg1: GET_OBJECT A type=A - then: LITERAL String type=kotlin.String value='A' - else: IF type=kotlin.String operator=WHEN - if: TYPE_OP operator=INSTANCEOF typeOperand=kotlin.String - GET_VAR x type=kotlin.Any? operator=null - then: LITERAL String type=kotlin.String value='String' - else: IF type=kotlin.String operator=WHEN - if: CALL .contains type=kotlin.Boolean operator=IN - $receiver: CALL .setOf type=kotlin.collections.Set operator=null - element: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Any - GET_VAR x type=kotlin.Any? operator=null - then: LITERAL String type=kotlin.String value='nothingness?' - else: LITERAL String type=kotlin.String value='something' + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR x type=kotlin.Any? operator=null + arg1: GET_OBJECT A type=A + then: LITERAL String type=kotlin.String value='A' + if: TYPE_OP operator=INSTANCEOF typeOperand=kotlin.String + GET_VAR x type=kotlin.Any? operator=null + then: LITERAL String type=kotlin.String value='String' + if: CALL .contains type=kotlin.Boolean operator=IN + $receiver: CALL .setOf type=kotlin.collections.Set operator=null + element: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Any + GET_VAR x type=kotlin.Any? operator=null + then: LITERAL String type=kotlin.String value='nothingness?' + else: LITERAL String type=kotlin.String value='something' IrFunction public fun testComma(/*0*/ x: kotlin.Int): kotlin.String IrExpressionBody BLOCK type= hasResult=false operator=null @@ -60,10 +54,10 @@ IrFile /when.kt BLOCK type=kotlin.String hasResult=true operator=WHEN VAR val tmp0_subject: kotlin.Int GET_VAR x type=kotlin.Int operator=null - IF type=kotlin.String operator=WHEN - if: IF type=kotlin.Boolean operator=WHEN_COMMA - if: IF type=kotlin.Boolean operator=WHEN_COMMA - if: IF type=kotlin.Boolean operator=WHEN_COMMA + WHEN type=kotlin.String operator=WHEN + if: WHEN type=kotlin.Boolean operator=WHEN_COMMA + if: WHEN type=kotlin.Boolean operator=WHEN_COMMA + if: WHEN type=kotlin.Boolean operator=WHEN_COMMA if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null arg1: LITERAL Int type=kotlin.Int value='1' @@ -80,29 +74,27 @@ IrFile /when.kt arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null arg1: LITERAL Int type=kotlin.Int value='4' then: LITERAL String type=kotlin.String value='1234' - else: IF type=kotlin.String operator=WHEN - if: IF type=kotlin.Boolean operator=WHEN_COMMA - if: IF type=kotlin.Boolean operator=WHEN_COMMA - if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ - arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null - arg1: LITERAL Int type=kotlin.Int value='5' - then: LITERAL Boolean type=kotlin.Boolean value='true' - else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ - arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null - arg1: LITERAL Int type=kotlin.Int value='6' + if: WHEN type=kotlin.Boolean operator=WHEN_COMMA + if: WHEN type=kotlin.Boolean operator=WHEN_COMMA + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='5' then: LITERAL Boolean type=kotlin.Boolean value='true' else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null - arg1: LITERAL Int type=kotlin.Int value='7' - then: LITERAL String type=kotlin.String value='567' - else: IF type=kotlin.String operator=WHEN - if: IF type=kotlin.Boolean operator=WHEN_COMMA - if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ - arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null - arg1: LITERAL Int type=kotlin.Int value='8' - then: LITERAL Boolean type=kotlin.Boolean value='true' - else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ - arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null - arg1: LITERAL Int type=kotlin.Int value='9' - then: LITERAL String type=kotlin.String value='89' - else: LITERAL String type=kotlin.String value='?' + arg1: LITERAL Int type=kotlin.Int value='6' + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='7' + then: LITERAL String type=kotlin.String value='567' + if: WHEN type=kotlin.Boolean operator=WHEN_COMMA + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='8' + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='9' + then: LITERAL String type=kotlin.String value='89' + else: LITERAL String type=kotlin.String value='?'