Intrinsics for 'reversed': generate in-const-bound ranges as countable

#KT-21323 In Progress
This commit is contained in:
Dmitry Petrov
2017-12-11 12:20:21 +03:00
parent 1775f294f4
commit 821843e13f
9 changed files with 147 additions and 5 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.constants.ByteValue
import org.jetbrains.kotlin.resolve.constants.IntValue
import org.jetbrains.kotlin.resolve.constants.IntegerValueConstant
import org.jetbrains.kotlin.resolve.constants.ShortValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class PrimitiveNumberRangeLiteralRangeValue(
@@ -40,21 +41,24 @@ class PrimitiveNumberRangeLiteralRangeValue(
SimpleBoundedValue(codegen, rangeCall)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
getConstRangeForInRangeLiteralGenerator(codegen, forExpression) ?:
createConstBoundedForInRangeLiteralGenerator(codegen, forExpression) ?:
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
// TODO const-bounded version
createConstBoundedRangeForInReversedRangeLiteralGenerator(codegen, forExpression) ?:
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen))
private fun getConstRangeForInRangeLiteralGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator? {
private fun createConstBoundedForInRangeLiteralGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
): ForLoopGenerator? {
val rhsExpression = rangeCall.valueArgumentsByIndex?.run { get(0).arguments[0].getArgumentExpression() } ?: return null
val constValue = codegen.getCompileTimeConstant(rhsExpression).safeAs<IntegerValueConstant<*>>() ?: return null
val untilValue = when (constValue) {
is ByteValue -> constValue.value + 1
is ShortValue -> constValue.value + 1
is IntValue -> constValue.value + 1
else -> return null
else -> Int.MIN_VALUE
}
// Watch out for integer overflow
@@ -70,4 +74,32 @@ class PrimitiveNumberRangeLiteralRangeValue(
step = 1
)
}
private fun createConstBoundedRangeForInReversedRangeLiteralGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
): ForLoopGenerator? {
val lhsExpression = rangeCall.extensionReceiver.safeAs<ExpressionReceiver>()?.expression ?: return null
val constValue = codegen.getCompileTimeConstant(lhsExpression).safeAs<IntegerValueConstant<*>>() ?: return null
val untilValue = when (constValue) {
is ByteValue -> constValue.value - 1
is ShortValue -> constValue.value - 1
is IntValue -> constValue.value - 1
else -> Int.MAX_VALUE
}
// Watch out for integer overflow
return if (untilValue == Int.MAX_VALUE)
null
else
ForInSimpleProgressionLoopGenerator(
codegen, forExpression,
startValue = codegen.generateCallSingleArgument(rangeCall),
isStartInclusive = true,
endValue = StackValue.integerConstant(untilValue, asmElementType),
isEndInclusive = false,
step = -1
)
}
}