From dd65e0876f43d0cc584df7f02dd4f9e2c2894060 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Tue, 2 Apr 2019 10:12:55 -0700 Subject: [PATCH] Simplify loop building by encoding open/closed bound information in the HeaderInfo object, and modifying the operator in the loop condition. The "additional emptiness condition" is no longer necessary with this. The open/closed property was removed from HeaderInfo in an earlier commit, but bringing it back in to simplify the loop building makes more sense. Also expanded tests for evaluation order of range bounds. --- .../common/lower/loops/ForLoopsLowering.kt | 55 +++-- .../backend/common/lower/loops/HeaderInfo.kt | 12 +- .../common/lower/loops/HeaderProcessor.kt | 191 ++++++++++-------- .../common/lower/loops/ProgressionHandlers.kt | 105 ++-------- .../forInDownToEvaluationOrder.kt | 21 ++ .../forInRangeLiteralEvaluationOrder.kt} | 10 +- .../forInReversedDownToEvaluationOrder.kt | 10 +- ...orInReversedRangeLiteralEvaluationOrder.kt | 21 ++ .../forInReversedUntilEvaluationOrder.kt | 10 +- .../forInUntilEvaluationOrder.kt | 21 ++ .../bytecodeText/forLoop/forInUntil.kt | 4 +- .../codegen/BlackBoxCodegenTestGenerated.java | 71 ++++--- .../LightAnalysisModeTestGenerated.java | 71 ++++--- .../ir/IrBlackBoxCodegenTestGenerated.java | 71 ++++--- .../IrJsCodegenBoxTestGenerated.java | 71 ++++--- .../semantics/JsCodegenBoxTestGenerated.java | 71 ++++--- 16 files changed, 454 insertions(+), 361 deletions(-) create mode 100644 compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt rename compiler/testData/codegen/box/ranges/{forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt => evaluationOrder/forInRangeLiteralEvaluationOrder.kt} (57%) rename compiler/testData/codegen/box/ranges/{forInReversed => }/evaluationOrder/forInReversedDownToEvaluationOrder.kt (57%) create mode 100644 compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt rename compiler/testData/codegen/box/ranges/{forInReversed => }/evaluationOrder/forInReversedUntilEvaluationOrder.kt (57%) create mode 100644 compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ForLoopsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ForLoopsLowering.kt index 43c956facff..017bda71673 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ForLoopsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ForLoopsLowering.kt @@ -41,48 +41,59 @@ val forLoopsPhase = makeIrFilePhase( * * For example, this loop: * ``` - * for (i in first..last) { // Do something with i } + * for (loopVar in A..B) { // Loop body } * ``` * is represented in IR in such a manner: * ``` - * val it = (first..last).iterator() + * val it = (A..B).iterator() * while (it.hasNext()) { - * val i = it.next() - * // Do something with i + * val loopVar = it.next() + * // Loop body * } * ``` * We transform it into one of the following loops: * * ``` - * // 1. If the induction variable cannot overflow, i.e., `last` is const and != MAX_VALUE (if increasing, or MIN_VALUE if decreasing), - * // OR if loop is an until loop (e.g., `for (i in first until last)`): + * // 1. If the induction variable cannot overflow, i.e., `B` is const and != MAX_VALUE (if increasing, or MIN_VALUE if decreasing). * - * var inductionVar = first - * while (inductionVar <= last) { // (inductionVar >= last if the progression is decreasing) - * val i = inductionVar - * inductionVar++ - * // Do something with i + * var inductionVar = A + * var last = B + * while (inductionVar <= last) { // (`inductionVar >= last` if the progression is decreasing) + * val loopVar = inductionVar + * inductionVar++ // (`inductionVar--` if the progression is decreasing) + * // Loop body * } * * // 2. If the induction variable CAN overflow, i.e., `last` is not const or is MAX/MIN_VALUE: * - * var inductionVar = first - * if (inductionVar <= last) { // (inductionVar >= last if the progression is decreasing) + * var inductionVar = A + * var last = B + * if (inductionVar <= last) { // (`inductionVar >= last` if the progression is decreasing) * // Loop is not empty * do { - * val i = inductionVar - * inductionVar++ - * // Do something with i - * } while (i != last) + * val loopVar = inductionVar + * inductionVar++ // (`inductionVar--` if the progression is decreasing) + * // Loop body + * } while (loopVar != last) + * } + * + * // 3. If loop is an until loop (e.g., `for (i in A until B)`), it cannot overflow and we use `<` for comparisons: + * + * var inductionVar = A + * var last = B + * while (inductionVar < last) { + * val loopVar = inductionVar + * inductionVar++ + * // Loop body * } * ``` - * In case of iteration over an array, we transform it into the following: + * In case of iteration over an array (e.g., `for (i in array)`), we transform it into the following: * ``` * var inductionVar = 0 - * val last = array.size - 1 - * while (inductionVar <= last) { - * val i = array[inductionVar++] - * // Do something with i + * val last = array.size + * while (inductionVar < last) { + * val loopVar = array[inductionVar++] + * // Loop body * } * ``` */ diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt index fd0b1418ee0..aa5e03dcf99 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt @@ -61,7 +61,8 @@ internal sealed class HeaderInfo( val progressionType: ProgressionType, val first: IrExpression, val last: IrExpression, - val step: IrExpression + val step: IrExpression, + val isLastInclusive: Boolean ) { val direction: ProgressionDirection by lazy { // If step is a constant (either Int or Long), then we can determine the direction. @@ -82,10 +83,10 @@ internal class ProgressionHeaderInfo( first: IrExpression, last: IrExpression, step: IrExpression, + isLastInclusive: Boolean = true, canOverflow: Boolean? = null, - val additionalVariables: List = listOf(), - val additionalNotEmptyCondition: IrExpression? = null -) : HeaderInfo(progressionType, first, last, step) { + val additionalVariables: List = listOf() +) : HeaderInfo(progressionType, first, last, step, isLastInclusive) { private val _canOverflow: Boolean? = canOverflow val canOverflow: Boolean by lazy { @@ -129,7 +130,8 @@ internal class ArrayHeaderInfo( ProgressionType.INT_PROGRESSION, first, last, - step + step, + isLastInclusive = false ) /** Matches a call to `iterator()` and builds a [HeaderInfo] out of the call's context. */ diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt index 43d7ef15fbc..9040fa63d7d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt @@ -26,10 +26,10 @@ import org.jetbrains.kotlin.name.Name /** Contains information about variables used in the loop. */ internal sealed class ForLoopHeader( + protected open val headerInfo: HeaderInfo, val inductionVariable: IrVariable, val last: IrVariable, val step: IrVariable, - val progressionType: ProgressionType, var loopVariable: IrVariable? = null ) { /** Expression used to initialize the loop variable at the beginning of the loop. */ @@ -48,26 +48,98 @@ internal sealed class ForLoopHeader( * Returns null if no check is needed for the for-loop. */ abstract fun buildNotEmptyConditionIfNecessary(builder: DeclarationIrBuilder): IrExpression? + + protected fun buildLoopCondition(builder: DeclarationIrBuilder): IrExpression = + with(builder) { + val builtIns = context.irBuiltIns + val progressionType = headerInfo.progressionType + val progressionKotlinType = progressionType.elementType(builtIns).toKotlinType() + val compFun = + if (headerInfo.isLastInclusive) builtIns.lessOrEqualFunByOperandType[progressionKotlinType]!! + else builtIns.lessFunByOperandType[progressionKotlinType]!! + + // The default condition depends on the direction. + return when (headerInfo.direction) { + ProgressionDirection.DECREASING -> + // last <= inductionVar (use `<` if last is exclusive) + irCall(compFun).apply { + putValueArgument(0, irGet(last)) + putValueArgument(1, irGet(inductionVariable)) + } + ProgressionDirection.INCREASING -> + // inductionVar <= last (use `<` if last is exclusive) + irCall(compFun).apply { + putValueArgument(0, irGet(inductionVariable)) + putValueArgument(1, irGet(last)) + } + ProgressionDirection.UNKNOWN -> { + // If the direction is unknown, we check depending on the "step" value: + // // (use `<` if last is exclusive) + // (step > 0 && inductionVar <= last) || (step < 0 || last <= inductionVar) + val stepKotlinType = progressionType.stepType(builtIns).toKotlinType() + val zero = if (progressionType == ProgressionType.LONG_PROGRESSION) irLong(0) else irInt(0) + context.oror( + context.andand( + irCall(builtIns.greaterFunByOperandType[stepKotlinType]!!).apply { + putValueArgument(0, irGet(step)) + putValueArgument(1, zero) + }, + irCall(compFun).apply { + putValueArgument(0, irGet(inductionVariable)) + putValueArgument(1, irGet(last)) + }), + context.andand( + irCall(builtIns.lessFunByOperandType[stepKotlinType]!!).apply { + putValueArgument(0, irGet(step)) + putValueArgument(1, zero) + }, + irCall(compFun).apply { + putValueArgument(0, irGet(last)) + putValueArgument(1, irGet(inductionVariable)) + }) + ) + } + } + } } internal class ProgressionLoopHeader( - private val headerInfo: ProgressionHeaderInfo, + override val headerInfo: ProgressionHeaderInfo, inductionVariable: IrVariable, last: IrVariable, step: IrVariable -) : ForLoopHeader(inductionVariable, last, step, headerInfo.progressionType) { +) : ForLoopHeader(headerInfo, inductionVariable, last, step) { override fun initializeLoopVariable(symbols: Symbols, builder: DeclarationIrBuilder) = with(builder) { // loopVariable = inductionVariable irGet(inductionVariable) } + // For this loop: + // + // for (i in first()..last() step step()) + // + // ...the functions may have side-effects so we need to call them in the following order: first() (inductionVariable), last(), step(). + // Additional variables come first as they may be needed to the subsequent variables. override val declarations: List get() = headerInfo.additionalVariables + listOf(inductionVariable, last, step) override fun buildInnerLoop(builder: DeclarationIrBuilder, loop: IrLoop, newBody: IrExpression?): IrLoop = with(builder) { if (headerInfo.canOverflow) { - // Condition: loopVariable != last. We cannot use the induction variable because it can overflow. + // If the induction variable CAN overflow, we cannot use it in the loop condition. Loop is lowered into something like: + // + // var inductionVar = A + // var last = B + // if (inductionVar <= last) { + // // Loop is not empty + // do { + // val loopVar = inductionVar + // inductionVar++ + // // Loop body + // } while (loopVar != last) + // } + // + // The `if (inductionVar <= last)` "not empty" check is added in buildNotEmptyConditionIfNecessary(). assert(loopVariable != null) val booleanNotFun = context.irBuiltIns.booleanClass.functions.first { it.owner.name.asString() == "not" } val newCondition = irCallOp(booleanNotFun, booleanNotFun.owner.returnType, irCall(context.irBuiltIns.eqeqSymbol).apply { @@ -80,85 +152,38 @@ internal class ProgressionLoopHeader( body = newBody } } else { - // If the induction variable cannot overflow, use a while loop using the "not empty" condition. - val newCondition = buildNotEmptyCondition(this@with) + // If the induction variable can NOT overflow, use a simple while loop. Loop is lowered into something like: + // + // var inductionVar = A + // var last = B + // while (inductionVar <= last) { + // val loopVar = inductionVar + // inductionVar++ + // // Loop body + // } IrWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, loop.origin).apply { label = loop.label - condition = newCondition + condition = buildLoopCondition(this@with) body = newBody } } } - // If the induction variable cannot overflow, we do NOT need the enclosing "not empty" check because the for-loop is lowered into a - // while loop that uses the "not empty" condition (see buildInnerLoop()); the enclosing check would be redundant. + // If the induction variable can NOT overflow, we do NOT need the enclosing "not empty" check because the for-loop is lowered into a + // simple while loop (see buildInnerLoop()); the enclosing check would be redundant. override fun buildNotEmptyConditionIfNecessary(builder: DeclarationIrBuilder): IrExpression? = - if (headerInfo.canOverflow) buildNotEmptyCondition(builder) else null - - private fun buildNotEmptyCondition(builder: DeclarationIrBuilder): IrExpression = - with(builder) { - val builtIns = context.irBuiltIns - val progressionKotlinType = progressionType.elementType(builtIns).toKotlinType() - val lessOrEqualFun = builtIns.lessOrEqualFunByOperandType[progressionKotlinType]!! - - // The default "not empty" condition depends on the direction. - val notEmptyCondition = when (headerInfo.direction) { - ProgressionDirection.DECREASING -> - // last <= inductionVariable - irCall(lessOrEqualFun).apply { - putValueArgument(0, irGet(last)) - putValueArgument(1, irGet(inductionVariable)) - } - ProgressionDirection.INCREASING -> - // inductionVariable <= last - irCall(lessOrEqualFun).apply { - putValueArgument(0, irGet(inductionVariable)) - putValueArgument(1, irGet(last)) - } - ProgressionDirection.UNKNOWN -> { - // If the direction is unknown, we check depending on the "step" value: - // (step > 0 && inductionVariable <= last) || (step < 0 || last <= inductionVariable) - val stepKotlinType = progressionType.stepType(builtIns).toKotlinType() - val zero = if (progressionType == ProgressionType.LONG_PROGRESSION) irLong(0) else irInt(0) - context.oror( - context.andand( - irCall(builtIns.greaterFunByOperandType[stepKotlinType]!!).apply { - putValueArgument(0, irGet(step)) - putValueArgument(1, zero) - }, - irCall(lessOrEqualFun).apply { - putValueArgument(0, irGet(inductionVariable)) - putValueArgument(1, irGet(last)) - }), - context.andand( - irCall(builtIns.lessFunByOperandType[stepKotlinType]!!).apply { - putValueArgument(0, irGet(step)) - putValueArgument(1, zero) - }, - irCall(lessOrEqualFun).apply { - putValueArgument(0, irGet(last)) - putValueArgument(1, irGet(inductionVariable)) - }) - ) - } - } - - if (headerInfo.additionalNotEmptyCondition != null) context.andand( - headerInfo.additionalNotEmptyCondition, - notEmptyCondition - ) else notEmptyCondition - } + if (headerInfo.canOverflow) buildLoopCondition(builder) else null } internal class ArrayLoopHeader( - private val headerInfo: ArrayHeaderInfo, + override val headerInfo: ArrayHeaderInfo, inductionVariable: IrVariable, last: IrVariable, step: IrVariable -) : ForLoopHeader(inductionVariable, last, step, ProgressionType.INT_PROGRESSION) { +) : ForLoopHeader(headerInfo, inductionVariable, last, step) { override fun initializeLoopVariable(symbols: Symbols, builder: DeclarationIrBuilder) = with(builder) { - // loopVariable = array[inductionVariable] + // inductionVar = loopVar[inductionVariable] val arrayGetFun = headerInfo.arrayVariable.type.getClass()!!.functions.first { it.name.asString() == "get" } irCall(arrayGetFun).apply { dispatchReceiver = irGet(headerInfo.arrayVariable) @@ -170,17 +195,18 @@ internal class ArrayLoopHeader( get() = listOf(headerInfo.arrayVariable, inductionVariable, last, step) override fun buildInnerLoop(builder: DeclarationIrBuilder, loop: IrLoop, newBody: IrExpression?): IrLoop = with(builder) { - // Condition: inductionVariable != last - val builtIns = context.irBuiltIns - val callee = builtIns.lessOrEqualFunByOperandType[builtIns.int]!! - val newCondition = irCall(callee).apply { - putValueArgument(0, irGet(inductionVariable)) - putValueArgument(1, irGet(last)) - } - + // Loop is lowered into something like: + // + // var inductionVar = 0 + // var last = array.size + // while (inductionVar < last) { + // val loopVar = array[inductionVar++] + // inductionVar++ + // // Loop body + // } IrWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, loop.origin).apply { label = loop.label - condition = newCondition + condition = buildLoopCondition(this@with) body = newBody } } @@ -224,18 +250,13 @@ internal class HeaderProcessor( with(headerInfo) { // For this loop: // - // ``` - // for (i in first()..last() step step()) - // ``` + // for (i in first()..last() step step()) // - // ...the functions may have side-effects so we need to call them in the following - // order: first(), last(), step(). - // - // We also need to cast them to conform to the progression type so that operations - // in the induction variable within the loop are more efficient. + // We need to cast first(), last(). and step() to conform to the progression type so + // that operations on the induction variable within the loop are more efficient. // // In the above example, if first() is a Long and last() is an Int, this creates a - // LongProgression so last(), should be cast to a Long. + // LongProgression so last() should be cast to a Long. val inductionVariable = scope.createTemporaryVariable( first.castIfNecessary( progressionType.elementType(context.irBuiltIns), diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt index 8c8daf6c330..ad988bfba96 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt @@ -6,23 +6,19 @@ package org.jetbrains.kotlin.backend.common.lower.loops import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.createIrCallMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.builders.irInt import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrConst -import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.toKotlinType -import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.properties import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -80,78 +76,15 @@ internal class UntilHandler(private val context: CommonBackendContext, private v override fun build(call: IrCall, data: ProgressionType): HeaderInfo? = with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) { - val boundArg = call.getValueArgument(0)!! - val bound = ensureNotNullable( - boundArg.castIfNecessary( - data.elementType(context.irBuiltIns), - data.elementCastFunctionName - ) - ) - // `bound` may be needed for an additional condition to the emptiness check (see comments below). If so, store `bound` in a - // temporary variable as it may be an expression with side-effects and we should only evaluate it once. - val boundVar = if (needsMinValueCondition(data, boundArg)) scope.createTemporaryVariable( - bound, - nameHint = "bound", - origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE - ) else null - - // `last = bound - 1` for the loop `for (i in first until bound)`. - val decFun = data.decFun(context.irBuiltIns) - val last = irCallOp(decFun.symbol, bound.type, if (boundVar != null) irGet(boundVar) else bound) - - // The default "not empty" check cannot be used for the corner case: - // - // for (i in a until MIN_VALUE) {} - // - // ...which should always be considered an empty range. When the given bound is MIN_VALUE, and because `last = bound - 1`, - // "last" will underflow to MAX_VALUE, therefore the default "not empty" check: - // - // if (inductionVar <= last) { /* loop */ } - // - // ...will always be true and won't consider the range as empty. Therefore, we need to add an additional condition to the - // "not empty" check so that it becomes: - // - // if (inductionVar <= last && bound > MIN_VALUE) { /* loop */ } ProgressionHeaderInfo( data, first = call.extensionReceiver!!, - last = last, + last = call.getValueArgument(0)!!, step = irInt(1), - canOverflow = false, - additionalVariables = listOfNotNull(boundVar), - additionalNotEmptyCondition = if (boundVar != null) buildMinValueCondition(data, irGet(boundVar)) else null + isLastInclusive = false, + canOverflow = false ) } - - /** Returns true (i.e., min value condition is needed) if `bound` is non-const OR is MIN_VALUE. */ - private fun needsMinValueCondition(progressionType: ProgressionType, bound: IrExpression): Boolean { - val boundValue = (bound as? IrConst<*>)?.value - val boundValueAsLong = when (boundValue) { - is Number -> boundValue.toLong() - is Char -> boundValue.toLong() - else -> return true // If "bound" is not a const Number or Char. - } - val minValueAsLong = when (progressionType) { - ProgressionType.INT_PROGRESSION -> Int.MIN_VALUE.toLong() - ProgressionType.CHAR_PROGRESSION -> Char.MIN_VALUE.toLong() - ProgressionType.LONG_PROGRESSION -> Long.MIN_VALUE - } - return minValueAsLong == boundValueAsLong - } - - private fun DeclarationIrBuilder.buildMinValueCondition(progressionType: ProgressionType, bound: IrExpression): IrExpression { - val irBuiltIns = context.irBuiltIns - val minConst = when (progressionType) { - ProgressionType.INT_PROGRESSION -> irInt(Int.MIN_VALUE) - ProgressionType.CHAR_PROGRESSION -> irChar(Char.MIN_VALUE) - ProgressionType.LONG_PROGRESSION -> irLong(Long.MIN_VALUE) - } - val progressionKotlinType = progressionType.elementType(irBuiltIns).toKotlinType() - return irCall(irBuiltIns.greaterFunByOperandType[progressionKotlinType]!!).apply { - putValueArgument(0, bound) - putValueArgument(1, minConst) - } - } } /** Builds a [HeaderInfo] for progressions built using the `indices` extension property. */ @@ -167,18 +100,18 @@ internal class IndicesHandler(val context: CommonBackendContext) : ProgressionHa override fun build(call: IrCall, data: ProgressionType): HeaderInfo? = with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) { - // `last = array.size - 1` for the loop `for (i in array.indices)`. + // `last = array.size` for the loop `for (i in array.indices)`. val arraySizeProperty = call.extensionReceiver!!.type.getClass()!!.properties.first { it.name.asString() == "size" } - val decFun = data.decFun(context.irBuiltIns) - val last = irCallOp(decFun.symbol, data.elementType(context.irBuiltIns), irCall(arraySizeProperty.getter!!).apply { + val last = irCall(arraySizeProperty.getter!!).apply { dispatchReceiver = call.extensionReceiver - }) + } ProgressionHeaderInfo( data, first = irInt(0), last = last, step = irInt(1), + isLastInclusive = false, canOverflow = false // Cannot overflow because `last` is at most MAX_VALUE - 1 ) } @@ -225,8 +158,6 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte /** Builds a [HeaderInfo] for arrays. */ internal class ArrayIterationHandler(private val context: CommonBackendContext) : HeaderInfoHandler { - private val intDecFun = ProgressionType.INT_PROGRESSION.decFun(context.irBuiltIns) - override val matcher = createIrCallMatcher { origin { it == IrStatementOrigin.FOR_LOOP_ITERATOR } // TODO: Support rare cases like `T : IntArray` @@ -255,11 +186,11 @@ internal class ArrayIterationHandler(private val context: CommonBackendContext) origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE ) - // `last = array.size - 1` for the loop `for (i in array.indices)`. + // `last = array.size` for the loop `for (i in array.indices)`. val arraySizeProperty = arrayReference.type.getClass()!!.properties.first { it.name.asString() == "size" } - val last = irCallOp(intDecFun.symbol, context.irBuiltIns.intType, irCall(arraySizeProperty.getter!!).apply { + val last = irCall(arraySizeProperty.getter!!).apply { dispatchReceiver = irGet(arrayReference) - }) + } ArrayHeaderInfo( first = irInt(0), @@ -268,14 +199,4 @@ internal class ArrayIterationHandler(private val context: CommonBackendContext) arrayVariable = arrayReference ) } -} - -private fun ProgressionType.decFun(builtIns: IrBuiltIns): IrFunction { - val symbol = - when (this) { - ProgressionType.INT_PROGRESSION -> builtIns.intClass - ProgressionType.LONG_PROGRESSION -> builtIns.longClass - ProgressionType.CHAR_PROGRESSION -> builtIns.charClass - } - return symbol.owner.functions.first { it.name.asString() == "dec" } } \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt b/compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt new file mode 100644 index 00000000000..d4d195a083f --- /dev/null +++ b/compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt @@ -0,0 +1,21 @@ +// KJS_WITH_FULL_RUNTIME +// WITH_RUNTIME +import kotlin.test.* + +val log = StringBuilder() + +fun logged(message: String, value: Int) = + value.also { log.append(message) } + +fun box(): String { + var sum = 0 + for (i in logged("start;", 4) downTo logged("end;", 1)) { + sum = sum * 10 + i + } + + assertEquals(4321, sum) + + assertEquals("start;end;", log.toString()) + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt b/compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt similarity index 57% rename from compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt rename to compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt index 1b816de9394..fae58fac6ae 100644 --- a/compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt +++ b/compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt @@ -5,15 +5,15 @@ import kotlin.test.* val log = StringBuilder() fun logged(message: String, value: Int) = - value.also { log.append(message) } + value.also { log.append(message) } fun box(): String { - var s = 0 - for (i in (logged("start;", 1) .. logged("end;", 2)).reversed()) { - s += i + var sum = 0 + for (i in logged("start;", 1)..logged("end;", 4)) { + sum = sum * 10 + i } - assertEquals(3, s) + assertEquals(1234, sum) assertEquals("start;end;", log.toString()) diff --git a/compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedDownToEvaluationOrder.kt b/compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt similarity index 57% rename from compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedDownToEvaluationOrder.kt rename to compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt index 010af21f1d5..fad30bf9921 100644 --- a/compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedDownToEvaluationOrder.kt +++ b/compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt @@ -5,15 +5,15 @@ import kotlin.test.* val log = StringBuilder() fun logged(message: String, value: Int) = - value.also { log.append(message) } + value.also { log.append(message) } fun box(): String { - var s = 0 - for (i in (logged("start;", 2) downTo logged("end;", 1)).reversed()) { - s += i + var sum = 0 + for (i in (logged("start;", 4) downTo logged("end;", 1)).reversed()) { + sum = sum * 10 + i } - assertEquals(3, s) + assertEquals(1234, sum) assertEquals("start;end;", log.toString()) diff --git a/compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt b/compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt new file mode 100644 index 00000000000..09b90f3f3e0 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt @@ -0,0 +1,21 @@ +// KJS_WITH_FULL_RUNTIME +// WITH_RUNTIME +import kotlin.test.* + +val log = StringBuilder() + +fun logged(message: String, value: Int) = + value.also { log.append(message) } + +fun box(): String { + var sum = 0 + for (i in (logged("start;", 1)..logged("end;", 4)).reversed()) { + sum = sum * 10 + i + } + + assertEquals(4321, sum) + + assertEquals("start;end;", log.toString()) + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedUntilEvaluationOrder.kt b/compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt similarity index 57% rename from compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedUntilEvaluationOrder.kt rename to compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt index 0dac73ca202..2e1eb651377 100644 --- a/compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedUntilEvaluationOrder.kt +++ b/compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt @@ -5,15 +5,15 @@ import kotlin.test.* val log = StringBuilder() fun logged(message: String, value: Int) = - value.also { log.append(message) } + value.also { log.append(message) } fun box(): String { - var s = 0 - for (i in (logged("start;", 1) until logged("end;", 3)).reversed()) { - s += i + var sum = 0 + for (i in (logged("start;", 1) until logged("end;", 5)).reversed()) { + sum = sum * 10 + i } - assertEquals(3, s) + assertEquals(4321, sum) assertEquals("start;end;", log.toString()) diff --git a/compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt b/compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt new file mode 100644 index 00000000000..8864b09d443 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt @@ -0,0 +1,21 @@ +// KJS_WITH_FULL_RUNTIME +// WITH_RUNTIME +import kotlin.test.* + +val log = StringBuilder() + +fun logged(message: String, value: Int) = + value.also { log.append(message) } + +fun box(): String { + var sum = 0 + for (i in logged("start;", 1) until logged("end;", 5)) { + sum = sum * 10 + i + } + + assertEquals(1234, sum) + + assertEquals("start;end;", log.toString()) + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil.kt index bd08b8fc554..4ea36ceec8b 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil.kt @@ -1,6 +1,6 @@ -fun test(): Int { +fun test(a: Int, b: Int): Int { var sum = 0 - for (i in 1 until 6) { + for (i in a until b) { sum = sum * 10 + i } return sum diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d20f74cbe70..7c6f993bee7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -18583,6 +18583,49 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/ranges/evaluationOrder") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EvaluationOrder extends AbstractBlackBoxCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInEvaluationOrder() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("forInDownToEvaluationOrder.kt") + public void testForInDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInRangeLiteralEvaluationOrder.kt") + public void testForInRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedDownToEvaluationOrder.kt") + public void testForInReversedDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") + public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedUntilEvaluationOrder.kt") + public void testForInReversedUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); + } + + @TestMetadata("forInUntilEvaluationOrder.kt") + public void testForInUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/ranges/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -18958,34 +19001,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testForInReversedUntilWithNonConstBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt"); } - - @TestMetadata("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class EvaluationOrder extends AbstractBlackBoxCodegenTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); - } - - public void testAllFilesPresentInEvaluationOrder() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); - } - - @TestMetadata("forInReversedDownToEvaluationOrder.kt") - public void testForInReversedDownToEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") - public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedUntilEvaluationOrder.kt") - public void testForInReversedUntilEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); - } - } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index a27e19e2174..ee5597cf827 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -18583,6 +18583,49 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes } } + @TestMetadata("compiler/testData/codegen/box/ranges/evaluationOrder") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EvaluationOrder extends AbstractLightAnalysisModeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInEvaluationOrder() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("forInDownToEvaluationOrder.kt") + public void testForInDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInRangeLiteralEvaluationOrder.kt") + public void testForInRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedDownToEvaluationOrder.kt") + public void testForInReversedDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") + public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedUntilEvaluationOrder.kt") + public void testForInReversedUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); + } + + @TestMetadata("forInUntilEvaluationOrder.kt") + public void testForInUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/ranges/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -18958,34 +19001,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testForInReversedUntilWithNonConstBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt"); } - - @TestMetadata("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class EvaluationOrder extends AbstractLightAnalysisModeTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); - } - - public void testAllFilesPresentInEvaluationOrder() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); - } - - @TestMetadata("forInReversedDownToEvaluationOrder.kt") - public void testForInReversedDownToEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") - public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedUntilEvaluationOrder.kt") - public void testForInReversedUntilEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); - } - } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 4aed2a0238b..14dea039ed6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -18588,6 +18588,49 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @TestMetadata("compiler/testData/codegen/box/ranges/evaluationOrder") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EvaluationOrder extends AbstractIrBlackBoxCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInEvaluationOrder() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); + } + + @TestMetadata("forInDownToEvaluationOrder.kt") + public void testForInDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInRangeLiteralEvaluationOrder.kt") + public void testForInRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedDownToEvaluationOrder.kt") + public void testForInReversedDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") + public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedUntilEvaluationOrder.kt") + public void testForInReversedUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); + } + + @TestMetadata("forInUntilEvaluationOrder.kt") + public void testForInUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/ranges/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -18963,34 +19006,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testForInReversedUntilWithNonConstBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt"); } - - @TestMetadata("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class EvaluationOrder extends AbstractIrBlackBoxCodegenTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); - } - - public void testAllFilesPresentInEvaluationOrder() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); - } - - @TestMetadata("forInReversedDownToEvaluationOrder.kt") - public void testForInReversedDownToEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") - public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedUntilEvaluationOrder.kt") - public void testForInReversedUntilEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); - } - } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index b2bd8439ad8..cf969dcbf1a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -14643,6 +14643,49 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/ranges/evaluationOrder") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EvaluationOrder extends AbstractIrJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInEvaluationOrder() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); + } + + @TestMetadata("forInDownToEvaluationOrder.kt") + public void testForInDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInRangeLiteralEvaluationOrder.kt") + public void testForInRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedDownToEvaluationOrder.kt") + public void testForInReversedDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") + public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedUntilEvaluationOrder.kt") + public void testForInReversedUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); + } + + @TestMetadata("forInUntilEvaluationOrder.kt") + public void testForInUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/ranges/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -15018,34 +15061,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testForInReversedUntilWithNonConstBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt"); } - - @TestMetadata("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class EvaluationOrder extends AbstractIrJsCodegenBoxTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); - } - - public void testAllFilesPresentInEvaluationOrder() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); - } - - @TestMetadata("forInReversedDownToEvaluationOrder.kt") - public void testForInReversedDownToEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") - public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedUntilEvaluationOrder.kt") - public void testForInReversedUntilEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); - } - } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index ed7824e7348..63112efe47d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -15813,6 +15813,49 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/ranges/evaluationOrder") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EvaluationOrder extends AbstractJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInEvaluationOrder() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("forInDownToEvaluationOrder.kt") + public void testForInDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInRangeLiteralEvaluationOrder.kt") + public void testForInRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedDownToEvaluationOrder.kt") + public void testForInReversedDownToEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") + public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); + } + + @TestMetadata("forInReversedUntilEvaluationOrder.kt") + public void testForInReversedUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); + } + + @TestMetadata("forInUntilEvaluationOrder.kt") + public void testForInUntilEvaluationOrder() throws Exception { + runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/ranges/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -16188,34 +16231,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testForInReversedUntilWithNonConstBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt"); } - - @TestMetadata("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class EvaluationOrder extends AbstractJsCodegenBoxTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInEvaluationOrder() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); - } - - @TestMetadata("forInReversedDownToEvaluationOrder.kt") - public void testForInReversedDownToEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") - public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); - } - - @TestMetadata("forInReversedUntilEvaluationOrder.kt") - public void testForInReversedUntilEvaluationOrder() throws Exception { - runTest("compiler/testData/codegen/box/ranges/forInReversed/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); - } - } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")