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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type 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> = private val RANGE_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
supportedRangeTypes().associateBy { supportedRangeTypes.associateBy {
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Range")) RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Range"))
} }
private val PROGRESSION_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> = private val PROGRESSION_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
supportedRangeTypes().associateBy { supportedRangeTypes.associateBy {
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Progression")) RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Progression"))
} }
fun supportedRangeTypes() =
listOf(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG)
fun isPrimitiveRange(rangeType: KotlinType) = fun isPrimitiveRange(rangeType: KotlinType) =
!rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null !rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null
fun isPrimitiveProgression(rangeType: KotlinType) = fun isPrimitiveProgression(rangeType: KotlinType) =
!rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null !rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null
fun getPrimitiveRangeElementType(rangeType: KotlinType) = fun getPrimitiveRangeElementType(rangeType: KotlinType): PrimitiveType? =
getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE) getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE)
private fun getPrimitiveProgressionElementType(rangeType: KotlinType) = private fun getPrimitiveProgressionElementType(rangeType: KotlinType) =
@@ -62,6 +62,32 @@ private fun getPrimitiveRangeOrProgressionElementType(
return map[fqName.toSafe()] 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? = fun getPrimitiveRangeOrProgressionElementType(rangeOrProgressionName: FqName): PrimitiveType? =
RANGE_TO_ELEMENT_TYPE[rangeOrProgressionName] ?: RANGE_TO_ELEMENT_TYPE[rangeOrProgressionName] ?:
PROGRESSION_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; private final static ImmutableMap<String, Type> VALUES_TYPENAME_TO_TYPE;
static { static {
ImmutableMap.Builder<String, Type> builder = ImmutableMap.builder(); 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())); builder.put(primitiveType.getTypeName().asString(), Type.getType(JvmPrimitiveType.get(primitiveType).getDesc()));
} }
VALUES_TYPENAME_TO_TYPE = builder.build(); 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; private static final ImmutableMap<PrimitiveType, ProgressionIteratorBasicValue> ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE;
static { static {
ImmutableMap.Builder<PrimitiveType, ProgressionIteratorBasicValue> builder = ImmutableMap.builder(); 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())); builder.put(elementType, new ProgressionIteratorBasicValue(elementType.getTypeName().asString()));
} }
ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE = builder.build(); 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.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.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInArrayIndicesRangeLoopGenerator 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.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression 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.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
class ArrayIndicesRangeValue( class ArrayIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
private val boundedValue = override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue( SimpleBoundedValue(
codegen, rangeCall, codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType), lowBound = StackValue.constant(0, asmElementType),
@@ -49,6 +42,4 @@ class ArrayIndicesRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInArrayIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) 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 package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen 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.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor 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 { abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall<out CallableDescriptor>): RangeValue {
protected abstract fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>): Boolean 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 { override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator {
val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext) val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext)
return if (isIntrinsicInCall(resolvedCall)) return if (isIntrinsicInCall(resolvedCall))
createIntrinsicInExpressionGenerator(codegen, operatorReference) createIntrinsicInExpressionGenerator(codegen, operatorReference, resolvedCall)
else else
CallBasedInExpressionGenerator(codegen, operatorReference) CallBasedInExpressionGenerator(codegen, operatorReference)
} }
@@ -19,24 +19,17 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen 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.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInCharSequenceIndicesRangeLoopGenerator 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.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression 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.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
class CharSequenceIndicesRangeValue( class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
private val boundedValue = override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue( SimpleBoundedValue(
codegen, rangeCall, codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType), lowBound = StackValue.constant(0, asmElementType),
@@ -48,7 +41,4 @@ class CharSequenceIndicesRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInCharSequenceIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) 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.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.range.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInCollectionIndicesRangeLoopGenerator 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.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression 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.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
class CollectionIndicesRangeValue( class CollectionIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
private val boundedValue = override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue( SimpleBoundedValue(
codegen, rangeCall, codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType), lowBound = StackValue.constant(0, asmElementType),
@@ -48,7 +41,4 @@ class CollectionIndicesRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInCollectionIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) 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 package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.isClosedRangeContains import org.jetbrains.kotlin.codegen.isClosedRangeContains
import org.jetbrains.kotlin.codegen.range.comparison.ObjectComparisonGenerator import org.jetbrains.kotlin.codegen.range.comparison.ObjectComparisonGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.IteratorForLoopGenerator import org.jetbrains.kotlin.codegen.range.forLoop.IteratorForLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
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.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall 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( class ComparableRangeLiteralRangeValue(
codegen: ExpressionCodegen, codegen: ExpressionCodegen,
@@ -43,6 +38,6 @@ class ComparableRangeLiteralRangeValue(
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) = override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
isClosedRangeContains(resolvedCallForIn.resultingDescriptor) 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) 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.ExpressionCodegen
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.comparison.getComparisonGeneratorForPrimitiveType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInDownToProgressionLoopGenerator 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.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression 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.calls.model.ResolvedCall
class DownToProgressionRangeValue( class DownToProgressionRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
codegen: ExpressionCodegen, override fun getBoundedValue(codegen: ExpressionCodegen) =
rangeCall: ResolvedCall<out CallableDescriptor>
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val boundedValue =
SimpleBoundedValue( SimpleBoundedValue(
codegen, rangeCall, codegen, rangeCall,
lowBound = codegen.generateCallSingleArgument(rangeCall), lowBound = codegen.generateCallSingleArgument(rangeCall),
@@ -42,7 +34,4 @@ class DownToProgressionRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInDownToProgressionLoopGenerator(codegen, forExpression, rangeCall) 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 package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.getAsmRangeElementTypeForPrimitiveRangeOrProgression import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.isClosedFloatingPointRangeContains import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
import org.jetbrains.kotlin.codegen.isIntPrimitiveRangeExtensionForInt import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
import org.jetbrains.kotlin.codegen.isPrimitiveRangeContains 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.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): CallIntrinsicRangeValue(rangeCall) { abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): CallIntrinsicRangeValue(rangeCall) {
@@ -32,4 +35,18 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<o
isClosedFloatingPointRangeContains(it) || isClosedFloatingPointRangeContains(it) ||
isIntPrimitiveRangeExtensionForInt(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 package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen 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.forLoop.ForInRangeLiteralLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression 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.calls.model.ResolvedCall
class PrimitiveNumberRangeLiteralRangeValue( class PrimitiveNumberRangeLiteralRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
codegen: ExpressionCodegen, override fun getBoundedValue(codegen: ExpressionCodegen) =
rangeCall: ResolvedCall<out CallableDescriptor> SimpleBoundedValue(codegen, rangeCall)
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val boundedValue = SimpleBoundedValue(codegen, rangeCall)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInRangeLiteralLoopGenerator(codegen, forExpression, rangeCall) 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 package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen 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.forLoop.ForInUntilRangeLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression 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.calls.model.ResolvedCall
class PrimitiveNumberUntilRangeValue( class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
codegen: ExpressionCodegen, override fun getBoundedValue(codegen: ExpressionCodegen) =
rangeCall: ResolvedCall<out CallableDescriptor> SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
private val boundedValue = SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInUntilRangeLoopGenerator(codegen, forExpression, rangeCall) 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 { return when {
isPrimitiveNumberRangeTo(rangeCallee) -> isPrimitiveNumberRangeTo(rangeCallee) ->
PrimitiveNumberRangeLiteralRangeValue(this, rangeCall) PrimitiveNumberRangeLiteralRangeValue(rangeCall)
isPrimitiveNumberDownTo(rangeCallee) -> isPrimitiveNumberDownTo(rangeCallee) ->
DownToProgressionRangeValue(this, rangeCall) DownToProgressionRangeValue(rangeCall)
isPrimitiveNumberUntil(rangeCallee) -> isPrimitiveNumberUntil(rangeCallee) ->
PrimitiveNumberUntilRangeValue(this, rangeCall) PrimitiveNumberUntilRangeValue(rangeCall)
isArrayOrPrimitiveArrayIndices(rangeCallee) -> isArrayOrPrimitiveArrayIndices(rangeCallee) ->
ArrayIndicesRangeValue(this, rangeCall) ArrayIndicesRangeValue(rangeCall)
isCollectionIndices(rangeCallee) -> isCollectionIndices(rangeCallee) ->
CollectionIndicesRangeValue(this, rangeCall) CollectionIndicesRangeValue(rangeCall)
isCharSequenceIndices(rangeCallee) -> isCharSequenceIndices(rangeCallee) ->
CharSequenceIndicesRangeValue(this, rangeCall) CharSequenceIndicesRangeValue(rangeCall)
isComparableRangeTo(rangeCallee) -> isComparableRangeTo(rangeCallee) ->
ComparableRangeLiteralRangeValue(this, rangeCall) ComparableRangeLiteralRangeValue(this, rangeCall)
else -> else ->
@@ -16,6 +16,10 @@
package org.jetbrains.kotlin.codegen.range.comparison 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.Label
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -30,10 +34,44 @@ interface ComparisonGenerator {
} }
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator = fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
when (type) { when {
Type.INT_TYPE, Type.SHORT_TYPE, Type.BYTE_TYPE, Type.CHAR_TYPE -> IntComparisonGenerator type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
Type.LONG_TYPE -> LongComparisonGenerator type == Type.LONG_TYPE -> LongComparisonGenerator
Type.FLOAT_TYPE -> FloatComparisonGenerator type == Type.FLOAT_TYPE -> FloatComparisonGenerator
Type.DOUBLE_TYPE -> DoubleComparisonGenerator type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
else -> throw UnsupportedOperationException("Unexpected primitive type: " + type) 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