Support const-bounded for loop generation for reversed 'until'

This commit is contained in:
Dmitry Petrov
2017-12-12 15:07:31 +03:00
parent 54cceac99b
commit bf97b332cf
7 changed files with 86 additions and 10 deletions
@@ -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
@@ -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
)
}
} }
@@ -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"
}
@@ -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")