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/BranchingExpressionGenerator.kt similarity index 75% rename from compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt rename to compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt index 5c5dc7e361c..a4aca7e613b 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/BranchingExpressionGenerator.kt @@ -22,15 +22,56 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.defaultLoad +import org.jetbrains.kotlin.psi2ir.deparenthesize import org.jetbrains.kotlin.psi2ir.generators.getInfixOperator import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.utils.SmartList import java.lang.AssertionError -class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : BodyGenerator { +class BranchingExpressionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope { override val scope: Scope get() = statementGenerator.scope override val context: GeneratorContext get() = statementGenerator.context - fun generate(expression: KtWhenExpression): IrExpression { + fun generateIfExpression(expression: KtIfExpression): IrExpression { + val resultType = getInferredTypeWithSmartcasts(expression) + + var ktLastIf: KtIfExpression = expression + val irBranches = SmartList>() + var irElseBranch: IrExpression? = null + + whenBranches@while (true) { + val irCondition = statementGenerator.generateExpression(ktLastIf.condition!!) + val irThenBranch = statementGenerator.generateExpression(ktLastIf.then!!) + irBranches.add(Pair(irCondition, irThenBranch)) + + val ktElse = ktLastIf.`else`?.deparenthesize() + when (ktElse) { + null -> break@whenBranches + is KtIfExpression -> ktLastIf = ktElse + is KtExpression -> { + irElseBranch = statementGenerator.generateExpression(ktElse) + 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 + } + } + + fun generateWhenExpression(expression: KtWhenExpression): IrExpression { val irSubject = expression.subjectExpression?.let { scope.createTemporaryVariable(statementGenerator.generateExpression(it), "subject") } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index 49d0139b448..4681d725c15 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -35,9 +35,9 @@ import java.util.* class CallGenerator( override val context: GeneratorContext, override val scope: Scope -) : BodyGenerator { +) : GeneratorWithScope { - constructor(parent: BodyGenerator) : this(parent.context, parent.scope) + constructor(parent: GeneratorWithScope) : this(parent.context, parent.scope) fun generateCall( startOffset: Int, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExpressionBodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExpressionBodyGenerator.kt index 616d7253ff3..5a470f617a9 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExpressionBodyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExpressionBodyGenerator.kt @@ -17,16 +17,17 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.ir.expressions.IrBlockImpl -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrReturnImpl +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.KtBlockExpression import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtWhileExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset +import java.util.* -class ExpressionBodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): BodyGenerator { +class ExpressionBodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): GeneratorWithScope { override val scope = Scope(scopeOwner) + private val loopTable = HashMap() fun generateFunctionBody(ktBody: KtExpression): IrExpression { resetInternalContext() @@ -46,6 +47,7 @@ class ExpressionBodyGenerator(val scopeOwner: CallableDescriptor, override val c } private fun resetInternalContext() { + loopTable.clear() } private fun postprocessFunctionBody() { @@ -56,5 +58,9 @@ class ExpressionBodyGenerator(val scopeOwner: CallableDescriptor, override val c private fun createStatementGenerator() = StatementGenerator(context, scopeOwner, this, scope) + + fun putLoop(expression: KtExpression, irLoop: IrLoop) { + loopTable[expression] = irLoop + } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Generator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Generator.kt index 4a07e4bf39e..0124d96eb16 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Generator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Generator.kt @@ -40,7 +40,7 @@ interface Generator { val context: GeneratorContext } -interface BodyGenerator : Generator { +interface GeneratorWithScope : Generator { val scope: Scope } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt new file mode 100644 index 00000000000..c68746655bd --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt @@ -0,0 +1,39 @@ +/* + * 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.psi2ir.generators + +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.psi.KtDoWhileExpression +import org.jetbrains.kotlin.psi.KtWhileExpression +import org.jetbrains.kotlin.psi.KtWhileExpressionBase +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.startOffset + +class LoopExpressionGenerator(val statementGenerator: StatementGenerator) { + fun generateWhileExpression(expression: KtWhileExpression): IrExpression = + generateConditionalLoop(expression, IrWhileLoopImpl(expression.startOffset, expression.endOffset, IrOperator.WHILE_LOOP)) + + fun generateDoWhileExpression(expression: KtDoWhileExpression): IrExpression = + generateConditionalLoop(expression, IrDoWhileLoopImpl(expression.startOffset, expression.endOffset, IrOperator.DO_WHILE_LOOP)) + + private fun generateConditionalLoop(expression: KtWhileExpressionBase, irLoop: IrLoop): IrLoop { + statementGenerator.expressionBodyGenerator.putLoop(expression, irLoop) + irLoop.condition = statementGenerator.generateExpression(expression.condition!!) + irLoop.body = statementGenerator.generateExpression(expression.body!!) + return irLoop + } +} \ No newline at end of file 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 1b2b43de60e..7d08736b318 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 @@ -34,7 +34,7 @@ import java.lang.AssertionError class OperatorExpressionGenerator( val statementGenerator: StatementGenerator -) : BodyGenerator { +) : GeneratorWithScope { override val scope: Scope get() = statementGenerator.scope override val context: GeneratorContext get() = statementGenerator.context 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 8ac971aeafd..7816ff1aaa4 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 @@ -41,15 +41,14 @@ 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 import java.lang.AssertionError class StatementGenerator( override val context: GeneratorContext, val scopeOwner: DeclarationDescriptor, - @Suppress("unused") val expressionBodyGenerator: ExpressionBodyGenerator, + val expressionBodyGenerator: ExpressionBodyGenerator, override val scope: Scope -) : KtVisitor(), BodyGenerator { +) : KtVisitor(), GeneratorWithScope { fun generateExpression(ktExpression: KtExpression): IrExpression = ktExpression.genExpr() @@ -267,50 +266,17 @@ class StatementGenerator( override fun visitIsExpression(expression: KtIsExpression, data: Nothing?): IrStatement = OperatorExpressionGenerator(this).generateInstanceOfExpression(expression) - override fun visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement { - val resultType = getInferredTypeWithSmartcasts(expression) - - var ktLastIf: KtIfExpression = expression - val irBranches = SmartList>() - var irElseBranch: IrExpression? = null - - whenBranches@while (true) { - val irCondition = ktLastIf.condition!!.genExpr() - val irThenBranch = ktLastIf.then!!.genExpr() - irBranches.add(Pair(irCondition, irThenBranch)) - - val ktElse = ktLastIf.`else`?.deparenthesize() - when (ktElse) { - null -> break@whenBranches - is KtIfExpression -> ktLastIf = ktElse - is KtExpression -> { - irElseBranch = ktElse.genExpr() - 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 visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement = + BranchingExpressionGenerator(this).generateIfExpression(expression) override fun visitWhenExpression(expression: KtWhenExpression, data: Nothing?): IrStatement = - WhenExpressionGenerator(this).generate(expression) + BranchingExpressionGenerator(this).generateWhenExpression(expression) + override fun visitWhileExpression(expression: KtWhileExpression, data: Nothing?): IrStatement = + LoopExpressionGenerator(this).generateWhileExpression(expression) + override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Nothing?): IrStatement = + LoopExpressionGenerator(this).generateDoWhileExpression(expression) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt index 0d246755bc1..4e6d152cf3b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SafeCallReceiver.kt @@ -20,14 +20,14 @@ import org.jetbrains.kotlin.ir.expressions.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrIfThenElseImpl import org.jetbrains.kotlin.ir.expressions.IrOperator -import org.jetbrains.kotlin.psi2ir.generators.BodyGenerator +import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope import org.jetbrains.kotlin.psi2ir.generators.constNull import org.jetbrains.kotlin.psi2ir.generators.equalsNull import org.jetbrains.kotlin.types.typeUtil.makeNullable class SafeCallReceiver( - val generator: BodyGenerator, + val generator: GeneratorWithScope, val startOffset: Int, val endOffset: Int, val explicitReceiver: IrExpression, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoop.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoop.kt index f6da22904b8..a3a8965a158 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoop.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoop.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor interface IrLoop : IrExpression { + val operator: IrOperator? var body: IrExpression var condition: IrExpression } @@ -30,8 +31,19 @@ interface IrDoWhileLoop : IrLoop abstract class IrLoopBase( startOffset: Int, - endOffset: Int + endOffset: Int, + override val operator: IrOperator? ) : IrExpressionBase(startOffset, endOffset, null), IrLoop { + private var conditionImpl: IrExpression? = null + override var condition: IrExpression + get() = conditionImpl!! + set(value) { + value.assertDetached() + conditionImpl?.detach() + conditionImpl = value + value.setTreeLocation(this, LOOP_CONDITION_SLOT) + } + private var bodyImpl: IrExpression? = null override var body: IrExpression get() = bodyImpl!! @@ -45,54 +57,30 @@ abstract class IrLoopBase( override fun getChild(slot: Int): IrElement? = when (slot) { LOOP_BODY_SLOT -> body + LOOP_CONDITION_SLOT -> condition else -> null } override fun replaceChild(slot: Int, newChild: IrElement) { when (slot) { LOOP_BODY_SLOT -> body = newChild.assertCast() - } - } -} - -abstract class IrConditionalLoopBase( - startOffset: Int, - endOffset: Int -) : IrLoopBase(startOffset, endOffset) { - private var conditionImpl: IrExpression? = null - override var condition: IrExpression - get() = conditionImpl!! - set(value) { - value.assertDetached() - conditionImpl?.detach() - conditionImpl = value - value.setTreeLocation(this, LOOP_CONDITION_SLOT) - } - - override fun getChild(slot: Int): IrElement? = - when (slot) { - LOOP_CONDITION_SLOT -> condition - else -> super.getChild(slot) - } - - override fun replaceChild(slot: Int, newChild: IrElement) { - when (slot) { LOOP_CONDITION_SLOT -> condition = newChild.assertCast() - else -> super.replaceChild(slot, newChild) } } } class IrWhileLoopImpl( startOffset: Int, - endOffset: Int -) : IrConditionalLoopBase(startOffset, endOffset), IrWhileLoop { + endOffset: Int, + operator: IrOperator? +) : IrLoopBase(startOffset, endOffset, operator), IrWhileLoop { constructor( startOffset: Int, endOffset: Int, + operator: IrOperator?, condition: IrExpression, body: IrExpression - ) : this(startOffset, endOffset) { + ) : this(startOffset, endOffset, operator) { this.condition = condition this.body = body } @@ -109,14 +97,16 @@ class IrWhileLoopImpl( class IrDoWhileLoopImpl( startOffset: Int, - endOffset: Int -) : IrConditionalLoopBase(startOffset, endOffset), IrDoWhileLoop { + endOffset: Int, + operator: IrOperator? +) : IrLoopBase(startOffset, endOffset, operator), IrDoWhileLoop { constructor( startOffset: Int, endOffset: Int, + operator: IrOperator?, body: IrExpression, condition: IrExpression - ) : this(startOffset, endOffset) { + ) : this(startOffset, endOffset, operator) { this.condition = condition this.body = body } 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 4737028bb79..aa03f939a32 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 @@ -74,6 +74,8 @@ interface IrOperator { object IF : IrOperatorImpl("IF") object WHEN : IrOperatorImpl("WHEN") object WHEN_COMMA : IrOperatorImpl("WHEN_COMMA") + object WHILE_LOOP : IrOperatorImpl("WHILE_LOOP") + object DO_WHILE_LOOP : IrOperatorImpl("DO_WHILE_LOOP") data class COMPONENT_N private constructor(val index: Int) : IrOperatorImpl("COMPONENT_$index") { companion object { @@ -87,6 +89,8 @@ interface IrOperator { } } + + } fun IrOperator.isAssignmentOperatorWithResult() = 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 51020280908..415bd2a4f92 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,9 @@ 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.IrDoWhileLoop import org.jetbrains.kotlin.ir.expressions.IrWhen +import org.jetbrains.kotlin.ir.expressions.IrWhileLoop import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.utils.Printer @@ -64,6 +66,20 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { } } + override fun visitWhileLoop(loop: IrWhileLoop, data: String) { + loop.dumpLabeledElementWith(data) { + loop.condition.accept(this, "condition") + loop.body.accept(this, "body") + } + } + + override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: String) { + loop.dumpLabeledElementWith(data) { + loop.body.accept(this, "body") + loop.condition.accept(this, "condition") + } + } + private inline fun IrElement.dumpLabeledElementWith(label: String, body: () -> Unit) { printer.println(accept(elementRenderer, null).withLabel(label)) indented(body) 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 473873b6949..be908348f84 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 @@ -100,6 +100,12 @@ class RenderIrElementVisitor : IrElementVisitor { override fun visitWhen(expression: IrWhen, data: Nothing?): String = "WHEN type=${expression.type.render()} operator=${expression.operator}" + override fun visitWhileLoop(loop: IrWhileLoop, data: Nothing?): String = + "WHILE operator=${loop.operator}" + + override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: Nothing?): String = + "DO_WHILE operator=${loop.operator}" + override fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: Nothing?): String = "DUMMY ${declaration.descriptor.name}" diff --git a/compiler/testData/ir/irText/whileDoWhile.kt b/compiler/testData/ir/irText/whileDoWhile.kt new file mode 100644 index 00000000000..c48d468c1d4 --- /dev/null +++ b/compiler/testData/ir/irText/whileDoWhile.kt @@ -0,0 +1,15 @@ +fun test() { + var x = 0 + while (x < 5) x++ + while (x < 10) { x++ } + do x++ while (x < 15) + do { x ++ } while (x < 20) +} + +fun testSmartcastInCondition() { + val a: Any? = null + if (a is Boolean) { + while (a) {} + do {} while (a) + } +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/whileDoWhile.txt b/compiler/testData/ir/irText/whileDoWhile.txt new file mode 100644 index 00000000000..6b56816b56f --- /dev/null +++ b/compiler/testData/ir/irText/whileDoWhile.txt @@ -0,0 +1,73 @@ +IrFile /whileDoWhile.kt + IrFunction public fun test(): kotlin.Unit + IrExpressionBody + BLOCK type= hasResult=false operator=null + VAR var x: kotlin.Int + CONST Int type=kotlin.Int value='0' + WHILE operator=WHILE_LOOP + condition: CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR x type=kotlin.Int operator=null + other: CONST Int type=kotlin.Int value='5' + body: BLOCK type=kotlin.Int hasResult=true operator=POSTFIX_INCR + VAR val tmp0: kotlin.Int + GET_VAR x type=kotlin.Int operator=POSTFIX_INCR + SET_VAR x type= operator=POSTFIX_INCR + CALL .inc type=kotlin.Int operator=POSTFIX_INCR + $this: GET_VAR tmp0 type=kotlin.Int operator=null + GET_VAR tmp0 type=kotlin.Int operator=null + WHILE operator=WHILE_LOOP + condition: CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR x type=kotlin.Int operator=null + other: CONST Int type=kotlin.Int value='10' + body: BLOCK type=kotlin.Int hasResult=true operator=null + BLOCK type=kotlin.Int hasResult=true operator=POSTFIX_INCR + VAR val tmp1: kotlin.Int + GET_VAR x type=kotlin.Int operator=POSTFIX_INCR + SET_VAR x type= operator=POSTFIX_INCR + CALL .inc type=kotlin.Int operator=POSTFIX_INCR + $this: GET_VAR tmp1 type=kotlin.Int operator=null + GET_VAR tmp1 type=kotlin.Int operator=null + DO_WHILE operator=DO_WHILE_LOOP + body: BLOCK type=kotlin.Int hasResult=true operator=POSTFIX_INCR + VAR val tmp2: kotlin.Int + GET_VAR x type=kotlin.Int operator=POSTFIX_INCR + SET_VAR x type= operator=POSTFIX_INCR + CALL .inc type=kotlin.Int operator=POSTFIX_INCR + $this: GET_VAR tmp2 type=kotlin.Int operator=null + GET_VAR tmp2 type=kotlin.Int operator=null + condition: CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR x type=kotlin.Int operator=null + other: CONST Int type=kotlin.Int value='15' + DO_WHILE operator=DO_WHILE_LOOP + body: BLOCK type=kotlin.Int hasResult=true operator=null + BLOCK type=kotlin.Int hasResult=true operator=POSTFIX_INCR + VAR val tmp3: kotlin.Int + GET_VAR x type=kotlin.Int operator=POSTFIX_INCR + SET_VAR x type= operator=POSTFIX_INCR + CALL .inc type=kotlin.Int operator=POSTFIX_INCR + $this: GET_VAR tmp3 type=kotlin.Int operator=null + GET_VAR tmp3 type=kotlin.Int operator=null + condition: CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR x type=kotlin.Int operator=null + other: CONST Int type=kotlin.Int value='20' + IrFunction public fun testSmartcastInCondition(): kotlin.Unit + IrExpressionBody + BLOCK type= hasResult=false operator=null + VAR val a: kotlin.Any? = null + CONST Null type=kotlin.Nothing? value='null' + WHEN type=kotlin.Unit operator=IF + if: TYPE_OP operator=INSTANCEOF typeOperand=kotlin.Boolean + GET_VAR a type=kotlin.Any? operator=null + then: BLOCK type= hasResult=false operator=null + WHILE operator=WHILE_LOOP + condition: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Boolean + GET_VAR a type=kotlin.Any? operator=null + body: BLOCK type= hasResult=false operator=null + DO_WHILE operator=DO_WHILE_LOOP + body: BLOCK type= hasResult=false operator=null + condition: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Boolean + GET_VAR a type=kotlin.Any? operator=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 93c715a3e60..4dc9b3425e0 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -250,4 +250,10 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/when.kt"); doTest(fileName); } + + @TestMetadata("whileDoWhile.kt") + public void testWhileDoWhile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/whileDoWhile.kt"); + doTest(fileName); + } }