diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt index a09e4ad333f..33816be2624 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt @@ -18,13 +18,19 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall +import org.jetbrains.kotlin.codegen.range.forLoop.ForInDefinitelySafeSimpleProgressionLoopGenerator +import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator import org.jetbrains.kotlin.codegen.range.inExpression.InFloatingPointRangeLiteralExpressionGenerator import org.jetbrains.kotlin.codegen.range.inExpression.InIntegralContinuousRangeExpressionGenerator import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.constants.* +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.Type abstract class PrimitiveNumberRangeIntrinsicRangeValue( @@ -64,4 +70,100 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue( } protected abstract fun getBoundedValue(codegen: ExpressionCodegen): BoundedValue + + protected fun createConstBoundedForLoopGeneratorOrNull( + codegen: ExpressionCodegen, + forExpression: KtForExpression, + startValue: StackValue, + endExpression: KtExpression, + step: Int + ): ForLoopGenerator? { + val endConstValue = codegen.getCompileTimeConstant(endExpression).safeAs>() ?: return null + + return when (endConstValue) { + is ByteValue -> { + val endIntValue = endConstValue.value.toInt() + if (isProhibitedIntConstEndValue(step, endIntValue)) + null + else + createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step) + } + + is ShortValue -> { + val endIntValue = endConstValue.value.toInt() + if (isProhibitedIntConstEndValue(step, endIntValue)) + null + else + createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step) + } + + is IntValue -> { + val endIntValue = endConstValue.value + if (isProhibitedIntConstEndValue(step, endIntValue)) + null + else + createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step) + } + + is CharValue -> { + val endCharValue = endConstValue.value + if (isProhibitedCharConstEndValue(step, endCharValue)) + null + else + createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endCharValue.toInt(), step) + } + + is LongValue -> { + val endLongValue = endConstValue.value + if (isProhibitedLongConstEndValue(step, endLongValue)) + null + else + createConstBoundedLongForLoopGenerator(codegen, forExpression, startValue, endLongValue, step) + } + + else -> null + } + } + + private fun createConstBoundedIntForLoopGenerator( + codegen: ExpressionCodegen, + forExpression: KtForExpression, + startValue: StackValue, + endIntValue: Int, + step: Int + ): ForLoopGenerator? = + ForInDefinitelySafeSimpleProgressionLoopGenerator( + codegen, forExpression, + startValue = startValue, + isStartInclusive = true, + endValue = StackValue.integerConstant(endIntValue, asmElementType), + isEndInclusive = true, + step = step + ) + + private fun createConstBoundedLongForLoopGenerator( + codegen: ExpressionCodegen, + forExpression: KtForExpression, + startValue: StackValue, + endLongValue: Long, + step: Int + ): ForLoopGenerator? = + ForInDefinitelySafeSimpleProgressionLoopGenerator( + codegen, forExpression, + startValue = startValue, + isStartInclusive = true, + endValue = StackValue.constant(endLongValue, asmElementType), + isEndInclusive = true, + step = step + ) + + private fun isProhibitedCharConstEndValue(step: Int, endValue: Char) = + endValue == if (step == 1) java.lang.Character.MAX_VALUE else java.lang.Character.MIN_VALUE + + private fun isProhibitedIntConstEndValue(step: Int, endValue: Int) = + endValue == if (step == 1) Int.MAX_VALUE else Int.MIN_VALUE + + private fun isProhibitedLongConstEndValue(step: Int, endValue: Long) = + endValue == if (step == 1) Long.MAX_VALUE else Long.MIN_VALUE + } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt index e4438e56743..388a078f075 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt @@ -17,17 +17,13 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.generateCallReceiver import org.jetbrains.kotlin.codegen.generateCallSingleArgument -import org.jetbrains.kotlin.codegen.range.forLoop.ForInDefinitelySafeSimpleProgressionLoopGenerator 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.psi.KtExpression import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -52,7 +48,7 @@ class PrimitiveNumberRangeLiteralRangeValue( forExpression: KtForExpression ): ForLoopGenerator? { val endExpression = rangeCall.valueArgumentsByIndex?.run { get(0).arguments[0].getArgumentExpression() } ?: return null - return createConstBoundedForLoopGenerator( + return createConstBoundedForLoopGeneratorOrNull( codegen, forExpression, codegen.generateCallReceiver(rangeCall), endExpression, @@ -65,107 +61,11 @@ class PrimitiveNumberRangeLiteralRangeValue( forExpression: KtForExpression ): ForLoopGenerator? { val endExpression = rangeCall.extensionReceiver.safeAs()?.expression ?: return null - return createConstBoundedForLoopGenerator( + return createConstBoundedForLoopGeneratorOrNull( codegen, forExpression, codegen.generateCallSingleArgument(rangeCall), endExpression, -1 ) } - - private fun createConstBoundedForLoopGenerator( - codegen: ExpressionCodegen, - forExpression: KtForExpression, - startValue: StackValue, - endExpression: KtExpression, - step: Int - ): ForLoopGenerator? { - val endConstValue = codegen.getCompileTimeConstant(endExpression).safeAs>() ?: return null - - return when (endConstValue) { - is ByteValue -> { - val endIntValue = endConstValue.value.toInt() - if (isProhibitedIntConstEndValue(step, endIntValue)) - null - else - createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step) - } - - is ShortValue -> { - val endIntValue = endConstValue.value.toInt() - if (isProhibitedIntConstEndValue(step, endIntValue)) - null - else - createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step) - } - - is IntValue -> { - val endIntValue = endConstValue.value - if (isProhibitedIntConstEndValue(step, endIntValue)) - null - else - createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endIntValue, step) - } - - is CharValue -> { - val endCharValue = endConstValue.value - if (isProhibitedCharConstEndValue(step, endCharValue)) - null - else - createConstBoundedIntForLoopGenerator(codegen, forExpression, startValue, endCharValue.toInt(), step) - } - - is LongValue -> { - val endLongValue = endConstValue.value - if (isProhibitedLongConstEndValue(step, endLongValue)) - null - else - createConstBoundedLongForLoopGenerator(codegen, forExpression, startValue, endLongValue, step) - } - - else -> null - } - } - - private fun createConstBoundedIntForLoopGenerator( - codegen: ExpressionCodegen, - forExpression: KtForExpression, - startValue: StackValue, - endIntValue: Int, - step: Int - ): ForLoopGenerator? = - ForInDefinitelySafeSimpleProgressionLoopGenerator( - codegen, forExpression, - startValue = startValue, - isStartInclusive = true, - endValue = StackValue.integerConstant(endIntValue, asmElementType), - isEndInclusive = true, - step = step - ) - - private fun createConstBoundedLongForLoopGenerator( - codegen: ExpressionCodegen, - forExpression: KtForExpression, - startValue: StackValue, - endLongValue: Long, - step: Int - ): ForLoopGenerator? = - ForInDefinitelySafeSimpleProgressionLoopGenerator( - codegen, forExpression, - startValue = startValue, - isStartInclusive = true, - endValue = StackValue.constant(endLongValue, asmElementType), - isEndInclusive = true, - step = step - ) - - private fun isProhibitedCharConstEndValue(step: Int, endValue: Char) = - endValue == if (step == 1) java.lang.Character.MAX_VALUE else java.lang.Character.MIN_VALUE - - private fun isProhibitedIntConstEndValue(step: Int, endValue: Int) = - endValue == if (step == 1) Int.MAX_VALUE else Int.MIN_VALUE - - private fun isProhibitedLongConstEndValue(step: Int, endValue: Long) = - endValue == if (step == 1) Long.MAX_VALUE else Long.MIN_VALUE - } \ No newline at end of file