diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt index c304a89e0c9..ccc82e2bb98 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt @@ -20,13 +20,14 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.KtBlockExpression import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtLoopExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import java.util.* class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): GeneratorWithScope { override val scope = Scope(scopeOwner) - private val loopTable = HashMap() + private val loopTable = HashMap() fun generateFunctionBody(ktBody: KtExpression): IrBody { resetInternalContext() @@ -64,7 +65,7 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge private fun createStatementGenerator() = StatementGenerator(context, scopeOwner, this, scope) - fun putLoop(expression: KtExpression, irLoop: IrLoop) { + fun putLoop(expression: KtLoopExpression, irLoop: IrLoop) { loopTable[expression] = irLoop } 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 index 85a37313145..98c62d73bdd 100644 --- 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 @@ -44,7 +44,7 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene private fun generateConditionalLoop(ktLoop: KtWhileExpressionBase, irLoop: IrLoopBase): IrLoop { statementGenerator.bodyGenerator.putLoop(ktLoop, irLoop) irLoop.condition = statementGenerator.generateExpression(ktLoop.condition!!) - irLoop.body = statementGenerator.generateExpression(ktLoop.body!!) + irLoop.body = ktLoop.body?.let { statementGenerator.generateExpression(ktLoop.body!!) } irLoop.label = getLoopLabel(ktLoop) return irLoop } @@ -105,7 +105,7 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene } val ktLoopRange = ktFor.loopRange!! - val ktForBody = ktFor.body!! + val ktForBody = ktFor.body val iteratorResolvedCall = getOrFail(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, ktLoopRange) val hasNextResolvedCall = getOrFail(BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, ktLoopRange) val nextResolvedCall = getOrFail(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, ktLoopRange) @@ -150,7 +150,9 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene statementGenerator.declareComponentVariablesInBlock(ktLoopDestructuringParameter, irInnerBody, VariableLValue(irLoopParameter)) } - irInnerBody.addStatement(statementGenerator.generateExpression(ktForBody)) + if (ktForBody != null) { + irInnerBody.addStatement(statementGenerator.generateExpression(ktForBody)) + } return irForBlock } 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 6e2de8c07a3..d39cbeeaa19 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 @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.types.KotlinType interface IrLoop : IrExpression { val operator: IrOperator? - var body: IrExpression + var body: IrExpression? var condition: IrExpression val label: String? } @@ -49,14 +49,12 @@ abstract class IrLoopBase( value.setTreeLocation(this, LOOP_CONDITION_SLOT) } - private var bodyImpl: IrExpression? = null - override var body: IrExpression - get() = bodyImpl!! + override var body: IrExpression? = null set(value) { - value.assertDetached() - bodyImpl?.detach() - bodyImpl = value - value.setTreeLocation(this, LOOP_BODY_SLOT) + value?.assertDetached() + field?.detach() + field = value + value?.setTreeLocation(this, LOOP_BODY_SLOT) } override fun getChild(slot: Int): IrElement? = @@ -98,7 +96,7 @@ class IrWhileLoopImpl( override fun acceptChildren(visitor: IrElementVisitor, data: D) { condition.accept(visitor, data) - body.accept(visitor, data) + body?.accept(visitor, data) } } @@ -125,7 +123,7 @@ class IrDoWhileLoopImpl( } override fun acceptChildren(visitor: IrElementVisitor, data: D) { - body.accept(visitor, data) + body?.accept(visitor, data) condition.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 faadaff7f5e..423fd31022b 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 @@ -66,13 +66,13 @@ 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") + loop.body?.accept(this, "body") } } override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: String) { loop.dumpLabeledElementWith(data) { - loop.body.accept(this, "body") + loop.body?.accept(this, "body") loop.condition.accept(this, "condition") } } diff --git a/compiler/testData/ir/irText/for.kt b/compiler/testData/ir/irText/for.kt index bdeba41db84..6d780f0805f 100644 --- a/compiler/testData/ir/irText/for.kt +++ b/compiler/testData/ir/irText/for.kt @@ -1,3 +1,7 @@ +fun testEmpty(ss: List) { + for (s in ss); +} + fun testIterable(ss: List) { for (s in ss) { println(s) diff --git a/compiler/testData/ir/irText/for.txt b/compiler/testData/ir/irText/for.txt index 4c7275023b9..9bc78d96f0f 100644 --- a/compiler/testData/ir/irText/for.txt +++ b/compiler/testData/ir/irText/for.txt @@ -1,4 +1,17 @@ FILE /for.kt + FUN public fun testEmpty(/*0*/ ss: kotlin.collections.List): kotlin.Unit + BLOCK_BODY + BLOCK type=kotlin.Unit operator=FOR_LOOP + VAR val tmp0_iterator: kotlin.collections.Iterator + CALL .iterator type=kotlin.collections.Iterator operator=FOR_LOOP_ITERATOR + $this: GET_VAR ss type=kotlin.collections.List operator=null + WHILE label=null operator=FOR_LOOP_INNER_WHILE + condition: CALL .hasNext type=kotlin.Boolean operator=FOR_LOOP_HAS_NEXT + $this: GET_VAR tmp0_iterator type=kotlin.collections.Iterator operator=null + body: BLOCK type=kotlin.Unit operator=FOR_LOOP_INNER_WHILE + VAR val s: kotlin.String + CALL .next type=kotlin.String operator=FOR_LOOP_NEXT + $this: GET_VAR tmp0_iterator type=kotlin.collections.Iterator operator=null FUN public fun testIterable(/*0*/ ss: kotlin.collections.List): kotlin.Unit BLOCK_BODY BLOCK type=kotlin.Unit operator=FOR_LOOP diff --git a/compiler/testData/ir/irText/whileDoWhile.kt b/compiler/testData/ir/irText/whileDoWhile.kt index c48d468c1d4..58227d46da4 100644 --- a/compiler/testData/ir/irText/whileDoWhile.kt +++ b/compiler/testData/ir/irText/whileDoWhile.kt @@ -1,7 +1,9 @@ fun test() { var x = 0 + while (x < 0); while (x < 5) x++ while (x < 10) { x++ } + do while (x < 0) do x++ while (x < 15) do { x ++ } while (x < 20) } diff --git a/compiler/testData/ir/irText/whileDoWhile.txt b/compiler/testData/ir/irText/whileDoWhile.txt index 88563439e2a..2c5fe0fcdf1 100644 --- a/compiler/testData/ir/irText/whileDoWhile.txt +++ b/compiler/testData/ir/irText/whileDoWhile.txt @@ -3,6 +3,11 @@ FILE /whileDoWhile.kt BLOCK_BODY VAR var x: kotlin.Int CONST Int type=kotlin.Int value='0' + WHILE label=null 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='0' WHILE label=null operator=WHILE_LOOP condition: CALL .LT0 type=kotlin.Boolean operator=LT arg0: CALL .compareTo type=kotlin.Int operator=LT @@ -28,6 +33,11 @@ FILE /whileDoWhile.kt 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 label=null operator=DO_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='0' DO_WHILE label=null operator=DO_WHILE_LOOP body: BLOCK type=kotlin.Int operator=POSTFIX_INCR VAR val tmp2: kotlin.Int