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.
This commit is contained in:
committed by
max-kammerer
parent
7680e7fd56
commit
dd65e0876f
+33
-22
@@ -41,48 +41,59 @@ val forLoopsPhase = makeIrFilePhase(
|
|||||||
*
|
*
|
||||||
* For example, this loop:
|
* 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:
|
* is represented in IR in such a manner:
|
||||||
* ```
|
* ```
|
||||||
* val it = (first..last).iterator()
|
* val it = (A..B).iterator()
|
||||||
* while (it.hasNext()) {
|
* while (it.hasNext()) {
|
||||||
* val i = it.next()
|
* val loopVar = it.next()
|
||||||
* // Do something with i
|
* // Loop body
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
* We transform it into one of the following loops:
|
* 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),
|
* // 1. If the induction variable cannot overflow, i.e., `B` 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)`):
|
|
||||||
*
|
*
|
||||||
* var inductionVar = first
|
* var inductionVar = A
|
||||||
* while (inductionVar <= last) { // (inductionVar >= last if the progression is decreasing)
|
* var last = B
|
||||||
* val i = inductionVar
|
* while (inductionVar <= last) { // (`inductionVar >= last` if the progression is decreasing)
|
||||||
* inductionVar++
|
* val loopVar = inductionVar
|
||||||
* // Do something with i
|
* 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:
|
* // 2. If the induction variable CAN overflow, i.e., `last` is not const or is MAX/MIN_VALUE:
|
||||||
*
|
*
|
||||||
* var inductionVar = first
|
* var inductionVar = A
|
||||||
* if (inductionVar <= last) { // (inductionVar >= last if the progression is decreasing)
|
* var last = B
|
||||||
|
* if (inductionVar <= last) { // (`inductionVar >= last` if the progression is decreasing)
|
||||||
* // Loop is not empty
|
* // Loop is not empty
|
||||||
* do {
|
* do {
|
||||||
* val i = inductionVar
|
* val loopVar = inductionVar
|
||||||
* inductionVar++
|
* inductionVar++ // (`inductionVar--` if the progression is decreasing)
|
||||||
* // Do something with i
|
* // Loop body
|
||||||
* } while (i != last)
|
* } 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
|
* var inductionVar = 0
|
||||||
* val last = array.size - 1
|
* val last = array.size
|
||||||
* while (inductionVar <= last) {
|
* while (inductionVar < last) {
|
||||||
* val i = array[inductionVar++]
|
* val loopVar = array[inductionVar++]
|
||||||
* // Do something with i
|
* // Loop body
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|||||||
+7
-5
@@ -61,7 +61,8 @@ internal sealed class HeaderInfo(
|
|||||||
val progressionType: ProgressionType,
|
val progressionType: ProgressionType,
|
||||||
val first: IrExpression,
|
val first: IrExpression,
|
||||||
val last: IrExpression,
|
val last: IrExpression,
|
||||||
val step: IrExpression
|
val step: IrExpression,
|
||||||
|
val isLastInclusive: Boolean
|
||||||
) {
|
) {
|
||||||
val direction: ProgressionDirection by lazy {
|
val direction: ProgressionDirection by lazy {
|
||||||
// If step is a constant (either Int or Long), then we can determine the direction.
|
// If step is a constant (either Int or Long), then we can determine the direction.
|
||||||
@@ -82,10 +83,10 @@ internal class ProgressionHeaderInfo(
|
|||||||
first: IrExpression,
|
first: IrExpression,
|
||||||
last: IrExpression,
|
last: IrExpression,
|
||||||
step: IrExpression,
|
step: IrExpression,
|
||||||
|
isLastInclusive: Boolean = true,
|
||||||
canOverflow: Boolean? = null,
|
canOverflow: Boolean? = null,
|
||||||
val additionalVariables: List<IrVariable> = listOf(),
|
val additionalVariables: List<IrVariable> = listOf()
|
||||||
val additionalNotEmptyCondition: IrExpression? = null
|
) : HeaderInfo(progressionType, first, last, step, isLastInclusive) {
|
||||||
) : HeaderInfo(progressionType, first, last, step) {
|
|
||||||
|
|
||||||
private val _canOverflow: Boolean? = canOverflow
|
private val _canOverflow: Boolean? = canOverflow
|
||||||
val canOverflow: Boolean by lazy {
|
val canOverflow: Boolean by lazy {
|
||||||
@@ -129,7 +130,8 @@ internal class ArrayHeaderInfo(
|
|||||||
ProgressionType.INT_PROGRESSION,
|
ProgressionType.INT_PROGRESSION,
|
||||||
first,
|
first,
|
||||||
last,
|
last,
|
||||||
step
|
step,
|
||||||
|
isLastInclusive = false
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Matches a call to `iterator()` and builds a [HeaderInfo] out of the call's context. */
|
/** Matches a call to `iterator()` and builds a [HeaderInfo] out of the call's context. */
|
||||||
|
|||||||
+106
-85
@@ -26,10 +26,10 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
|
|
||||||
/** Contains information about variables used in the loop. */
|
/** Contains information about variables used in the loop. */
|
||||||
internal sealed class ForLoopHeader(
|
internal sealed class ForLoopHeader(
|
||||||
|
protected open val headerInfo: HeaderInfo,
|
||||||
val inductionVariable: IrVariable,
|
val inductionVariable: IrVariable,
|
||||||
val last: IrVariable,
|
val last: IrVariable,
|
||||||
val step: IrVariable,
|
val step: IrVariable,
|
||||||
val progressionType: ProgressionType,
|
|
||||||
var loopVariable: IrVariable? = null
|
var loopVariable: IrVariable? = null
|
||||||
) {
|
) {
|
||||||
/** Expression used to initialize the loop variable at the beginning of the loop. */
|
/** 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.
|
* Returns null if no check is needed for the for-loop.
|
||||||
*/
|
*/
|
||||||
abstract fun buildNotEmptyConditionIfNecessary(builder: DeclarationIrBuilder): IrExpression?
|
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(
|
internal class ProgressionLoopHeader(
|
||||||
private val headerInfo: ProgressionHeaderInfo,
|
override val headerInfo: ProgressionHeaderInfo,
|
||||||
inductionVariable: IrVariable,
|
inductionVariable: IrVariable,
|
||||||
last: IrVariable,
|
last: IrVariable,
|
||||||
step: IrVariable
|
step: IrVariable
|
||||||
) : ForLoopHeader(inductionVariable, last, step, headerInfo.progressionType) {
|
) : ForLoopHeader(headerInfo, inductionVariable, last, step) {
|
||||||
|
|
||||||
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) {
|
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) {
|
||||||
// loopVariable = inductionVariable
|
// loopVariable = inductionVariable
|
||||||
irGet(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<IrStatement>
|
override val declarations: List<IrStatement>
|
||||||
get() = headerInfo.additionalVariables + listOf(inductionVariable, last, step)
|
get() = headerInfo.additionalVariables + listOf(inductionVariable, last, step)
|
||||||
|
|
||||||
override fun buildInnerLoop(builder: DeclarationIrBuilder, loop: IrLoop, newBody: IrExpression?): IrLoop = with(builder) {
|
override fun buildInnerLoop(builder: DeclarationIrBuilder, loop: IrLoop, newBody: IrExpression?): IrLoop = with(builder) {
|
||||||
if (headerInfo.canOverflow) {
|
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)
|
assert(loopVariable != null)
|
||||||
val booleanNotFun = context.irBuiltIns.booleanClass.functions.first { it.owner.name.asString() == "not" }
|
val booleanNotFun = context.irBuiltIns.booleanClass.functions.first { it.owner.name.asString() == "not" }
|
||||||
val newCondition = irCallOp(booleanNotFun, booleanNotFun.owner.returnType, irCall(context.irBuiltIns.eqeqSymbol).apply {
|
val newCondition = irCallOp(booleanNotFun, booleanNotFun.owner.returnType, irCall(context.irBuiltIns.eqeqSymbol).apply {
|
||||||
@@ -80,85 +152,38 @@ internal class ProgressionLoopHeader(
|
|||||||
body = newBody
|
body = newBody
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the induction variable cannot overflow, use a while loop using the "not empty" condition.
|
// If the induction variable can NOT overflow, use a simple while loop. Loop is lowered into something like:
|
||||||
val newCondition = buildNotEmptyCondition(this@with)
|
//
|
||||||
|
// 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 {
|
IrWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, loop.origin).apply {
|
||||||
label = loop.label
|
label = loop.label
|
||||||
condition = newCondition
|
condition = buildLoopCondition(this@with)
|
||||||
body = newBody
|
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
|
// If the induction variable can NOT 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.
|
// simple while loop (see buildInnerLoop()); the enclosing check would be redundant.
|
||||||
override fun buildNotEmptyConditionIfNecessary(builder: DeclarationIrBuilder): IrExpression? =
|
override fun buildNotEmptyConditionIfNecessary(builder: DeclarationIrBuilder): IrExpression? =
|
||||||
if (headerInfo.canOverflow) buildNotEmptyCondition(builder) else null
|
if (headerInfo.canOverflow) buildLoopCondition(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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ArrayLoopHeader(
|
internal class ArrayLoopHeader(
|
||||||
private val headerInfo: ArrayHeaderInfo,
|
override val headerInfo: ArrayHeaderInfo,
|
||||||
inductionVariable: IrVariable,
|
inductionVariable: IrVariable,
|
||||||
last: IrVariable,
|
last: IrVariable,
|
||||||
step: IrVariable
|
step: IrVariable
|
||||||
) : ForLoopHeader(inductionVariable, last, step, ProgressionType.INT_PROGRESSION) {
|
) : ForLoopHeader(headerInfo, inductionVariable, last, step) {
|
||||||
|
|
||||||
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) {
|
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) {
|
||||||
// loopVariable = array[inductionVariable]
|
// inductionVar = loopVar[inductionVariable]
|
||||||
val arrayGetFun = headerInfo.arrayVariable.type.getClass()!!.functions.first { it.name.asString() == "get" }
|
val arrayGetFun = headerInfo.arrayVariable.type.getClass()!!.functions.first { it.name.asString() == "get" }
|
||||||
irCall(arrayGetFun).apply {
|
irCall(arrayGetFun).apply {
|
||||||
dispatchReceiver = irGet(headerInfo.arrayVariable)
|
dispatchReceiver = irGet(headerInfo.arrayVariable)
|
||||||
@@ -170,17 +195,18 @@ internal class ArrayLoopHeader(
|
|||||||
get() = listOf(headerInfo.arrayVariable, inductionVariable, last, step)
|
get() = listOf(headerInfo.arrayVariable, inductionVariable, last, step)
|
||||||
|
|
||||||
override fun buildInnerLoop(builder: DeclarationIrBuilder, loop: IrLoop, newBody: IrExpression?): IrLoop = with(builder) {
|
override fun buildInnerLoop(builder: DeclarationIrBuilder, loop: IrLoop, newBody: IrExpression?): IrLoop = with(builder) {
|
||||||
// Condition: inductionVariable != last
|
// Loop is lowered into something like:
|
||||||
val builtIns = context.irBuiltIns
|
//
|
||||||
val callee = builtIns.lessOrEqualFunByOperandType[builtIns.int]!!
|
// var inductionVar = 0
|
||||||
val newCondition = irCall(callee).apply {
|
// var last = array.size
|
||||||
putValueArgument(0, irGet(inductionVariable))
|
// while (inductionVar < last) {
|
||||||
putValueArgument(1, irGet(last))
|
// val loopVar = array[inductionVar++]
|
||||||
}
|
// inductionVar++
|
||||||
|
// // Loop body
|
||||||
|
// }
|
||||||
IrWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, loop.origin).apply {
|
IrWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, loop.origin).apply {
|
||||||
label = loop.label
|
label = loop.label
|
||||||
condition = newCondition
|
condition = buildLoopCondition(this@with)
|
||||||
body = newBody
|
body = newBody
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,18 +250,13 @@ internal class HeaderProcessor(
|
|||||||
with(headerInfo) {
|
with(headerInfo) {
|
||||||
// For this loop:
|
// 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
|
// We need to cast first(), last(). and step() to conform to the progression type so
|
||||||
// order: first(), last(), step().
|
// that operations on the induction variable within the loop are more efficient.
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
//
|
||||||
// In the above example, if first() is a Long and last() is an Int, this creates a
|
// 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(
|
val inductionVariable = scope.createTemporaryVariable(
|
||||||
first.castIfNecessary(
|
first.castIfNecessary(
|
||||||
progressionType.elementType(context.irBuiltIns),
|
progressionType.elementType(context.irBuiltIns),
|
||||||
|
|||||||
+13
-92
@@ -6,23 +6,19 @@
|
|||||||
package org.jetbrains.kotlin.backend.common.lower.loops
|
package org.jetbrains.kotlin.backend.common.lower.loops
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
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.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
|
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.createIrCallMatcher
|
||||||
import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension
|
import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
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.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.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.expressions.IrStatementOrigin
|
||||||
import org.jetbrains.kotlin.ir.types.getClass
|
import org.jetbrains.kotlin.ir.types.getClass
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
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.ir.util.properties
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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? =
|
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
||||||
with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) {
|
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(
|
ProgressionHeaderInfo(
|
||||||
data,
|
data,
|
||||||
first = call.extensionReceiver!!,
|
first = call.extensionReceiver!!,
|
||||||
last = last,
|
last = call.getValueArgument(0)!!,
|
||||||
step = irInt(1),
|
step = irInt(1),
|
||||||
canOverflow = false,
|
isLastInclusive = false,
|
||||||
additionalVariables = listOfNotNull(boundVar),
|
canOverflow = false
|
||||||
additionalNotEmptyCondition = if (boundVar != null) buildMinValueCondition(data, irGet(boundVar)) else null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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. */
|
/** 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? =
|
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
||||||
with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) {
|
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 arraySizeProperty = call.extensionReceiver!!.type.getClass()!!.properties.first { it.name.asString() == "size" }
|
||||||
val decFun = data.decFun(context.irBuiltIns)
|
val last = irCall(arraySizeProperty.getter!!).apply {
|
||||||
val last = irCallOp(decFun.symbol, data.elementType(context.irBuiltIns), irCall(arraySizeProperty.getter!!).apply {
|
|
||||||
dispatchReceiver = call.extensionReceiver
|
dispatchReceiver = call.extensionReceiver
|
||||||
})
|
}
|
||||||
|
|
||||||
ProgressionHeaderInfo(
|
ProgressionHeaderInfo(
|
||||||
data,
|
data,
|
||||||
first = irInt(0),
|
first = irInt(0),
|
||||||
last = last,
|
last = last,
|
||||||
step = irInt(1),
|
step = irInt(1),
|
||||||
|
isLastInclusive = false,
|
||||||
canOverflow = false // Cannot overflow because `last` is at most MAX_VALUE - 1
|
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. */
|
/** Builds a [HeaderInfo] for arrays. */
|
||||||
internal class ArrayIterationHandler(private val context: CommonBackendContext) : HeaderInfoHandler<Nothing?> {
|
internal class ArrayIterationHandler(private val context: CommonBackendContext) : HeaderInfoHandler<Nothing?> {
|
||||||
|
|
||||||
private val intDecFun = ProgressionType.INT_PROGRESSION.decFun(context.irBuiltIns)
|
|
||||||
|
|
||||||
override val matcher = createIrCallMatcher {
|
override val matcher = createIrCallMatcher {
|
||||||
origin { it == IrStatementOrigin.FOR_LOOP_ITERATOR }
|
origin { it == IrStatementOrigin.FOR_LOOP_ITERATOR }
|
||||||
// TODO: Support rare cases like `T : IntArray`
|
// TODO: Support rare cases like `T : IntArray`
|
||||||
@@ -255,11 +186,11 @@ internal class ArrayIterationHandler(private val context: CommonBackendContext)
|
|||||||
origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE
|
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 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)
|
dispatchReceiver = irGet(arrayReference)
|
||||||
})
|
}
|
||||||
|
|
||||||
ArrayHeaderInfo(
|
ArrayHeaderInfo(
|
||||||
first = irInt(0),
|
first = irInt(0),
|
||||||
@@ -269,13 +200,3 @@ internal class ArrayIterationHandler(private val context: CommonBackendContext)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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" }
|
|
||||||
}
|
|
||||||
+21
@@ -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"
|
||||||
|
}
|
||||||
+5
-5
@@ -5,15 +5,15 @@ import kotlin.test.*
|
|||||||
val log = StringBuilder()
|
val log = StringBuilder()
|
||||||
|
|
||||||
fun logged(message: String, value: Int) =
|
fun logged(message: String, value: Int) =
|
||||||
value.also { log.append(message) }
|
value.also { log.append(message) }
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
var s = 0
|
var sum = 0
|
||||||
for (i in (logged("start;", 1) .. logged("end;", 2)).reversed()) {
|
for (i in logged("start;", 1)..logged("end;", 4)) {
|
||||||
s += i
|
sum = sum * 10 + i
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(3, s)
|
assertEquals(1234, sum)
|
||||||
|
|
||||||
assertEquals("start;end;", log.toString())
|
assertEquals("start;end;", log.toString())
|
||||||
|
|
||||||
+5
-5
@@ -5,15 +5,15 @@ import kotlin.test.*
|
|||||||
val log = StringBuilder()
|
val log = StringBuilder()
|
||||||
|
|
||||||
fun logged(message: String, value: Int) =
|
fun logged(message: String, value: Int) =
|
||||||
value.also { log.append(message) }
|
value.also { log.append(message) }
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
var s = 0
|
var sum = 0
|
||||||
for (i in (logged("start;", 2) downTo logged("end;", 1)).reversed()) {
|
for (i in (logged("start;", 4) downTo logged("end;", 1)).reversed()) {
|
||||||
s += i
|
sum = sum * 10 + i
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(3, s)
|
assertEquals(1234, sum)
|
||||||
|
|
||||||
assertEquals("start;end;", log.toString())
|
assertEquals("start;end;", log.toString())
|
||||||
|
|
||||||
Vendored
+21
@@ -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"
|
||||||
|
}
|
||||||
+5
-5
@@ -5,15 +5,15 @@ import kotlin.test.*
|
|||||||
val log = StringBuilder()
|
val log = StringBuilder()
|
||||||
|
|
||||||
fun logged(message: String, value: Int) =
|
fun logged(message: String, value: Int) =
|
||||||
value.also { log.append(message) }
|
value.also { log.append(message) }
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
var s = 0
|
var sum = 0
|
||||||
for (i in (logged("start;", 1) until logged("end;", 3)).reversed()) {
|
for (i in (logged("start;", 1) until logged("end;", 5)).reversed()) {
|
||||||
s += i
|
sum = sum * 10 + i
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(3, s)
|
assertEquals(4321, sum)
|
||||||
|
|
||||||
assertEquals("start;end;", log.toString())
|
assertEquals("start;end;", log.toString())
|
||||||
|
|
||||||
+21
@@ -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"
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
fun test(): Int {
|
fun test(a: Int, b: Int): Int {
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (i in 1 until 6) {
|
for (i in a until b) {
|
||||||
sum = sum * 10 + i
|
sum = sum * 10 + i
|
||||||
}
|
}
|
||||||
return sum
|
return sum
|
||||||
|
|||||||
+43
-28
@@ -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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/expression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -18958,34 +19001,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
+43
-28
@@ -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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/expression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -18958,34 +19001,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
+43
-28
@@ -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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/expression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -18963,34 +19006,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
Generated
+43
-28
@@ -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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/expression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -15018,34 +15061,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
+43
-28
@@ -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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/expression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -16188,34 +16231,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
Reference in New Issue
Block a user