Minor: pull up helper methods for const-bounded for-in-range generation

This commit is contained in:
Dmitry Petrov
2017-12-12 11:11:31 +03:00
parent a4c29b3587
commit 2f0df832c0
2 changed files with 104 additions and 102 deletions
@@ -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<IntegerValueConstant<*>>() ?: 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
}
@@ -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<ExpressionReceiver>()?.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<IntegerValueConstant<*>>() ?: 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
}