Pull up logic for ComparisonGenerator selection

This commit is contained in:
Dmitry Petrov
2017-07-06 16:15:18 +03:00
parent ea95f31f99
commit d137b04b0a
13 changed files with 123 additions and 104 deletions
@@ -24,30 +24,30 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
val supportedRangeTypes = listOf(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG)
private val RANGE_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
supportedRangeTypes().associateBy {
supportedRangeTypes.associateBy {
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Range"))
}
private val PROGRESSION_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
supportedRangeTypes().associateBy {
supportedRangeTypes.associateBy {
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Progression"))
}
fun supportedRangeTypes() =
listOf(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG)
fun isPrimitiveRange(rangeType: KotlinType) =
!rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null
fun isPrimitiveProgression(rangeType: KotlinType) =
!rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null
fun getPrimitiveRangeElementType(rangeType: KotlinType) =
fun getPrimitiveRangeElementType(rangeType: KotlinType): PrimitiveType? =
getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE)
private fun getPrimitiveProgressionElementType(rangeType: KotlinType) =
@@ -62,6 +62,32 @@ private fun getPrimitiveRangeOrProgressionElementType(
return map[fqName.toSafe()]
}
fun getRangeOrProgressionElementType(rangeType: KotlinType): KotlinType? {
val rangeTypeDescriptor = rangeType.constructor.declarationDescriptor ?: return null
val builtIns = rangeTypeDescriptor.builtIns
return when {
isTopLevelInPackage(rangeTypeDescriptor, "CharRange", "kotlin.ranges") -> builtIns.charType
isTopLevelInPackage(rangeTypeDescriptor, "IntRange", "kotlin.ranges") -> builtIns.intType
isTopLevelInPackage(rangeTypeDescriptor, "LongRange", "kotlin.ranges") -> builtIns.longType
isTopLevelInPackage(rangeTypeDescriptor, "CharProgression", "kotlin.ranges") -> builtIns.charType
isTopLevelInPackage(rangeTypeDescriptor, "IntProgression", "kotlin.ranges") -> builtIns.intType
isTopLevelInPackage(rangeTypeDescriptor, "LongProgression", "kotlin.ranges") -> builtIns.longType
isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatRange", "kotlin.ranges") -> builtIns.floatType
isTopLevelInPackage(rangeTypeDescriptor, "ClosedDoubleRange", "kotlin.ranges") -> builtIns.doubleType
isTopLevelInPackage(rangeTypeDescriptor, "ClosedRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatingPointRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
isTopLevelInPackage(rangeTypeDescriptor, "ComparableRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
else -> null
}
}
fun getPrimitiveRangeOrProgressionElementType(rangeOrProgressionName: FqName): PrimitiveType? =
RANGE_TO_ELEMENT_TYPE[rangeOrProgressionName] ?:
PROGRESSION_TO_ELEMENT_TYPE[rangeOrProgressionName]
@@ -32,7 +32,7 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
private final static ImmutableMap<String, Type> VALUES_TYPENAME_TO_TYPE;
static {
ImmutableMap.Builder<String, Type> builder = ImmutableMap.builder();
for (PrimitiveType primitiveType : RangeCodegenUtilKt.supportedRangeTypes()) {
for (PrimitiveType primitiveType : RangeCodegenUtilKt.getSupportedRangeTypes()) {
builder.put(primitiveType.getTypeName().asString(), Type.getType(JvmPrimitiveType.get(primitiveType).getDesc()));
}
VALUES_TYPENAME_TO_TYPE = builder.build();
@@ -41,7 +41,7 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
private static final ImmutableMap<PrimitiveType, ProgressionIteratorBasicValue> ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE;
static {
ImmutableMap.Builder<PrimitiveType, ProgressionIteratorBasicValue> builder = ImmutableMap.builder();
for (PrimitiveType elementType : RangeCodegenUtilKt.supportedRangeTypes()) {
for (PrimitiveType elementType : RangeCodegenUtilKt.getSupportedRangeTypes()) {
builder.put(elementType, new ProgressionIteratorBasicValue(elementType.getTypeName().asString()));
}
ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE = builder.build();
@@ -19,24 +19,17 @@ 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.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInArrayIndicesRangeLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
class ArrayIndicesRangeValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
class ArrayIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
private val boundedValue =
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
@@ -49,6 +42,4 @@ class ArrayIndicesRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInArrayIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator)
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -27,12 +28,12 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall<out CallableDescriptor>): RangeValue {
protected abstract fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>): Boolean
protected abstract fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator
protected abstract fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression, resolvedCall: ResolvedCall<out CallableDescriptor>): InExpressionGenerator
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator {
val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext)
return if (isIntrinsicInCall(resolvedCall))
createIntrinsicInExpressionGenerator(codegen, operatorReference)
createIntrinsicInExpressionGenerator(codegen, operatorReference, resolvedCall)
else
CallBasedInExpressionGenerator(codegen, operatorReference)
}
@@ -19,24 +19,17 @@ 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.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInCharSequenceIndicesRangeLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
class CharSequenceIndicesRangeValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
private val boundedValue =
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
@@ -48,7 +41,4 @@ class CharSequenceIndicesRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInCharSequenceIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator)
}
@@ -19,24 +19,17 @@ 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.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInCollectionIndicesRangeLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
class CollectionIndicesRangeValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
class CollectionIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
private val boundedValue =
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
@@ -48,7 +41,4 @@ class CollectionIndicesRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInCollectionIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator)
}
@@ -17,19 +17,14 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.isClosedRangeContains
import org.jetbrains.kotlin.codegen.range.comparison.ObjectComparisonGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.IteratorForLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
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.scopes.receivers.ReceiverValue
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class ComparableRangeLiteralRangeValue(
codegen: ExpressionCodegen,
@@ -43,6 +38,6 @@ class ComparableRangeLiteralRangeValue(
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression)=
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression, resolvedCall: ResolvedCall<out CallableDescriptor>)=
InContinuousRangeExpressionGenerator(operatorReference, boundedValue, ObjectComparisonGenerator)
}
@@ -19,21 +19,13 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.generateCallSingleArgument
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInDownToProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class DownToProgressionRangeValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val boundedValue =
class DownToProgressionRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = codegen.generateCallSingleArgument(rangeCall),
@@ -42,7 +34,4 @@ class DownToProgressionRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInDownToProgressionLoopGenerator(codegen, forExpression, rangeCall)
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator)
}
@@ -16,11 +16,14 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.getAsmRangeElementTypeForPrimitiveRangeOrProgression
import org.jetbrains.kotlin.codegen.isClosedFloatingPointRangeContains
import org.jetbrains.kotlin.codegen.isIntPrimitiveRangeExtensionForInt
import org.jetbrains.kotlin.codegen.isPrimitiveRangeContains
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): CallIntrinsicRangeValue(rangeCall) {
@@ -32,4 +35,18 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<o
isClosedFloatingPointRangeContains(it) ||
isIntPrimitiveRangeExtensionForInt(it)
}
override fun createIntrinsicInExpressionGenerator(
codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>
): InExpressionGenerator {
val comparisonGenerator = getComparisonGeneratorForRangeContainsCall(codegen, resolvedCall)
return if (comparisonGenerator != null)
InContinuousRangeExpressionGenerator(operatorReference, getBoundedValue(codegen), comparisonGenerator)
else
CallBasedInExpressionGenerator(codegen, operatorReference)
}
protected abstract fun getBoundedValue(codegen: ExpressionCodegen): BoundedValue
}
@@ -17,24 +17,15 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInRangeLiteralLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class PrimitiveNumberRangeLiteralRangeValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val boundedValue = SimpleBoundedValue(codegen, rangeCall)
class PrimitiveNumberRangeLiteralRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(codegen, rangeCall)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInRangeLiteralLoopGenerator(codegen, forExpression, rangeCall)
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator)
}
@@ -17,24 +17,15 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInUntilRangeLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class PrimitiveNumberUntilRangeValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val boundedValue = SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInUntilRangeLoopGenerator(codegen, forExpression, rangeCall)
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator)
}
@@ -84,17 +84,17 @@ private fun ExpressionCodegen.createIntrinsifiedRangeValueOrNull(rangeCall: Reso
return when {
isPrimitiveNumberRangeTo(rangeCallee) ->
PrimitiveNumberRangeLiteralRangeValue(this, rangeCall)
PrimitiveNumberRangeLiteralRangeValue(rangeCall)
isPrimitiveNumberDownTo(rangeCallee) ->
DownToProgressionRangeValue(this, rangeCall)
DownToProgressionRangeValue(rangeCall)
isPrimitiveNumberUntil(rangeCallee) ->
PrimitiveNumberUntilRangeValue(this, rangeCall)
PrimitiveNumberUntilRangeValue(rangeCall)
isArrayOrPrimitiveArrayIndices(rangeCallee) ->
ArrayIndicesRangeValue(this, rangeCall)
ArrayIndicesRangeValue(rangeCall)
isCollectionIndices(rangeCallee) ->
CollectionIndicesRangeValue(this, rangeCall)
CollectionIndicesRangeValue(rangeCall)
isCharSequenceIndices(rangeCallee) ->
CharSequenceIndicesRangeValue(this, rangeCall)
CharSequenceIndicesRangeValue(rangeCall)
isComparableRangeTo(rangeCallee) ->
ComparableRangeLiteralRangeValue(this, rangeCall)
else ->
@@ -16,6 +16,10 @@
package org.jetbrains.kotlin.codegen.range.comparison
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.getRangeOrProgressionElementType
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -30,10 +34,44 @@ interface ComparisonGenerator {
}
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
when (type) {
Type.INT_TYPE, Type.SHORT_TYPE, Type.BYTE_TYPE, Type.CHAR_TYPE -> IntComparisonGenerator
Type.LONG_TYPE -> LongComparisonGenerator
Type.FLOAT_TYPE -> FloatComparisonGenerator
Type.DOUBLE_TYPE -> DoubleComparisonGenerator
when {
type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
type == Type.LONG_TYPE -> LongComparisonGenerator
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
else -> throw UnsupportedOperationException("Unexpected primitive type: " + type)
}
}
fun getComparisonGeneratorForRangeContainsCall(codegen: ExpressionCodegen, call: ResolvedCall<out CallableDescriptor>): ComparisonGenerator? {
val descriptor = call.resultingDescriptor
val receiverType = descriptor.extensionReceiverParameter?.type ?: descriptor.dispatchReceiverParameter?.type ?: return null
val elementType = getRangeOrProgressionElementType(receiverType) ?: return null
val valueParameterType = descriptor.valueParameters.singleOrNull()?.type ?: return null
val asmElementType = codegen.asmType(elementType)
val asmValueParameterType = codegen.asmType(valueParameterType)
return when {
asmElementType == asmValueParameterType ->
getComparisonGeneratorForPrimitiveType(asmElementType)
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType.isRepresentedAsPrimitiveInt() ->
IntComparisonGenerator
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType == Type.LONG_TYPE ||
asmValueParameterType.isRepresentedAsPrimitiveInt() && asmElementType == Type.LONG_TYPE ->
LongComparisonGenerator
asmElementType == Type.FLOAT_TYPE && asmValueParameterType == Type.DOUBLE_TYPE ||
asmElementType == Type.DOUBLE_TYPE && asmValueParameterType == Type.FLOAT_TYPE ->
DoubleComparisonGenerator
else -> null
}
}
private fun Type.isRepresentedAsPrimitiveInt() =
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE || this == Type.CHAR_TYPE