Support const-bounded for loop generation for reversed 'until'
This commit is contained in:
+13
-10
@@ -76,7 +76,8 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
|||||||
forExpression: KtForExpression,
|
forExpression: KtForExpression,
|
||||||
startValue: StackValue,
|
startValue: StackValue,
|
||||||
endExpression: KtExpression,
|
endExpression: KtExpression,
|
||||||
step: Int
|
step: Int,
|
||||||
|
isStartInclusive: Boolean = true
|
||||||
): ForLoopGenerator? {
|
): ForLoopGenerator? {
|
||||||
val endConstValue = codegen.getCompileTimeConstant(endExpression).safeAs<IntegerValueConstant<*>>() ?: return null
|
val endConstValue = codegen.getCompileTimeConstant(endExpression).safeAs<IntegerValueConstant<*>>() ?: return null
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
|||||||
if (isProhibitedIntConstEndValue(step, endIntValue))
|
if (isProhibitedIntConstEndValue(step, endIntValue))
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step)
|
createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step, isStartInclusive)
|
||||||
}
|
}
|
||||||
|
|
||||||
is ShortValue -> {
|
is ShortValue -> {
|
||||||
@@ -94,7 +95,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
|||||||
if (isProhibitedIntConstEndValue(step, endIntValue))
|
if (isProhibitedIntConstEndValue(step, endIntValue))
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step)
|
createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step, isStartInclusive)
|
||||||
}
|
}
|
||||||
|
|
||||||
is IntValue -> {
|
is IntValue -> {
|
||||||
@@ -102,7 +103,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
|||||||
if (isProhibitedIntConstEndValue(step, endIntValue))
|
if (isProhibitedIntConstEndValue(step, endIntValue))
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step)
|
createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step, isStartInclusive)
|
||||||
}
|
}
|
||||||
|
|
||||||
is CharValue -> {
|
is CharValue -> {
|
||||||
@@ -110,7 +111,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
|||||||
if (isProhibitedCharConstEndValue(step, endCharValue))
|
if (isProhibitedCharConstEndValue(step, endCharValue))
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endCharValue.toInt(), step)
|
createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endCharValue.toInt(), step, isStartInclusive)
|
||||||
}
|
}
|
||||||
|
|
||||||
is LongValue -> {
|
is LongValue -> {
|
||||||
@@ -118,7 +119,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
|||||||
if (isProhibitedLongConstEndValue(step, endLongValue))
|
if (isProhibitedLongConstEndValue(step, endLongValue))
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
createConstBoundedLongForLoopGenerator(codegen, forExpression, startValue, endLongValue, step)
|
createConstBoundedLongForLoopGenerator(codegen, forExpression, startValue, endLongValue, step, isStartInclusive)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
@@ -130,12 +131,13 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
|||||||
forExpression: KtForExpression,
|
forExpression: KtForExpression,
|
||||||
startValue: StackValue,
|
startValue: StackValue,
|
||||||
endIntValue: Int,
|
endIntValue: Int,
|
||||||
step: Int
|
step: Int,
|
||||||
|
isStartInclusive: Boolean
|
||||||
): ForLoopGenerator? =
|
): ForLoopGenerator? =
|
||||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
||||||
codegen, forExpression,
|
codegen, forExpression,
|
||||||
startValue = startValue,
|
startValue = startValue,
|
||||||
isStartInclusive = true,
|
isStartInclusive = isStartInclusive,
|
||||||
endValue = StackValue.integerConstant(endIntValue, asmElementType),
|
endValue = StackValue.integerConstant(endIntValue, asmElementType),
|
||||||
isEndInclusive = true,
|
isEndInclusive = true,
|
||||||
step = step
|
step = step
|
||||||
@@ -146,12 +148,13 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
|||||||
forExpression: KtForExpression,
|
forExpression: KtForExpression,
|
||||||
startValue: StackValue,
|
startValue: StackValue,
|
||||||
endLongValue: Long,
|
endLongValue: Long,
|
||||||
step: Int
|
step: Int,
|
||||||
|
isStartInclusive: Boolean
|
||||||
): ForLoopGenerator? =
|
): ForLoopGenerator? =
|
||||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
||||||
codegen, forExpression,
|
codegen, forExpression,
|
||||||
startValue = startValue,
|
startValue = startValue,
|
||||||
isStartInclusive = true,
|
isStartInclusive = isStartInclusive,
|
||||||
endValue = StackValue.constant(endLongValue, asmElementType),
|
endValue = StackValue.constant(endLongValue, asmElementType),
|
||||||
isEndInclusive = true,
|
isEndInclusive = true,
|
||||||
step = step
|
step = step
|
||||||
|
|||||||
+18
@@ -17,9 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.codegen.range
|
package org.jetbrains.kotlin.codegen.range
|
||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||||
|
import org.jetbrains.kotlin.codegen.generateCallSingleArgument
|
||||||
import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGenerator
|
import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGenerator
|
||||||
|
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtForExpression
|
import org.jetbrains.kotlin.psi.KtForExpression
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
|
||||||
class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
|
class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
|
||||||
@@ -32,5 +35,20 @@ class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescrip
|
|||||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||||
|
|
||||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||||
|
createConstBoundedForInReversedUntilGenerator(codegen, forExpression) ?:
|
||||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen))
|
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen))
|
||||||
|
|
||||||
|
private fun createConstBoundedForInReversedUntilGenerator(
|
||||||
|
codegen: ExpressionCodegen,
|
||||||
|
forExpression: KtForExpression
|
||||||
|
): ForLoopGenerator? {
|
||||||
|
val endExpression = rangeCall.getReceiverExpression() ?: return null
|
||||||
|
return createConstBoundedForLoopGeneratorOrNull(
|
||||||
|
codegen, forExpression,
|
||||||
|
codegen.generateCallSingleArgument(rangeCall),
|
||||||
|
endExpression,
|
||||||
|
step = -1,
|
||||||
|
isStartInclusive = false
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun intLow() = 1
|
||||||
|
fun intHigh() = 5
|
||||||
|
fun longLow() = 1L
|
||||||
|
fun longHigh() = 5L
|
||||||
|
fun charLow() = '1'
|
||||||
|
fun charHigh() = '5'
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var sum = 0
|
||||||
|
for (i in (intLow() until intHigh()).reversed()) {
|
||||||
|
sum = sum * 10 + i
|
||||||
|
}
|
||||||
|
assertEquals(4321, sum)
|
||||||
|
|
||||||
|
var sumL = 0L
|
||||||
|
for (i in (longLow() until longHigh()).reversed()) {
|
||||||
|
sumL = sumL * 10 + i
|
||||||
|
}
|
||||||
|
assertEquals(4321L, sumL)
|
||||||
|
|
||||||
|
var sumC = 0
|
||||||
|
for (i in (charLow() until charHigh()).reversed()) {
|
||||||
|
sumC = sumC * 10 + i.toInt() - '0'.toInt()
|
||||||
|
}
|
||||||
|
assertEquals(4321, sumC)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+6
@@ -15318,6 +15318,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("forInReversedUntilWithNonConstBounds.kt")
|
||||||
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
@@ -15318,6 +15318,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("forInReversedUntilWithNonConstBounds.kt")
|
||||||
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
@@ -15318,6 +15318,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("forInReversedUntilWithNonConstBounds.kt")
|
||||||
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
@@ -16734,6 +16734,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntil.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("forInReversedUntilWithNonConstBounds.kt")
|
||||||
|
public void testForInReversedUntilWithNonConstBounds() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/forInReversed/forInReversedUntilWithNonConstBounds.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
@TestMetadata("compiler/testData/codegen/box/ranges/forInUntil")
|
||||||
|
|||||||
Reference in New Issue
Block a user