This commit is contained in:
Dmitry Petrov
2016-08-24 17:11:01 +03:00
committed by Dmitry Petrov
parent 03a666690b
commit 4709aaafaa
12 changed files with 375 additions and 32 deletions
@@ -29,6 +29,10 @@ fun StatementGenerator.generateReceiverOrNull(ktDefaultElement: KtElement, recei
receiver?.let { generateReceiver(ktDefaultElement, receiver) }
fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: ReceiverValue): IntermediateValue {
if (receiver is TransientReceiver) {
return TransientReceiverValue(ktDefaultElement.text, receiver.type)
}
val receiverExpression = when (receiver) {
is ImplicitClassReceiver ->
IrThisReferenceImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset, receiver.type, receiver.classDescriptor)
@@ -16,44 +16,49 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginKind
import org.jetbrains.kotlin.ir.declarations.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.intermediate.VariableLValue
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
import org.jetbrains.kotlin.resolve.BindingContext
class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope {
override val scope: Scope get() = statementGenerator.scope
override val context: GeneratorContext get() = statementGenerator.context
fun generateWhileExpression(expression: KtWhileExpression): IrExpression =
generateConditionalLoop(expression, IrWhileLoopImpl(expression.startOffset, expression.endOffset, IrOperator.WHILE_LOOP))
fun generateWhileLoop(ktWhile: KtWhileExpression): IrExpression =
generateConditionalLoop(ktWhile, IrWhileLoopImpl(ktWhile.startOffset, ktWhile.endOffset, IrOperator.WHILE_LOOP))
fun generateDoWhileExpression(expression: KtDoWhileExpression): IrExpression =
generateConditionalLoop(expression, IrDoWhileLoopImpl(expression.startOffset, expression.endOffset, IrOperator.DO_WHILE_LOOP))
fun generateDoWhileLoop(ktDoWhile: KtDoWhileExpression): IrExpression =
generateConditionalLoop(ktDoWhile, IrDoWhileLoopImpl(ktDoWhile.startOffset, ktDoWhile.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!!)
private fun generateConditionalLoop(ktLoop: KtWhileExpressionBase, irLoop: IrLoop): IrLoop {
statementGenerator.expressionBodyGenerator.putLoop(ktLoop, irLoop)
irLoop.condition = statementGenerator.generateExpression(ktLoop.condition!!)
irLoop.body = statementGenerator.generateExpression(ktLoop.body!!)
return irLoop
}
fun generateBreakExpression(expression: KtBreakExpression): IrExpression {
val parentLoop = findParentLoop(expression)
return IrBreakImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, parentLoop)
fun generateBreak(ktBreak: KtBreakExpression): IrExpression {
val parentLoop = findParentLoop(ktBreak)
return IrBreakImpl(ktBreak.startOffset, ktBreak.endOffset, context.builtIns.nothingType, parentLoop)
}
fun generateContinueExpression(expression: KtContinueExpression): IrExpression {
val parentLoop = findParentLoop(expression)
return IrContinueImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, parentLoop)
fun generateContinue(ktContinue: KtContinueExpression): IrExpression {
val parentLoop = findParentLoop(ktContinue)
return IrContinueImpl(ktContinue.startOffset, ktContinue.endOffset, context.builtIns.nothingType, parentLoop)
}
private fun findParentLoop(expression: KtExpressionWithLabel): IrLoop =
findParentLoop(expression, expression.getTargetLabel()?.getReferencedName())
private fun findParentLoop(ktWithLabel: KtExpressionWithLabel): IrLoop =
findParentLoop(ktWithLabel, ktWithLabel.getTargetLabel()?.getReferencedName())
private fun findParentLoop(expression: KtExpression, targetLabel: String?): IrLoop {
var finger: KtExpression? = expression
private fun findParentLoop(ktExpression: KtExpression, targetLabel: String?): IrLoop {
var finger: KtExpression? = ktExpression
while (finger != null) {
finger = finger.getParentOfType<KtLoopExpression>(true)
if (finger == null) {
@@ -75,10 +80,65 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene
throw AssertionError("No parent loop for break/continue @$targetLabel")
}
private fun getLoop(finger: KtLoopExpression): IrLoop {
return statementGenerator.expressionBodyGenerator.getLoop(finger) ?:
throw AssertionError("Loop was not visited:\n${finger.text}")
private fun getLoop(ktLoop: KtLoopExpression): IrLoop {
return statementGenerator.expressionBodyGenerator.getLoop(ktLoop) ?:
throw AssertionError("Loop was not visited:\n${ktLoop.text}")
}
fun generateForLoop(ktFor: KtForExpression): IrExpression {
val ktLoopParameter = ktFor.loopParameter
val ktLoopDestructuringParameter = ktFor.destructuringParameter
if (ktLoopParameter == null && ktLoopDestructuringParameter == null) {
throw AssertionError("Either loopParameter or destructuringParameter should be present:\n${ktFor.text}")
}
val ktLoopRange = ktFor.loopRange!!
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)
val callGenerator = CallGenerator(statementGenerator)
val irForBlock = IrBlockImpl(ktFor.startOffset, ktFor.endOffset, context.builtIns.unitType, false, IrOperator.FOR_LOOP)
val iteratorCall = statementGenerator.pregenerateCall(iteratorResolvedCall)
val irIteratorCall = callGenerator.generateCall(ktLoopRange, iteratorCall, IrOperator.FOR_LOOP_ITERATOR)
val irIterator = scope.createTemporaryVariable(irIteratorCall, "iterator")
val iteratorValue = VariableLValue(irIterator)
irForBlock.addStatement(irIterator)
val irInnerWhile = IrWhileLoopImpl(ktFor.startOffset, ktFor.endOffset, IrOperator.FOR_LOOP_INNER_WHILE)
statementGenerator.expressionBodyGenerator.putLoop(ktFor, irInnerWhile)
irForBlock.addStatement(irInnerWhile)
val hasNextCall = statementGenerator.pregenerateCall(hasNextResolvedCall)
hasNextCall.setExplicitReceiverValue(iteratorValue)
val irHasNextCall = callGenerator.generateCall(ktLoopRange, hasNextCall, IrOperator.FOR_LOOP_HAS_NEXT)
irInnerWhile.condition = irHasNextCall
val irInnerBody = IrBlockImpl(ktFor.startOffset, ktFor.endOffset, context.builtIns.unitType, false, IrOperator.FOR_LOOP_INNER_WHILE)
irInnerWhile.body = irInnerBody
val nextCall = statementGenerator.pregenerateCall(nextResolvedCall)
nextCall.setExplicitReceiverValue(iteratorValue)
val irNextCall = callGenerator.generateCall(ktLoopRange, nextCall, IrOperator.FOR_LOOP_NEXT)
val irLoopParameter = if (ktLoopParameter != null) {
val loopParameterDescriptor = getOrFail(BindingContext.VALUE_PARAMETER, ktLoopParameter)
IrVariableImpl(ktLoopParameter.startOffset, ktLoopParameter.endOffset, IrDeclarationOriginKind.DEFINED,
loopParameterDescriptor, irNextCall)
}
else {
scope.createTemporaryVariable(irNextCall, "loop_parameter")
}
irInnerBody.addStatement(irLoopParameter)
if (ktLoopDestructuringParameter != null) {
statementGenerator.declareComponentVariablesInBlock(ktLoopDestructuringParameter, irInnerBody, VariableLValue(irLoopParameter))
}
irInnerBody.addStatement(statementGenerator.generateExpression(ktForBody))
return irForBlock
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.deparenthesize
import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue
import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableOrTemporary
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
import org.jetbrains.kotlin.resolve.BindingContext
@@ -76,25 +77,28 @@ class StatementGenerator(
val irBlock = IrBlockImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null, false, IrOperator.SYNTHETIC_BLOCK)
val ktInitializer = multiDeclaration.initializer!!
val irTmpInitializerValue = createRematerializableOrTemporary(scope, ktInitializer.genExpr(), irBlock, "container")
val containerValue = createRematerializableOrTemporary(scope, ktInitializer.genExpr(), irBlock, "container")
val irCallGenerator = CallGenerator(this)
declareComponentVariablesInBlock(multiDeclaration, irBlock, containerValue)
return irBlock
}
fun declareComponentVariablesInBlock(multiDeclaration: KtDestructuringDeclaration, irBlock: IrBlockImpl, containerValue: IntermediateValue) {
val callGenerator = CallGenerator(this)
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
val componentSubstitutedCall = pregenerateCall(componentResolvedCall)
componentSubstitutedCall.setExplicitReceiverValue(irTmpInitializerValue)
componentSubstitutedCall.setExplicitReceiverValue(containerValue)
val componentVariable = getOrFail(BindingContext.VARIABLE, ktEntry)
val irComponentCall = irCallGenerator.generateCall(ktEntry.startOffset, ktEntry.endOffset, componentSubstitutedCall,
IrOperator.COMPONENT_N.withIndex(index + 1))
val irComponentCall = callGenerator.generateCall(ktEntry.startOffset, ktEntry.endOffset, componentSubstitutedCall,
IrOperator.COMPONENT_N.withIndex(index + 1))
val irComponentVar = IrVariableImpl(ktEntry.startOffset, ktEntry.endOffset, IrDeclarationOriginKind.DEFINED,
componentVariable, irComponentCall)
irBlock.addStatement(irComponentVar)
}
return irBlock
}
override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement {
@@ -273,16 +277,19 @@ class StatementGenerator(
BranchingExpressionGenerator(this).generateWhenExpression(expression)
override fun visitWhileExpression(expression: KtWhileExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateWhileExpression(expression)
LoopExpressionGenerator(this).generateWhileLoop(expression)
override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateDoWhileExpression(expression)
LoopExpressionGenerator(this).generateDoWhileLoop(expression)
override fun visitForExpression(expression: KtForExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateForLoop(expression)
override fun visitBreakExpression(expression: KtBreakExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateBreakExpression(expression)
LoopExpressionGenerator(this).generateBreak(expression)
override fun visitContinueExpression(expression: KtContinueExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateContinueExpression(expression)
LoopExpressionGenerator(this).generateContinue(expression)
}
@@ -0,0 +1,26 @@
/*
* 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.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.types.KotlinType
class TransientReceiverValue(val description: String, override val type: KotlinType?): IntermediateValue {
override fun load(): IrExpression {
throw AssertionError("Transient receiver should not be instantiated: $description")
}
}
@@ -76,6 +76,11 @@ interface IrOperator {
object WHEN_COMMA : IrOperatorImpl("WHEN_COMMA")
object WHILE_LOOP : IrOperatorImpl("WHILE_LOOP")
object DO_WHILE_LOOP : IrOperatorImpl("DO_WHILE_LOOP")
object FOR_LOOP : IrOperatorImpl("FOR_LOOP")
object FOR_LOOP_ITERATOR : IrOperatorImpl("FOR_LOOP_ITERATOR")
object FOR_LOOP_INNER_WHILE : IrOperatorImpl("FOR_LOOP_INNER_WHILE")
object FOR_LOOP_HAS_NEXT : IrOperatorImpl("FOR_LOOP_HAS_NEXT")
object FOR_LOOP_NEXT : IrOperatorImpl("FOR_LOOP_NEXT")
data class COMPONENT_N private constructor(val index: Int) : IrOperatorImpl("COMPONENT_$index") {
companion object {
+13
View File
@@ -0,0 +1,13 @@
fun testIterable(ss: List<String>) {
for (s in ss) {
println(s)
}
}
fun testDestructuring(pp: List<Pair<Int, String>>) {
for ((i, s) in pp) {
println(i)
println(s)
}
}
+43
View File
@@ -0,0 +1,43 @@
IrFile /for.kt
IrFunction public fun testIterable(/*0*/ ss: kotlin.collections.List<kotlin.String>): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp0_iterator: kotlin.collections.Iterator<kotlin.String>
CALL .iterator type=kotlin.collections.Iterator<kotlin.String> operator=FOR_LOOP_ITERATOR
$this: GET_VAR ss type=kotlin.collections.List<kotlin.String> operator=null
WHILE 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<kotlin.String> operator=null
body: BLOCK type=kotlin.Unit hasResult=false 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<kotlin.String> operator=null
BLOCK type=<no-type> hasResult=false operator=null
CALL .println type=kotlin.Unit operator=null
message: GET_VAR s type=kotlin.String operator=null
IrFunction public fun testDestructuring(/*0*/ pp: kotlin.collections.List<kotlin.Pair<kotlin.Int, kotlin.String>>): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp0_iterator: kotlin.collections.Iterator<kotlin.Pair<kotlin.Int, kotlin.String>>
CALL .iterator type=kotlin.collections.Iterator<kotlin.Pair<kotlin.Int, kotlin.String>> operator=FOR_LOOP_ITERATOR
$this: GET_VAR pp type=kotlin.collections.List<kotlin.Pair<kotlin.Int, kotlin.String>> operator=null
WHILE 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<kotlin.Pair<kotlin.Int, kotlin.String>> operator=null
body: BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP_INNER_WHILE
VAR val tmp1_loop_parameter: kotlin.Pair<kotlin.Int, kotlin.String>
CALL .next type=kotlin.Pair<kotlin.Int, kotlin.String> operator=FOR_LOOP_NEXT
$this: GET_VAR tmp0_iterator type=kotlin.collections.Iterator<kotlin.Pair<kotlin.Int, kotlin.String>> operator=null
VAR val i: kotlin.Int
CALL .component1 type=kotlin.Int operator=COMPONENT_N(index=1)
$this: GET_VAR tmp1_loop_parameter type=kotlin.Pair<kotlin.Int, kotlin.String> operator=null
VAR val s: kotlin.String
CALL .component2 type=kotlin.String operator=COMPONENT_N(index=2)
$this: GET_VAR tmp1_loop_parameter type=kotlin.Pair<kotlin.Int, kotlin.String> operator=null
BLOCK type=<no-type> hasResult=false operator=null
CALL .println type=kotlin.Unit operator=null
message: GET_VAR i type=kotlin.Int operator=null
CALL .println type=kotlin.Unit operator=null
message: GET_VAR s type=kotlin.String operator=null
+33
View File
@@ -0,0 +1,33 @@
fun testForBreak1(ss: List<String>) {
for (s in ss) {
break
}
}
fun testForBreak2(ss: List<String>) {
OUTER@for (s1 in ss) {
INNER@for (s2 in ss) {
break@OUTER
break@INNER
break
}
break@OUTER
}
}
fun testForContinue1(ss: List<String>) {
for (s in ss) {
continue
}
}
fun testForContinue2(ss: List<String>) {
OUTER@for (s1 in ss) {
INNER@for (s2 in ss) {
continue@OUTER
continue@INNER
continue
}
continue@OUTER
}
}
+95
View File
@@ -0,0 +1,95 @@
IrFile /forWithBreakContinue.kt
IrFunction public fun testForBreak1(/*0*/ ss: kotlin.collections.List<kotlin.String>): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp0_iterator: kotlin.collections.Iterator<kotlin.String>
CALL .iterator type=kotlin.collections.Iterator<kotlin.String> operator=FOR_LOOP_ITERATOR
$this: GET_VAR ss type=kotlin.collections.List<kotlin.String> operator=null
WHILE 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<kotlin.String> operator=null
body: BLOCK type=kotlin.Unit hasResult=false 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<kotlin.String> operator=null
BLOCK type=<no-type> hasResult=false operator=null
BREAK loop.operator=FOR_LOOP_INNER_WHILE depth=0
IrFunction public fun testForBreak2(/*0*/ ss: kotlin.collections.List<kotlin.String>): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp0_iterator: kotlin.collections.Iterator<kotlin.String>
CALL .iterator type=kotlin.collections.Iterator<kotlin.String> operator=FOR_LOOP_ITERATOR
$this: GET_VAR ss type=kotlin.collections.List<kotlin.String> operator=null
WHILE 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<kotlin.String> operator=null
body: BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP_INNER_WHILE
VAR val s1: kotlin.String
CALL .next type=kotlin.String operator=FOR_LOOP_NEXT
$this: GET_VAR tmp0_iterator type=kotlin.collections.Iterator<kotlin.String> operator=null
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp1_iterator: kotlin.collections.Iterator<kotlin.String>
CALL .iterator type=kotlin.collections.Iterator<kotlin.String> operator=FOR_LOOP_ITERATOR
$this: GET_VAR ss type=kotlin.collections.List<kotlin.String> operator=null
WHILE operator=FOR_LOOP_INNER_WHILE
condition: CALL .hasNext type=kotlin.Boolean operator=FOR_LOOP_HAS_NEXT
$this: GET_VAR tmp1_iterator type=kotlin.collections.Iterator<kotlin.String> operator=null
body: BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP_INNER_WHILE
VAR val s2: kotlin.String
CALL .next type=kotlin.String operator=FOR_LOOP_NEXT
$this: GET_VAR tmp1_iterator type=kotlin.collections.Iterator<kotlin.String> operator=null
BLOCK type=<no-type> hasResult=false operator=null
BREAK loop.operator=FOR_LOOP_INNER_WHILE depth=1
BREAK loop.operator=FOR_LOOP_INNER_WHILE depth=0
BREAK loop.operator=FOR_LOOP_INNER_WHILE depth=0
BREAK loop.operator=FOR_LOOP_INNER_WHILE depth=0
IrFunction public fun testForContinue1(/*0*/ ss: kotlin.collections.List<kotlin.String>): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp0_iterator: kotlin.collections.Iterator<kotlin.String>
CALL .iterator type=kotlin.collections.Iterator<kotlin.String> operator=FOR_LOOP_ITERATOR
$this: GET_VAR ss type=kotlin.collections.List<kotlin.String> operator=null
WHILE 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<kotlin.String> operator=null
body: BLOCK type=kotlin.Unit hasResult=false 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<kotlin.String> operator=null
BLOCK type=<no-type> hasResult=false operator=null
CONTINUE loop.operator=FOR_LOOP_INNER_WHILE depth=0
IrFunction public fun testForContinue2(/*0*/ ss: kotlin.collections.List<kotlin.String>): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp0_iterator: kotlin.collections.Iterator<kotlin.String>
CALL .iterator type=kotlin.collections.Iterator<kotlin.String> operator=FOR_LOOP_ITERATOR
$this: GET_VAR ss type=kotlin.collections.List<kotlin.String> operator=null
WHILE 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<kotlin.String> operator=null
body: BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP_INNER_WHILE
VAR val s1: kotlin.String
CALL .next type=kotlin.String operator=FOR_LOOP_NEXT
$this: GET_VAR tmp0_iterator type=kotlin.collections.Iterator<kotlin.String> operator=null
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp1_iterator: kotlin.collections.Iterator<kotlin.String>
CALL .iterator type=kotlin.collections.Iterator<kotlin.String> operator=FOR_LOOP_ITERATOR
$this: GET_VAR ss type=kotlin.collections.List<kotlin.String> operator=null
WHILE operator=FOR_LOOP_INNER_WHILE
condition: CALL .hasNext type=kotlin.Boolean operator=FOR_LOOP_HAS_NEXT
$this: GET_VAR tmp1_iterator type=kotlin.collections.Iterator<kotlin.String> operator=null
body: BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP_INNER_WHILE
VAR val s2: kotlin.String
CALL .next type=kotlin.String operator=FOR_LOOP_NEXT
$this: GET_VAR tmp1_iterator type=kotlin.collections.Iterator<kotlin.String> operator=null
BLOCK type=<no-type> hasResult=false operator=null
CONTINUE loop.operator=FOR_LOOP_INNER_WHILE depth=1
CONTINUE loop.operator=FOR_LOOP_INNER_WHILE depth=0
CONTINUE loop.operator=FOR_LOOP_INNER_WHILE depth=0
CONTINUE loop.operator=FOR_LOOP_INNER_WHILE depth=0
+15
View File
@@ -0,0 +1,15 @@
object FiveTimes
class IntCell(var value: Int)
interface IReceiver {
operator fun FiveTimes.iterator() = IntCell(5)
operator fun IntCell.hasNext() = value > 0
operator fun IntCell.next() = value--
}
fun IReceiver.test() {
for (i in FiveTimes) {
println(i)
}
}
@@ -0,0 +1,24 @@
IrFile /forWithImplicitReceivers.kt
DUMMY FiveTimes
DUMMY IntCell
DUMMY IReceiver
IrFunction public fun IReceiver.test(): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false operator=null
BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP
VAR val tmp0_iterator: IntCell
CALL .iterator type=IntCell operator=FOR_LOOP_ITERATOR
$this: $RECEIVER of: test type=IReceiver
$receiver: GET_OBJECT FiveTimes type=FiveTimes
WHILE operator=FOR_LOOP_INNER_WHILE
condition: CALL .hasNext type=kotlin.Boolean operator=FOR_LOOP_HAS_NEXT
$this: $RECEIVER of: test type=IReceiver
$receiver: GET_VAR tmp0_iterator type=IntCell operator=null
body: BLOCK type=kotlin.Unit hasResult=false operator=FOR_LOOP_INNER_WHILE
VAR val i: kotlin.Int
CALL .next type=kotlin.Int operator=FOR_LOOP_NEXT
$this: $RECEIVER of: test type=IReceiver
$receiver: GET_VAR tmp0_iterator type=IntCell operator=null
BLOCK type=<no-type> hasResult=false operator=null
CALL .println type=kotlin.Unit operator=null
message: GET_VAR i type=kotlin.Int operator=null
@@ -137,6 +137,24 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
@TestMetadata("for.kt")
public void testFor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/for.kt");
doTest(fileName);
}
@TestMetadata("forWithBreakContinue.kt")
public void testForWithBreakContinue() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/forWithBreakContinue.kt");
doTest(fileName);
}
@TestMetadata("forWithImplicitReceivers.kt")
public void testForWithImplicitReceivers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/forWithImplicitReceivers.kt");
doTest(fileName);
}
@TestMetadata("identity.kt")
public void testIdentity() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/identity.kt");