diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberUntilRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberUntilRangeValue.kt index bd39fe61ba6..806ce5031c0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberUntilRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberUntilRangeValue.kt @@ -22,10 +22,15 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { +class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall) : + PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue { + override fun getBoundedValue(codegen: ExpressionCodegen) = SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false) override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen)) + + override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = + ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen)) } \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt b/compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt new file mode 100644 index 00000000000..41c5873f042 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt @@ -0,0 +1,24 @@ +// WITH_RUNTIME +import kotlin.test.* + +fun box(): String { + var sum = 0 + for (i in (1 until 5).reversed()) { + sum = sum * 10 + i + } + assertEquals(4321, sum) + + var sumL = 0L + for (i in (1L until 5L).reversed()) { + sumL = sumL * 10 + i + } + assertEquals(4321L, sumL) + + var sumC = 0 + for (i in ('1' until '5').reversed()) { + sumC = sumC * 10 + i.toInt() - '0'.toInt() + } + assertEquals(4321, sumC) + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInUntilIntMinValueReversed.kt b/compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInUntilIntMinValueReversed.kt new file mode 100644 index 00000000000..bd269a4fb79 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInUntilIntMinValueReversed.kt @@ -0,0 +1,15 @@ +// WITH_RUNTIME + +const val M = Int.MIN_VALUE + +fun box(): String { + var count = 0 + for (i in (M until M + 1).reversed()) { + ++count + if (count > 1) { + throw AssertionError("Loop should be executed once") + } + } + if (count != 1) throw AssertionError("Should be executed once") + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedUntil.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedUntil.kt new file mode 100644 index 00000000000..cbd63d29e69 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedUntil.kt @@ -0,0 +1,23 @@ +// WITH_RUNTIME +import kotlin.test.* + +fun box(): String { + var sum = 0 + for (i in (1 until 5).reversed()) { + sum = sum * 10 + i + } + + var sumL = 0L + for (i in (1L until 5L).reversed()) { + sumL = sumL * 10 + i + } + + var sumC = 0 + for (i in ('1' until '5').reversed()) { + sumC = sumC * 10 + i.toInt() - '0'.toInt() + } + + return "OK" +} + +// 0 reversed \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 09e06723284..2114d97ba13 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -15312,6 +15312,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedReversedReversedRange.kt"); doTest(fileName); } + + @TestMetadata("forInReversedUntil.kt") + public void testForInReversedUntil() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil") @@ -15420,6 +15426,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInRangeToLongMaxValue.kt"); doTest(fileName); } + + @TestMetadata("forInUntilIntMinValueReversed.kt") + public void testForInUntilIntMinValueReversed() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInUntilIntMinValueReversed.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges/literal") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 1ef9a739d77..3880d96259a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -15312,6 +15312,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedReversedReversedRange.kt"); doTest(fileName); } + + @TestMetadata("forInReversedUntil.kt") + public void testForInReversedUntil() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil") @@ -15420,6 +15426,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInRangeToLongMaxValue.kt"); doTest(fileName); } + + @TestMetadata("forInUntilIntMinValueReversed.kt") + public void testForInUntilIntMinValueReversed() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInUntilIntMinValueReversed.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges/literal") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 98cd3e8b97a..79fdd607134 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -1473,6 +1473,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedReversedRange.kt"); doTest(fileName); } + + @TestMetadata("forInReversedUntil.kt") + public void testForInReversedUntil() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedUntil.kt"); + doTest(fileName); + } } } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index ded0d6e7a01..9f2907a4e90 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15312,6 +15312,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedReversedReversedRange.kt"); doTest(fileName); } + + @TestMetadata("forInReversedUntil.kt") + public void testForInReversedUntil() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil") @@ -15420,6 +15426,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInRangeToLongMaxValue.kt"); doTest(fileName); } + + @TestMetadata("forInUntilIntMinValueReversed.kt") + public void testForInUntilIntMinValueReversed() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInUntilIntMinValueReversed.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges/literal") 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 467fe7b08a0..c362e4b2ecf 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 @@ -16728,6 +16728,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedReversedReversedRange.kt"); doTest(fileName); } + + @TestMetadata("forInReversedUntil.kt") + public void testForInReversedUntil() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges/forInUntil") @@ -16836,6 +16842,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInRangeToLongMaxValue.kt"); doTest(fileName); } + + @TestMetadata("forInUntilIntMinValueReversed.kt") + public void testForInUntilIntMinValueReversed() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInUntilIntMinValueReversed.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges/literal")