From c0d521266b239a8aeaacdcf360dddf47099feecd Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 22 Aug 2016 09:59:42 +0300 Subject: [PATCH] Use ternary 'if' for 'when' (and also '||' as ',' in 'when'). --- .../generators/OperatorExpressionGenerator.kt | 2 +- .../psi2ir/generators/StatementGenerator.kt | 38 +--- .../generators/WhenExpressionGenerator.kt | 56 +++++- .../psi2ir/generators/values/IndexedLValue.kt | 2 +- .../values/RematerializableValue.kt | 8 +- .../src/org/jetbrains/kotlin/ir/IrSlots.kt | 6 +- .../kotlin/ir/declarations/IrFile.kt | 4 +- .../kotlin/ir/declarations/IrModule.kt | 4 +- .../ir/expressions/IrBlockExpression.kt | 5 +- ...eralExpression.kt => IrConstExpression.kt} | 33 ++-- .../kotlin/ir/expressions/IrIfExpression.kt | 126 +++++++++++++ .../kotlin/ir/expressions/IrOperator.kt | 5 + .../kotlin/ir/expressions/IrWhenExpression.kt | 174 ------------------ .../jetbrains/kotlin/ir/util/DumpIrTree.kt | 15 +- .../kotlin/ir/util/RenderIrElement.kt | 9 +- .../kotlin/ir/visitors/IrElementVisitor.kt | 7 +- compiler/testData/ir/irText/elvis.txt | 4 +- compiler/testData/ir/irText/ifElseIf.txt | 13 +- compiler/testData/ir/irText/smartCasts.txt | 6 +- .../ir/irText/smartCastsWithDestructuring.txt | 2 +- compiler/testData/ir/irText/when.kt | 8 + compiler/testData/ir/irText/when.txt | 122 ++++++++---- 22 files changed, 343 insertions(+), 306 deletions(-) rename compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/{IrLiteralExpression.kt => IrConstExpression.kt} (57%) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfExpression.kt delete mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrWhenExpression.kt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index f225111076a..5ee1dda9124 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -189,7 +189,7 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I IrBinaryOperatorExpressionImpl( expression.startOffset, expression.endOffset, context.builtIns.booleanType, irOperator, null, irCompareToCall, - IrLiteralExpressionImpl.int(expression.startOffset, expression.endOffset, context.builtIns.intType, 0) + IrConstExpressionImpl.int(expression.startOffset, expression.endOffset, context.builtIns.intType, 0) ) } } 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 982a16b3cb2..84c15330617 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 @@ -141,11 +141,11 @@ class StatementGenerator( return when (constantValue) { is StringValue -> - IrLiteralExpressionImpl.string(expression.startOffset, expression.endOffset, constantType, constantValue.value) + IrConstExpressionImpl.string(expression.startOffset, expression.endOffset, constantType, constantValue.value) is IntValue -> - IrLiteralExpressionImpl.int(expression.startOffset, expression.endOffset, constantType, constantValue.value) + IrConstExpressionImpl.int(expression.startOffset, expression.endOffset, constantType, constantValue.value) is NullValue -> - IrLiteralExpressionImpl.nullLiteral(expression.startOffset, expression.endOffset, constantType) + IrConstExpressionImpl.constNull(expression.startOffset, expression.endOffset, constantType) else -> TODO("handle other literal types: ${constantValue.type}") } @@ -160,7 +160,7 @@ class StatementGenerator( return entry0.genExpr() } } - entries.size == 0 -> return IrLiteralExpressionImpl.string(expression.startOffset, expression.endOffset, getInferredTypeWithSmarcastsOrFail(expression), "") + entries.size == 0 -> return IrConstExpressionImpl.string(expression.startOffset, expression.endOffset, getInferredTypeWithSmarcastsOrFail(expression), "") } val irStringTemplate = IrStringConcatenationExpressionImpl(expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression)) @@ -169,7 +169,7 @@ class StatementGenerator( } override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrStatement = - IrLiteralExpressionImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text) + IrConstExpressionImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text) override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): IrExpression { val resolvedCall = getResolvedCall(expression)!! @@ -266,29 +266,11 @@ class StatementGenerator( override fun visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement { val resultType = getInferredTypeWithSmartcasts(expression) - val irWhen = IrWhenExpressionImpl(expression.startOffset, expression.endOffset, resultType) - - var ktBranch: KtIfExpression? = expression - branches@while (ktBranch != null) { - val irBranch = IrBranchImpl(ktBranch.startOffset, ktBranch.endOffset, - ktBranch.condition!!.genExpr().toExpectedType(context.builtIns.booleanType), - ktBranch.then!!.genExpr().toExpectedType(resultType)) - irWhen.addBranch(irBranch) - - val ktElse = ktBranch.`else` - - ktBranch = when (ktElse) { - is KtIfExpression -> ktElse - null -> - break@branches - else -> { - irWhen.elseExpression = ktElse.genExpr().toExpectedType(resultType) - break@branches - } - } - } - - return irWhen + val irCondition = expression.condition!!.genExpr().toExpectedType(context.builtIns.booleanType) + val irThenBranch = expression.then!!.genExpr().toExpectedType(resultType) + val irElseBranch = expression.`else`?.let { it.genExpr().toExpectedType(resultType) } + return IrIfExpressionImpl(expression.startOffset, expression.endOffset, resultType, + irCondition, irThenBranch, irElseBranch, IrOperator.IF) } 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 e07131f6427..85f808afc10 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 @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.load import org.jetbrains.kotlin.psi2ir.toExpectedType import org.jetbrains.kotlin.resolve.BindingContext +import java.util.* class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGenerator { override val context: GeneratorContext get() = statementGenerator.context @@ -37,31 +38,66 @@ class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGe val resultType = getInferredTypeWithSmartcasts(expression) - val irWhen = IrWhenExpressionImpl(expression.startOffset, expression.endOffset, resultType, irSubject) + val irBranches = ArrayList>(expression.entries.size) + var irElseExpression: IrExpression? = null for (ktEntry in expression.entries) { if (ktEntry.isElse) { - irWhen.elseExpression = statementGenerator.generateExpression(ktEntry.expression!!).toExpectedType(resultType) - continue + irElseExpression = statementGenerator.generateExpression(ktEntry.expression!!).toExpectedType(resultType) + break } - val irBranch = IrBranchImpl(ktEntry.startOffset, ktEntry.endOffset) - + var irBranchCondition: IrExpression? = null for (ktCondition in ktEntry.conditions) { val irCondition = if (irSubject != null) generateWhenConditionWithSubject(ktCondition, conditionsGenerator, irSubject) else generateWhenConditionNoSubject(ktCondition) - irBranch.addCondition(irCondition) + irBranchCondition = irBranchCondition?.let { IrIfExpressionImpl.whenComma(it, irCondition) } ?: irCondition + } - irBranch.result = statementGenerator.generateExpression(ktEntry.expression!!).toExpectedType(resultType) - - irWhen.addBranch(irBranch) + val irBranchResult = statementGenerator.generateExpression(ktEntry.expression!!).toExpectedType(resultType) + irBranches.add(Pair(irBranchCondition!!, irBranchResult)) } - return irWhen + if (irBranches.isEmpty()) return generateWhenBody(expression, irSubject) + + irBranches.reverse() + + val (irLastCondition, irLastResult) = irBranches[0] + var irTopBranch = IrIfExpressionImpl(irLastCondition.startOffset, irLastCondition.endOffset, resultType, + irLastCondition, irLastResult, irElseExpression, IrOperator.WHEN) + + for ((irBranchCondition, irBranchResult) in irBranches.subList(1, irBranches.size)) { + irTopBranch = IrIfExpressionImpl(irBranchCondition.startOffset, irBranchCondition.endOffset, resultType, + irBranchCondition, irBranchResult, irTopBranch, IrOperator.WHEN) + } + + return generateWhenBody(expression, irSubject, irTopBranch) + } + + private fun generateWhenBody(expression: KtWhenExpression, irSubject: IrVariable?, irTopBranch: IrIfExpression? = null): IrExpression { + if (irSubject == null) { + if (irTopBranch == null) + return IrBlockExpressionImpl(expression.startOffset, expression.endOffset, null, false, IrOperator.WHEN) + else + return irTopBranch + } + else { + if (irTopBranch == null) { + val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, null, false, IrOperator.WHEN) + irBlock.addStatement(irSubject) + return irBlock + } + else { + val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, irTopBranch.type, true, IrOperator.WHEN) + irBlock.addStatement(irSubject) + irBlock.addStatement(irTopBranch) + return irBlock + } + } } private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression = diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/IndexedLValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/IndexedLValue.kt index 54ceab45324..2e10027da93 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/IndexedLValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/IndexedLValue.kt @@ -124,7 +124,7 @@ class IndexedLValue( hasResult, operator) } - private fun defineTemporaryVariables(irBlock: IrBlockExpression, callGenerator: CallGenerator) { + private fun defineTemporaryVariables(irBlock: IrBlockExpressionImpl, callGenerator: CallGenerator) { irBlock.addIfNotNull(callGenerator.introduceTemporary(ktArrayAccessExpression.arrayExpression!!, irArray, "array")) var index = 0 diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/RematerializableValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/RematerializableValue.kt index a4ccb044279..2f4ad887611 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/RematerializableValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/RematerializableValue.kt @@ -28,17 +28,17 @@ interface IrRematerializableValue : IrValue { fun createRematerializableValue(irExpression: IrExpression): IrRematerializableValue? = when (irExpression) { - is IrLiteralExpression<*> -> IrRematerializableLiteralValue(irExpression) + is IrConstExpression<*> -> IrRematerializableLiteralValue(irExpression) is IrGetVariableExpression -> IrRematerializableVariableValue(irExpression) is IrGetExtensionReceiverExpression -> IrRematerializableExtensionReceiverValue(irExpression) is IrThisExpression -> IrRematerializableThisValue(irExpression) else -> null } -class IrRematerializableLiteralValue(override val irExpression: IrLiteralExpression<*>): IrRematerializableValue { +class IrRematerializableLiteralValue(override val irExpression: IrConstExpression<*>): IrRematerializableValue { override fun load(): IrExpression = - IrLiteralExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, - irExpression.kind, irExpression.kind.valueOf(irExpression)) + IrConstExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, + irExpression.kind, irExpression.kind.valueOf(irExpression)) } class IrRematerializableVariableValue(override val irExpression: IrGetVariableExpression) : IrRematerializableValue { 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 a40bc2a0536..7cbaf69a161 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 WHEN_SUBJECT_VARIABLE_SLOT = -1 -const val WHEN_ELSE_EXPRESSION_SLOT = -2 -const val BRANCH_RESULT_SLOT = -1 +const val IF_CONDITION_SLOT = -1 +const val IF_THEN_SLOT = -2 +const val IF_ELSE_SLOT = -3 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/declarations/IrFile.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFile.kt index 26f4819c4cc..c16ca2d2dad 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFile.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFile.kt @@ -26,8 +26,6 @@ interface IrFile : IrElement { val fileEntry: SourceLocationManager.FileEntry val packageFragmentDescriptor: PackageFragmentDescriptor val declarations: List - - fun addDeclaration(declaration: IrDeclaration) } class IrFileImpl( @@ -37,7 +35,7 @@ class IrFileImpl( ) : IrElementBase(0, fileEntry.maxOffset), IrFile { override val declarations: MutableList = ArrayList() - override fun addDeclaration(declaration: IrDeclaration) { + fun addDeclaration(declaration: IrDeclaration) { declaration.assertDetached() declaration.setTreeLocation(this, declarations.size) declarations.add(declaration) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrModule.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrModule.kt index f900b7d723e..0095a158f95 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrModule.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrModule.kt @@ -35,8 +35,6 @@ interface IrModule : IrElement { val descriptor: ModuleDescriptor val irBuiltins: IrBuiltIns val files: List - - fun addFile(file: IrFile) } class IrModuleImpl( @@ -45,7 +43,7 @@ class IrModuleImpl( ) : IrModule { override val files: MutableList = ArrayList() - override fun addFile(file: IrFile) { + fun addFile(file: IrFile) { file.assertDetached() file.setTreeLocation(this, files.size) files.add(file) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt index 89e6541bf78..331ff1197e5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt @@ -27,10 +27,9 @@ interface IrBlockExpression : IrExpression { val operator: IrOperator? val statements: List - fun addStatement(statement: IrStatement) } -fun IrBlockExpression.addIfNotNull(statement: IrStatement?) { +fun IrBlockExpressionImpl.addIfNotNull(statement: IrStatement?) { if (statement != null) addStatement(statement) } @@ -43,7 +42,7 @@ class IrBlockExpressionImpl( ) : IrExpressionBase(startOffset, endOffset, type), IrBlockExpression { override val statements: MutableList = ArrayList() - override fun addStatement(statement: IrStatement) { + fun addStatement(statement: IrStatement) { statement.assertDetached() statement.setTreeLocation(this, statements.size) statements.add(statement) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLiteralExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstExpression.kt similarity index 57% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLiteralExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstExpression.kt index 4a0ef0efe8c..f61e4c561b4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLiteralExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstExpression.kt @@ -19,15 +19,15 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrLiteralExpression : IrExpression { +interface IrConstExpression : IrExpression { val kind: IrLiteralKind val value: T } sealed class IrLiteralKind(val asString: kotlin.String) { @Suppress("UNCHECKED_CAST") - fun valueOf(literal: IrLiteralExpression<*>) = - (literal as IrLiteralExpression).value + fun valueOf(aConst: IrConstExpression<*>) = + (aConst as IrConstExpression).value object Null : IrLiteralKind("Null") object Boolean : IrLiteralKind("Boolean") @@ -42,25 +42,34 @@ sealed class IrLiteralKind(val asString: kotlin.String) { override fun toString() = asString } -class IrLiteralExpressionImpl ( +class IrConstExpressionImpl ( startOffset: Int, endOffset: Int, type: KotlinType?, override val kind: IrLiteralKind, override val value: T -) : IrTerminalExpressionBase(startOffset, endOffset, type), IrLiteralExpression { +) : IrTerminalExpressionBase(startOffset, endOffset, type), IrConstExpression { override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitLiteral(this, data) + visitor.visitConst(this, data) companion object { - fun string(startOffset: Int, endOffset: Int, type: KotlinType, value: String): IrLiteralExpressionImpl = - IrLiteralExpressionImpl(startOffset, endOffset, type, IrLiteralKind.String, value) + fun string(startOffset: Int, endOffset: Int, type: KotlinType, value: String): IrConstExpressionImpl = + IrConstExpressionImpl(startOffset, endOffset, type, IrLiteralKind.String, value) - fun int(startOffset: Int, endOffset: Int, type: KotlinType, value: Int): IrLiteralExpressionImpl = - IrLiteralExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Int, value) + fun int(startOffset: Int, endOffset: Int, type: KotlinType, value: Int): IrConstExpressionImpl = + IrConstExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Int, value) - fun nullLiteral(startOffset: Int, endOffset: Int, type: KotlinType): IrLiteralExpressionImpl = - IrLiteralExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Null, null) + fun constNull(startOffset: Int, endOffset: Int, type: KotlinType): IrConstExpressionImpl = + IrConstExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Null, null) + + fun boolean(startOffset: Int, endOffset: Int, type: KotlinType, value: Boolean): IrConstExpressionImpl = + IrConstExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Boolean, value) + + fun constTrue(startOffset: Int, endOffset: Int, type: KotlinType): IrConstExpressionImpl = + boolean(startOffset, endOffset, type, true) + + fun constFalse(startOffset: Int, endOffset: Int, type: KotlinType): IrConstExpressionImpl = + boolean(startOffset, endOffset, type, false) } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfExpression.kt new file mode 100644 index 00000000000..b4efe9d40ec --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfExpression.kt @@ -0,0 +1,126 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir.expressions + +import org.jetbrains.kotlin.ir.* +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.SmartList +import java.util.* + +interface IrIfExpression : IrExpression { + val operator: IrOperator? + var condition: IrExpression + var thenBranch: IrExpression + var elseBranch: IrExpression? +} + +class IrIfExpressionImpl( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + override val operator: IrOperator? = null +) : IrExpressionBase(startOffset, endOffset, type), IrIfExpression { + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + condition: IrExpression, + thenBranch: IrExpression, + elseBranch: IrExpression? = null, + operator: IrOperator? = null + ) : this(startOffset, endOffset, type, operator) { + this.condition = condition + this.thenBranch = thenBranch + this.elseBranch = elseBranch + } + + private var conditionImpl: IrExpression? = null + override var condition: IrExpression + get() = conditionImpl!! + set(value) { + value.assertDetached() + value.detach() + conditionImpl = value + value.setTreeLocation(this, IF_CONDITION_SLOT) + } + + private var thenBranchImpl: IrExpression? = null + override var thenBranch: IrExpression + get() = thenBranchImpl!! + set(value) { + value.assertDetached() + value.detach() + thenBranchImpl = value + value.setTreeLocation(this, IF_THEN_SLOT) + } + + 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? = + when (slot) { + IF_CONDITION_SLOT -> condition + IF_THEN_SLOT -> thenBranch + IF_ELSE_SLOT -> elseBranch + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + newChild.assertDetached() + when (slot) { + IF_CONDITION_SLOT -> + condition = newChild.assertCast() + IF_THEN_SLOT -> + thenBranch = newChild.assertCast() + IF_ELSE_SLOT -> + elseBranch = newChild.assertCast() + } + } + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitIf(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + condition.accept(visitor, data) + thenBranch.accept(visitor, data) + elseBranch?.accept(visitor, data) + } + + companion object { + // a || b == if (a) true else b + fun oror(a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrIfExpression = + IrIfExpressionImpl(b.startOffset, b.endOffset, b.type!!, + a, IrConstExpressionImpl.constTrue(b.startOffset, b.endOffset, b.type!!), b, + operator) + + // a && b == if (a) b else false + fun andand(a: IrExpression, b: IrExpression): IrIfExpression = + IrIfExpressionImpl(b.startOffset, b.endOffset, b.type!!, + a, b, IrConstExpressionImpl.constFalse(b.startOffset, b.endOffset, b.type!!), + IrOperator.OROR) + + fun whenComma(a: IrExpression, b: IrExpression): IrIfExpression = + oror(a, b, IrOperator.WHEN_COMMA) + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt index 65c9b04d6bb..cbffea73a4a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt @@ -70,6 +70,10 @@ interface IrOperator { object GET_PROPERTY : IrOperatorImpl("GET_PROPERTY") object SET_PROPERTY : IrOperatorImpl("SET_PROPERTY") + object IF : IrOperatorImpl("IF") + object WHEN : IrOperatorImpl("WHEN") + object WHEN_COMMA : IrOperatorImpl("WHEN_COMMA") + data class COMPONENT_N private constructor(val index: Int) : IrOperatorImpl("COMPONENT_$index") { companion object { private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) } @@ -81,4 +85,5 @@ interface IrOperator { COMPONENT_N(index) } } + } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrWhenExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrWhenExpression.kt deleted file mode 100644 index 38a9483f519..00000000000 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrWhenExpression.kt +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.ir.expressions - -import org.jetbrains.kotlin.ir.* -import org.jetbrains.kotlin.ir.declarations.IrVariable -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.utils.SmartList -import java.util.* - -interface IrWhenExpression : IrExpression { - var subject: IrVariable? - val branches: List - var elseExpression: IrExpression? - - fun addBranch(branch: IrBranch) -} - -interface IrBranch : IrElement { - val conditions: List - var result: IrExpression - - fun addCondition(expression: IrExpression) -} - -class IrWhenExpressionImpl( - startOffset: Int, - endOffset: Int, - type: KotlinType? -) : IrExpressionBase(startOffset, endOffset, type), IrWhenExpression { - constructor( - startOffset: Int, - endOffset: Int, - type: KotlinType?, - subject: IrVariable? - ) : this(startOffset, endOffset, type) { - this.subject = subject - } - - override var subject: IrVariable? = null - set(value) { - value?.assertDetached() - subject?.detach() - field = value - field?.setTreeLocation(this, WHEN_SUBJECT_VARIABLE_SLOT) - } - - override val branches: MutableList = ArrayList() - - override var elseExpression: IrExpression? = null - set(value) { - value?.assertDetached() - subject?.detach() - field = value - field?.setTreeLocation(this, WHEN_ELSE_EXPRESSION_SLOT) - } - - override fun addBranch(branch: IrBranch) { - branch.assertDetached() - branch.setTreeLocation(this, branches.size) - branches.add(branch) - } - - override fun getChild(slot: Int): IrElement? = - when (slot) { - WHEN_SUBJECT_VARIABLE_SLOT -> subject - WHEN_ELSE_EXPRESSION_SLOT -> elseExpression - else -> branches.getOrNull(slot) - } - - override fun replaceChild(slot: Int, newChild: IrElement) { - newChild.assertDetached() - when (slot) { - WHEN_SUBJECT_VARIABLE_SLOT -> - subject = newChild.assertCast() - WHEN_ELSE_EXPRESSION_SLOT -> - elseExpression = newChild.assertCast() - in branches.indices -> { - branches[slot].detach() - branches[slot] = newChild.assertCast() - newChild.setTreeLocation(this, slot) - } - } - } - - override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitWhenExpression(this, data) - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - subject?.accept(visitor, data) - branches.forEach { it.accept(visitor, data) } - elseExpression?.accept(visitor, data) - } - - companion object { - fun ifThen(startOffset: Int, endOffset: Int, type: KotlinType?, condition: IrExpression, thenExpression: IrExpression) = - IrWhenExpressionImpl(startOffset, endOffset, type).apply { - addBranch(IrBranchImpl(startOffset, endOffset, condition, thenExpression)) - } - - fun ifThenElse(startOffset: Int, endOffset: Int, type: KotlinType?, - condition: IrExpression, thenExpression: IrExpression, elseExpression: IrExpression) = - IrWhenExpressionImpl(startOffset, endOffset, type).apply { - addBranch(IrBranchImpl(startOffset, endOffset, condition, thenExpression)) - this.elseExpression = elseExpression - } - } -} - -class IrBranchImpl(startOffset: Int, endOffset: Int) : IrElementBase(startOffset, endOffset), IrBranch { - constructor(startOffset: Int, endOffset: Int, condition: IrExpression, result: IrExpression) : this(startOffset, endOffset) { - this.result = result - addCondition(condition) - } - - override val conditions: MutableList = SmartList() - - override fun addCondition(expression: IrExpression) { - expression.assertDetached() - expression.setTreeLocation(this, conditions.size) - conditions.add(expression) - } - - private var resultImpl: IrExpression? = null - override var result: IrExpression - get() = resultImpl!! - set(value) { - value.assertDetached() - resultImpl?.detach() - resultImpl = value - value.setTreeLocation(this, BRANCH_RESULT_SLOT) - } - - override fun getChild(slot: Int): IrElement? = - when (slot) { - BRANCH_RESULT_SLOT -> result - else -> conditions.getOrNull(slot) - } - - override fun replaceChild(slot: Int, newChild: IrElement) { - when (slot) { - BRANCH_RESULT_SLOT -> - result = newChild.assertCast() - in conditions.indices -> { - conditions[slot].detach() - conditions[slot] = newChild.assertCast() - newChild.setTreeLocation(this, slot) - } - } - } - - override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitBranch(this, data) - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - conditions.forEach { it.accept(visitor, data) } - resultImpl?.accept(visitor, data) - } -} \ No newline at end of file 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 c25f1efa23a..9fffe93840f 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.IrCallExpression -import org.jetbrains.kotlin.ir.expressions.IrWhenExpression +import org.jetbrains.kotlin.ir.expressions.IrIfExpression import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.utils.Printer @@ -54,16 +54,11 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { } } - override fun visitWhenExpression(expression: IrWhenExpression, data: String) { + override fun visitIf(expression: IrIfExpression, data: String) { expression.dumpLabeledElementWith(data) { - expression.subject?.let { subject -> - subject.accept(this, "\$subject") - } - for (branch in expression.branches) { - branch.conditions.forEach { it.accept(this, "if") } - branch.result.accept(this, "then") - } - expression.elseExpression?.accept(this, "else") + expression.condition.accept(this, "if") + expression.thenBranch.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 47cb3e0c6b3..7a54671270f 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 @@ -60,7 +60,7 @@ class RenderIrElementVisitor : IrElementVisitor { override fun visitExpression(expression: IrExpression, data: Nothing?): String = "? ${expression.javaClass.simpleName} type=${expression.renderType()}" - override fun visitLiteral(expression: IrLiteralExpression, data: Nothing?): String = + override fun visitConst(expression: IrConstExpression, data: Nothing?): String = "LITERAL ${expression.kind} type=${expression.renderType()} value='${expression.value}'" override fun visitBlockExpression(expression: IrBlockExpression, data: Nothing?): String = @@ -107,11 +107,8 @@ class RenderIrElementVisitor : IrElementVisitor { override fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: Nothing?): String = "TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}" - override fun visitWhenExpression(expression: IrWhenExpression, data: Nothing?): String = - "WHEN subject=${expression.subject?.descriptor?.name} type=${expression.type.render()}" - - override fun visitBranch(branch: IrBranch, data: Nothing?): String = - "BRANCH" + override fun visitIf(expression: IrIfExpression, data: Nothing?): String = + "IF 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 d29ed9816ad..3977d4d0fc5 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 @@ -35,12 +35,11 @@ interface IrElementVisitor { fun visitDelegatedProperty(declaration: IrDelegatedProperty, data: D): R = visitProperty(declaration, data) fun visitLocalVariable(declaration: IrVariable, data: D) = visitDeclaration(declaration, data) - fun visitBody(body: IrBody, data: D): R = visitElement(body, data) fun visitExpressionBody(body: IrExpressionBody, data: D): R = visitBody(body, data) fun visitExpression(expression: IrExpression, data: D): R = visitElement(expression, data) - fun visitLiteral(expression: IrLiteralExpression, data: D): R = visitExpression(expression, data) + fun visitConst(expression: IrConstExpression, data: D): R = visitExpression(expression, data) fun visitReturnExpression(expression: IrReturnExpression, data: D): R = visitExpression(expression, data) fun visitBlockExpression(expression: IrBlockExpression, data: D): R = visitExpression(expression, data) fun visitStringConcatenation(expression: IrStringConcatenationExpression, data: D) = visitExpression(expression, data) @@ -60,9 +59,7 @@ interface IrElementVisitor { fun visitBinaryOperator(expression: IrBinaryOperatorExpression, data: D) = visitOperatorExpression(expression, data) fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: D) = visitExpression(expression, data) - fun visitWhenExpression(expression: IrWhenExpression, data: D) = visitExpression(expression, data) - fun visitBranch(branch: IrBranch, data: D): R = visitElement(branch, data) - + fun visitIf(expression: IrIfExpression, data: D) = visitExpression(expression, data) fun visitLoop(loop: IrLoopExpression, data: D) = visitExpression(loop, data) fun visitWhileLoop(loop: IrWhileLoopExpression, data: D) = visitLoop(loop, data) fun visitDoWhileLoop(loop: IrDoWhileLoopExpression, data: D) = visitLoop(loop, data) diff --git a/compiler/testData/ir/irText/elvis.txt b/compiler/testData/ir/irText/elvis.txt index 93ea4b3aea2..0874ebfd721 100644 --- a/compiler/testData/ir/irText/elvis.txt +++ b/compiler/testData/ir/irText/elvis.txt @@ -16,12 +16,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 - WHEN subject=null type=kotlin.Unit + IF 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='' - WHEN subject=null type=kotlin.Unit + IF 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 6a7d93dd803..9a96f89af70 100644 --- a/compiler/testData/ir/irText/ifElseIf.txt +++ b/compiler/testData/ir/irText/ifElseIf.txt @@ -3,13 +3,14 @@ IrFile /ifElseIf.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - WHEN subject=null type=kotlin.Int + IF type=kotlin.Int operator=IF if: BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int GET_VAR i type=kotlin.Int operator=null LITERAL Int type=kotlin.Int value='0' then: LITERAL Int type=kotlin.Int value='1' - if: BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int - GET_VAR i type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='0' - then: DUMMY MINUS type=kotlin.Int - else: LITERAL Int type=kotlin.Int value='0' + else: IF type=kotlin.Int operator=IF + if: BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int + GET_VAR i type=kotlin.Int operator=null + LITERAL Int type=kotlin.Int value='0' + then: DUMMY MINUS type=kotlin.Int + 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 811526b0440..5581a85caba 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 - WHEN subject=null type=kotlin.Unit + IF 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 - WHEN subject=null type=kotlin.Unit + IF 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 - WHEN subject=null type=kotlin.Unit + IF 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 e5bad7aa5d9..1aa625fa894 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 - WHEN subject=null type=kotlin.Unit + IF 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.kt b/compiler/testData/ir/irText/when.kt index 0f9cfa3bbac..42ab5558fa0 100644 --- a/compiler/testData/ir/irText/when.kt +++ b/compiler/testData/ir/irText/when.kt @@ -17,3 +17,11 @@ fun test(x: Any?) = x in setOf() -> "nothingness?" else -> "something" } + +fun testComma(x: Int) = + when (x) { + 1, 2, 3, 4 -> "1234" + 5, 6, 7 -> "567" + 8, 9 -> "89" + else -> "?" + } \ No newline at end of file diff --git a/compiler/testData/ir/irText/when.txt b/compiler/testData/ir/irText/when.txt index 8ae91505d9d..91646c59fdd 100644 --- a/compiler/testData/ir/irText/when.txt +++ b/compiler/testData/ir/irText/when.txt @@ -4,45 +4,105 @@ IrFile /when.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - WHEN subject=tmp0_subject type=kotlin.String - $subject: VAR val tmp0_subject: kotlin.Any? + BLOCK type=kotlin.String hasResult=true operator=WHEN + VAR val tmp0_subject: kotlin.Any? GET_VAR x type=kotlin.Any? operator=null - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Any? operator=null - LITERAL Null type=kotlin.Nothing? value='null' - then: LITERAL String type=kotlin.String value='null' - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Any? operator=null - 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 + IF type=kotlin.String operator=WHEN + if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null 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' + LITERAL Null type=kotlin.Nothing? value='null' + then: LITERAL String type=kotlin.String value='null' + else: IF type=kotlin.String operator=WHEN + if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Any? operator=null + 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' IrFunction public fun test(/*0*/ x: kotlin.Any?): kotlin.String IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - WHEN subject=null type=kotlin.String + IF type=kotlin.String operator=WHEN if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=public open operator fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean GET_VAR x type=kotlin.Any? operator=null LITERAL Null type=kotlin.Nothing? value='null' then: LITERAL String type=kotlin.String value='null' - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=public open operator fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - GET_VAR x type=kotlin.Any? operator=null - 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 + else: IF type=kotlin.String operator=WHEN + if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=public open operator fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean GET_VAR x type=kotlin.Any? operator=null - then: LITERAL String type=kotlin.String value='nothingness?' - else: LITERAL String type=kotlin.String value='something' + 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' + IrFunction public fun testComma(/*0*/ x: kotlin.Int): kotlin.String + IrExpressionBody + BLOCK type= hasResult=false operator=null + RETURN type= + 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 + if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + LITERAL Int type=kotlin.Int value='1' + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + LITERAL Int type=kotlin.Int value='2' + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + LITERAL Int type=kotlin.Int value='3' + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + 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: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + LITERAL Int type=kotlin.Int value='5' + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + LITERAL Int type=kotlin.Int value='6' + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + 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: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + LITERAL Int type=kotlin.Int value='8' + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null + GET_VAR tmp0_subject type=kotlin.Int operator=null + LITERAL Int type=kotlin.Int value='9' + then: LITERAL String type=kotlin.String value='89' + else: LITERAL String type=kotlin.String value='?'