'for'
This commit is contained in:
committed by
Dmitry Petrov
parent
03a666690b
commit
4709aaafaa
@@ -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)
|
||||
|
||||
+81
-21
@@ -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
|
||||
}
|
||||
}
|
||||
+18
-11
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+26
@@ -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 {
|
||||
|
||||
Vendored
+13
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+43
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user