'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) }
|
receiver?.let { generateReceiver(ktDefaultElement, receiver) }
|
||||||
|
|
||||||
fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: ReceiverValue): IntermediateValue {
|
fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: ReceiverValue): IntermediateValue {
|
||||||
|
if (receiver is TransientReceiver) {
|
||||||
|
return TransientReceiverValue(ktDefaultElement.text, receiver.type)
|
||||||
|
}
|
||||||
|
|
||||||
val receiverExpression = when (receiver) {
|
val receiverExpression = when (receiver) {
|
||||||
is ImplicitClassReceiver ->
|
is ImplicitClassReceiver ->
|
||||||
IrThisReferenceImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset, receiver.type, receiver.classDescriptor)
|
IrThisReferenceImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset, receiver.type, receiver.classDescriptor)
|
||||||
|
|||||||
+81
-21
@@ -16,44 +16,49 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi2ir.generators
|
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.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
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 {
|
class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope {
|
||||||
override val scope: Scope get() = statementGenerator.scope
|
override val scope: Scope get() = statementGenerator.scope
|
||||||
override val context: GeneratorContext get() = statementGenerator.context
|
override val context: GeneratorContext get() = statementGenerator.context
|
||||||
|
|
||||||
fun generateWhileExpression(expression: KtWhileExpression): IrExpression =
|
fun generateWhileLoop(ktWhile: KtWhileExpression): IrExpression =
|
||||||
generateConditionalLoop(expression, IrWhileLoopImpl(expression.startOffset, expression.endOffset, IrOperator.WHILE_LOOP))
|
generateConditionalLoop(ktWhile, IrWhileLoopImpl(ktWhile.startOffset, ktWhile.endOffset, IrOperator.WHILE_LOOP))
|
||||||
|
|
||||||
fun generateDoWhileExpression(expression: KtDoWhileExpression): IrExpression =
|
fun generateDoWhileLoop(ktDoWhile: KtDoWhileExpression): IrExpression =
|
||||||
generateConditionalLoop(expression, IrDoWhileLoopImpl(expression.startOffset, expression.endOffset, IrOperator.DO_WHILE_LOOP))
|
generateConditionalLoop(ktDoWhile, IrDoWhileLoopImpl(ktDoWhile.startOffset, ktDoWhile.endOffset, IrOperator.DO_WHILE_LOOP))
|
||||||
|
|
||||||
private fun generateConditionalLoop(expression: KtWhileExpressionBase, irLoop: IrLoop): IrLoop {
|
private fun generateConditionalLoop(ktLoop: KtWhileExpressionBase, irLoop: IrLoop): IrLoop {
|
||||||
statementGenerator.expressionBodyGenerator.putLoop(expression, irLoop)
|
statementGenerator.expressionBodyGenerator.putLoop(ktLoop, irLoop)
|
||||||
irLoop.condition = statementGenerator.generateExpression(expression.condition!!)
|
irLoop.condition = statementGenerator.generateExpression(ktLoop.condition!!)
|
||||||
irLoop.body = statementGenerator.generateExpression(expression.body!!)
|
irLoop.body = statementGenerator.generateExpression(ktLoop.body!!)
|
||||||
return irLoop
|
return irLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateBreakExpression(expression: KtBreakExpression): IrExpression {
|
fun generateBreak(ktBreak: KtBreakExpression): IrExpression {
|
||||||
val parentLoop = findParentLoop(expression)
|
val parentLoop = findParentLoop(ktBreak)
|
||||||
return IrBreakImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, parentLoop)
|
return IrBreakImpl(ktBreak.startOffset, ktBreak.endOffset, context.builtIns.nothingType, parentLoop)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateContinueExpression(expression: KtContinueExpression): IrExpression {
|
fun generateContinue(ktContinue: KtContinueExpression): IrExpression {
|
||||||
val parentLoop = findParentLoop(expression)
|
val parentLoop = findParentLoop(ktContinue)
|
||||||
return IrContinueImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, parentLoop)
|
return IrContinueImpl(ktContinue.startOffset, ktContinue.endOffset, context.builtIns.nothingType, parentLoop)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findParentLoop(expression: KtExpressionWithLabel): IrLoop =
|
private fun findParentLoop(ktWithLabel: KtExpressionWithLabel): IrLoop =
|
||||||
findParentLoop(expression, expression.getTargetLabel()?.getReferencedName())
|
findParentLoop(ktWithLabel, ktWithLabel.getTargetLabel()?.getReferencedName())
|
||||||
|
|
||||||
private fun findParentLoop(expression: KtExpression, targetLabel: String?): IrLoop {
|
private fun findParentLoop(ktExpression: KtExpression, targetLabel: String?): IrLoop {
|
||||||
var finger: KtExpression? = expression
|
var finger: KtExpression? = ktExpression
|
||||||
while (finger != null) {
|
while (finger != null) {
|
||||||
finger = finger.getParentOfType<KtLoopExpression>(true)
|
finger = finger.getParentOfType<KtLoopExpression>(true)
|
||||||
if (finger == null) {
|
if (finger == null) {
|
||||||
@@ -75,10 +80,65 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene
|
|||||||
throw AssertionError("No parent loop for break/continue @$targetLabel")
|
throw AssertionError("No parent loop for break/continue @$targetLabel")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLoop(finger: KtLoopExpression): IrLoop {
|
private fun getLoop(ktLoop: KtLoopExpression): IrLoop {
|
||||||
return statementGenerator.expressionBodyGenerator.getLoop(finger) ?:
|
return statementGenerator.expressionBodyGenerator.getLoop(ktLoop) ?:
|
||||||
throw AssertionError("Loop was not visited:\n${finger.text}")
|
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.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
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.createRematerializableOrTemporary
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
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 irBlock = IrBlockImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null, false, IrOperator.SYNTHETIC_BLOCK)
|
||||||
val ktInitializer = multiDeclaration.initializer!!
|
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()) {
|
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
|
||||||
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
|
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
|
||||||
|
|
||||||
val componentSubstitutedCall = pregenerateCall(componentResolvedCall)
|
val componentSubstitutedCall = pregenerateCall(componentResolvedCall)
|
||||||
componentSubstitutedCall.setExplicitReceiverValue(irTmpInitializerValue)
|
componentSubstitutedCall.setExplicitReceiverValue(containerValue)
|
||||||
|
|
||||||
val componentVariable = getOrFail(BindingContext.VARIABLE, ktEntry)
|
val componentVariable = getOrFail(BindingContext.VARIABLE, ktEntry)
|
||||||
val irComponentCall = irCallGenerator.generateCall(ktEntry.startOffset, ktEntry.endOffset, componentSubstitutedCall,
|
val irComponentCall = callGenerator.generateCall(ktEntry.startOffset, ktEntry.endOffset, componentSubstitutedCall,
|
||||||
IrOperator.COMPONENT_N.withIndex(index + 1))
|
IrOperator.COMPONENT_N.withIndex(index + 1))
|
||||||
val irComponentVar = IrVariableImpl(ktEntry.startOffset, ktEntry.endOffset, IrDeclarationOriginKind.DEFINED,
|
val irComponentVar = IrVariableImpl(ktEntry.startOffset, ktEntry.endOffset, IrDeclarationOriginKind.DEFINED,
|
||||||
componentVariable, irComponentCall)
|
componentVariable, irComponentCall)
|
||||||
irBlock.addStatement(irComponentVar)
|
irBlock.addStatement(irComponentVar)
|
||||||
}
|
}
|
||||||
|
|
||||||
return irBlock
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement {
|
override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement {
|
||||||
@@ -273,16 +277,19 @@ class StatementGenerator(
|
|||||||
BranchingExpressionGenerator(this).generateWhenExpression(expression)
|
BranchingExpressionGenerator(this).generateWhenExpression(expression)
|
||||||
|
|
||||||
override fun visitWhileExpression(expression: KtWhileExpression, data: Nothing?): IrStatement =
|
override fun visitWhileExpression(expression: KtWhileExpression, data: Nothing?): IrStatement =
|
||||||
LoopExpressionGenerator(this).generateWhileExpression(expression)
|
LoopExpressionGenerator(this).generateWhileLoop(expression)
|
||||||
|
|
||||||
override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Nothing?): IrStatement =
|
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 =
|
override fun visitBreakExpression(expression: KtBreakExpression, data: Nothing?): IrStatement =
|
||||||
LoopExpressionGenerator(this).generateBreakExpression(expression)
|
LoopExpressionGenerator(this).generateBreak(expression)
|
||||||
|
|
||||||
override fun visitContinueExpression(expression: KtContinueExpression, data: Nothing?): IrStatement =
|
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 WHEN_COMMA : IrOperatorImpl("WHEN_COMMA")
|
||||||
object WHILE_LOOP : IrOperatorImpl("WHILE_LOOP")
|
object WHILE_LOOP : IrOperatorImpl("WHILE_LOOP")
|
||||||
object DO_WHILE_LOOP : IrOperatorImpl("DO_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") {
|
data class COMPONENT_N private constructor(val index: Int) : IrOperatorImpl("COMPONENT_$index") {
|
||||||
companion object {
|
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);
|
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")
|
@TestMetadata("identity.kt")
|
||||||
public void testIdentity() throws Exception {
|
public void testIdentity() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/identity.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/identity.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user