Extract common code in PrimitiveNumberRangeLiteralRangeValue

This commit is contained in:
Dmitry Petrov
2017-12-11 17:09:29 +03:00
parent 455a1c0f53
commit df2b8d01d8
@@ -20,9 +20,11 @@ import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.generateCallSingleArgument 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.ForInSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator 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.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.constants.ByteValue import org.jetbrains.kotlin.resolve.constants.ByteValue
@@ -52,54 +54,57 @@ class PrimitiveNumberRangeLiteralRangeValue(
codegen: ExpressionCodegen, codegen: ExpressionCodegen,
forExpression: KtForExpression forExpression: KtForExpression
): ForLoopGenerator? { ): ForLoopGenerator? {
val rhsExpression = rangeCall.valueArgumentsByIndex?.run { get(0).arguments[0].getArgumentExpression() } ?: return null val endExpression = rangeCall.valueArgumentsByIndex?.run { get(0).arguments[0].getArgumentExpression() } ?: return null
val constValue = codegen.getCompileTimeConstant(rhsExpression).safeAs<IntegerValueConstant<*>>() ?: return null return createConstBoundedForLoopGenerator(
val untilValue = when (constValue) { codegen, forExpression,
is ByteValue -> constValue.value + 1 codegen.generateCallReceiver(rangeCall),
is ShortValue -> constValue.value + 1 endExpression,
is IntValue -> constValue.value + 1 1
else -> Int.MIN_VALUE )
}
// Watch out for integer overflow
return if (untilValue == Int.MIN_VALUE)
null
else
ForInSimpleProgressionLoopGenerator(
codegen, forExpression,
startValue = codegen.generateCallReceiver(rangeCall),
isStartInclusive = true,
endValue = StackValue.integerConstant(untilValue, asmElementType),
isEndInclusive = false,
step = 1
)
} }
private fun createConstBoundedRangeForInReversedRangeLiteralGenerator( private fun createConstBoundedRangeForInReversedRangeLiteralGenerator(
codegen: ExpressionCodegen, codegen: ExpressionCodegen,
forExpression: KtForExpression forExpression: KtForExpression
): ForLoopGenerator? { ): ForLoopGenerator? {
val lhsExpression = rangeCall.extensionReceiver.safeAs<ExpressionReceiver>()?.expression ?: return null val endExpression = rangeCall.extensionReceiver.safeAs<ExpressionReceiver>()?.expression ?: return null
val constValue = codegen.getCompileTimeConstant(lhsExpression).safeAs<IntegerValueConstant<*>>() ?: return null return createConstBoundedForLoopGenerator(
val untilValue = when (constValue) { codegen, forExpression,
is ByteValue -> constValue.value - 1 codegen.generateCallSingleArgument(rangeCall),
is ShortValue -> constValue.value - 1 endExpression,
is IntValue -> constValue.value - 1 -1
else -> Int.MAX_VALUE )
}
private fun createConstBoundedForLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
startValue: StackValue,
endExpression: KtExpression,
step: Int
) : ForLoopGenerator? {
val endConstValue = codegen.getCompileTimeConstant(endExpression).safeAs<IntegerValueConstant<*>>() ?: return null
val endIntValue = when (endConstValue) {
is ByteValue -> endConstValue.value.toInt()
is ShortValue -> endConstValue.value.toInt()
is IntValue -> endConstValue.value
else -> return null
} }
// Watch out for integer overflow return if (isProhibitedIntConstEndValue(step, endIntValue))
return if (untilValue == Int.MAX_VALUE)
null null
else else
ForInSimpleProgressionLoopGenerator( ForInDefinitelySafeSimpleProgressionLoopGenerator(
codegen, forExpression, codegen, forExpression,
startValue = codegen.generateCallSingleArgument(rangeCall), startValue = startValue,
isStartInclusive = true, isStartInclusive = true,
endValue = StackValue.integerConstant(untilValue, asmElementType), endValue = StackValue.integerConstant(endIntValue, asmElementType),
isEndInclusive = false, isEndInclusive = true,
step = -1 step = step
) )
} }
private fun isProhibitedIntConstEndValue(step: Int, endValue: Int) =
endValue == if (step == 1) Int.MAX_VALUE else Int.MIN_VALUE
} }