Provide intrinsic for in/in! expression with range of Comparable
This commit is contained in:
@@ -20,8 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.RANGES_PACKAGE_FQ_NAME
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitiveNumberClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -128,6 +127,27 @@ fun isCharSequenceIndices(descriptor: CallableDescriptor): Boolean {
|
||||
return KotlinBuiltIns.isCharSequenceOrNullableCharSequence(extensionReceiverType)
|
||||
}
|
||||
|
||||
fun isComparableRangeTo(descriptor: CallableDescriptor): Boolean {
|
||||
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false
|
||||
|
||||
val extensionReceiver = descriptor.original.extensionReceiverParameter ?: return false
|
||||
val extensionReceiverTypeDescriptor = extensionReceiver.type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
|
||||
val upperBoundType = extensionReceiverTypeDescriptor.upperBounds.singleOrNull() ?: return false
|
||||
val upperBoundClassDescriptor = upperBoundType.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
if (!isTopLevelInPackage(upperBoundClassDescriptor, "Comparable", "kotlin")) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
fun isClosedRangeContains(descriptor: CallableDescriptor): Boolean {
|
||||
if (descriptor.name.asString() != "contains") return false
|
||||
val containingClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||
if (!isTopLevelInPackage(containingClassDescriptor, "ClosedRange", "kotlin.ranges")) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun isPrimitiveRangeToExtension(operationReference: KtSimpleNameExpression, bindingContext: BindingContext): Boolean {
|
||||
val resolvedCall = operationReference.getResolvedCallWithAssert(bindingContext)
|
||||
val receiver = resolvedCall.dispatchReceiver as? ExpressionReceiver ?: return false
|
||||
@@ -164,7 +184,7 @@ fun isPrimitiveRangeSpecializationOfType(
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isTopLevelInPackage(descriptor: CallableDescriptor, name: String, packageName: String): Boolean {
|
||||
private fun isTopLevelInPackage(descriptor: DeclarationDescriptor, name: String, packageName: String): Boolean {
|
||||
if (name != descriptor.name.asString()) return false
|
||||
|
||||
val containingDeclaration = descriptor.containingDeclaration as? PackageFragmentDescriptor ?: return false
|
||||
|
||||
+64
-145
@@ -16,160 +16,79 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.range
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.getPrimitiveRangeElementType
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
abstract class AbstractInPrimitiveNumberRangeExpressionGenerator(
|
||||
val codegen: ExpressionCodegen,
|
||||
codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
rangeCall: ResolvedCall<*>,
|
||||
private val isInclusiveHighBound: Boolean
|
||||
) : InExpressionGenerator {
|
||||
protected val asmElementType =
|
||||
AsmTypes.valueTypeForPrimitive(
|
||||
getPrimitiveRangeElementType(rangeCall.resultingDescriptor.returnType!!)
|
||||
)
|
||||
|
||||
private val isInverted =
|
||||
operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
|
||||
|
||||
protected abstract fun genLowBound(): StackValue
|
||||
protected abstract fun genHighBound(): StackValue
|
||||
|
||||
override fun generate(argument: StackValue): BranchedValue =
|
||||
gen(argument).let { if (isInverted) Invert(it) else it }
|
||||
|
||||
private fun gen(argument: StackValue): BranchedValue =
|
||||
object : BranchedValue(argument, null, asmElementType, Opcodes.IFEQ) {
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
if (jumpIfFalse) {
|
||||
// arg1 in low .. high
|
||||
// arg1 >= low && arg1 <[=] high
|
||||
val cmpHighLabel = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
AsmUtil.dup(v, operandType)
|
||||
|
||||
genLowBound().put(operandType, v)
|
||||
v.jumpIfGe(cmpHighLabel)
|
||||
|
||||
AsmUtil.pop(v, operandType)
|
||||
v.goTo(jumpLabel)
|
||||
|
||||
v.mark(cmpHighLabel)
|
||||
genHighBound().put(operandType, v)
|
||||
if (isInclusiveHighBound) {
|
||||
v.jumpIfGt(jumpLabel)
|
||||
}
|
||||
else {
|
||||
v.jumpIfGe(jumpLabel)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// arg1 !in low .. high
|
||||
// arg1 < low || arg1 >[=] high
|
||||
val trueLabel1 = Label()
|
||||
val trueLabel2 = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
AsmUtil.dup(v, operandType)
|
||||
|
||||
genLowBound().put(operandType, v)
|
||||
v.jumpIfLt(trueLabel1)
|
||||
|
||||
genLowBound().put(operandType, v)
|
||||
if (isInclusiveHighBound) {
|
||||
v.jumpIfLe(jumpLabel)
|
||||
}
|
||||
else {
|
||||
v.jumpIfLt(jumpLabel)
|
||||
}
|
||||
v.goTo(trueLabel2)
|
||||
|
||||
v.mark(trueLabel1)
|
||||
AsmUtil.pop(v, operandType)
|
||||
|
||||
v.mark(trueLabel2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun InstructionAdapter.jumpIfGe(label: Label) {
|
||||
when {
|
||||
AsmUtil.isIntPrimitive(operandType) -> ificmpge(label)
|
||||
|
||||
operandType === Type.LONG_TYPE -> {
|
||||
lcmp()
|
||||
ifge(label)
|
||||
}
|
||||
|
||||
operandType === Type.FLOAT_TYPE || operandType === Type.DOUBLE_TYPE -> {
|
||||
cmpg(operandType)
|
||||
ifge(label)
|
||||
}
|
||||
|
||||
else -> throw UnsupportedOperationException("Unexpected type: " + operandType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun InstructionAdapter.jumpIfLe(label: Label) {
|
||||
when {
|
||||
AsmUtil.isIntPrimitive(operandType) -> ificmple(label)
|
||||
|
||||
operandType === Type.LONG_TYPE -> {
|
||||
lcmp()
|
||||
ifle(label)
|
||||
}
|
||||
|
||||
operandType === Type.FLOAT_TYPE || operandType === Type.DOUBLE_TYPE -> {
|
||||
cmpg(operandType)
|
||||
ifle(label)
|
||||
}
|
||||
|
||||
else -> throw UnsupportedOperationException("Unexpected type: " + operandType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun InstructionAdapter.jumpIfGt(label: Label) {
|
||||
when {
|
||||
AsmUtil.isIntPrimitive(operandType) -> ificmpgt(label)
|
||||
|
||||
operandType === Type.LONG_TYPE -> {
|
||||
lcmp()
|
||||
ifgt(label)
|
||||
}
|
||||
|
||||
operandType === Type.FLOAT_TYPE || operandType === Type.DOUBLE_TYPE -> {
|
||||
cmpg(operandType)
|
||||
ifgt(label)
|
||||
}
|
||||
|
||||
else -> throw UnsupportedOperationException("Unexpected type: " + operandType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun InstructionAdapter.jumpIfLt(label: Label) {
|
||||
when {
|
||||
AsmUtil.isIntPrimitive(operandType) -> ificmplt(label)
|
||||
|
||||
operandType === Type.LONG_TYPE -> {
|
||||
lcmp()
|
||||
iflt(label)
|
||||
}
|
||||
|
||||
operandType === Type.FLOAT_TYPE || operandType === Type.DOUBLE_TYPE -> {
|
||||
cmpg(operandType)
|
||||
iflt(label)
|
||||
}
|
||||
|
||||
else -> throw UnsupportedOperationException("Unexpected type: " + operandType)
|
||||
}
|
||||
}
|
||||
isInclusiveHighBound: Boolean
|
||||
) : AbstractInRangeWithKnownBoundsExpressionGenerator(
|
||||
codegen, operatorReference, isInclusiveHighBound, AsmTypes.valueTypeForPrimitive(getPrimitiveRangeElementType(rangeCall.resultingDescriptor.returnType!!))
|
||||
) {
|
||||
override val comparisonGenerator: ComparisonGenerator =
|
||||
when (asmElementType) {
|
||||
Type.INT_TYPE, Type.SHORT_TYPE, Type.BYTE_TYPE, Type.CHAR_TYPE -> PrimitiveIntegerComparisonGenerator
|
||||
Type.LONG_TYPE -> PrimitiveLongComparisonGenerator
|
||||
Type.FLOAT_TYPE, Type.DOUBLE_TYPE -> PrimitiveFloatComparisonGenerator(asmElementType)
|
||||
else -> throw UnsupportedOperationException("Unexpected type: " + asmElementType)
|
||||
}
|
||||
|
||||
private object PrimitiveIntegerComparisonGenerator : ComparisonGenerator {
|
||||
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) = v.ificmpge(label)
|
||||
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) = v.ificmple(label)
|
||||
override fun jumpIfGreater(v: InstructionAdapter, label: Label) = v.ificmpgt(label)
|
||||
override fun jumpIfLess(v: InstructionAdapter, label: Label) = v.ificmplt(label)
|
||||
}
|
||||
|
||||
private object PrimitiveLongComparisonGenerator : ComparisonGenerator {
|
||||
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
|
||||
v.lcmp()
|
||||
v.ifge(label)
|
||||
}
|
||||
|
||||
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) {
|
||||
v.lcmp()
|
||||
v.ifle(label)
|
||||
}
|
||||
|
||||
override fun jumpIfGreater(v: InstructionAdapter, label: Label) {
|
||||
v.lcmp()
|
||||
v.ifgt(label)
|
||||
}
|
||||
|
||||
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
|
||||
v.lcmp()
|
||||
v.iflt(label)
|
||||
}
|
||||
}
|
||||
|
||||
private class PrimitiveFloatComparisonGenerator(val floatType: Type) : ComparisonGenerator {
|
||||
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
|
||||
v.cmpg(floatType)
|
||||
v.ifge(label)
|
||||
}
|
||||
|
||||
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) {
|
||||
v.cmpg(floatType)
|
||||
v.ifle(label)
|
||||
}
|
||||
|
||||
override fun jumpIfGreater(v: InstructionAdapter, label: Label) {
|
||||
v.cmpg(floatType)
|
||||
v.ifgt(label)
|
||||
}
|
||||
|
||||
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
|
||||
v.cmpg(floatType)
|
||||
v.iflt(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.range
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
abstract class AbstractInRangeWithKnownBoundsExpressionGenerator(
|
||||
val codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
protected val isInclusiveHighBound: Boolean,
|
||||
protected val asmElementType: Type
|
||||
) : InExpressionGenerator {
|
||||
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
|
||||
|
||||
protected abstract fun genLowBound(): StackValue
|
||||
protected abstract fun genHighBound(): StackValue
|
||||
|
||||
protected interface ComparisonGenerator {
|
||||
fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label)
|
||||
fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label)
|
||||
fun jumpIfGreater(v: InstructionAdapter, label: Label)
|
||||
fun jumpIfLess(v: InstructionAdapter, label: Label)
|
||||
}
|
||||
|
||||
protected abstract val comparisonGenerator: ComparisonGenerator
|
||||
|
||||
override fun generate(argument: StackValue): BranchedValue =
|
||||
gen(argument).let { if (isNotIn) Invert(it) else it }
|
||||
|
||||
private fun gen(argument: StackValue): BranchedValue =
|
||||
object : BranchedValue(argument, null, asmElementType, Opcodes.IFEQ) {
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
if (jumpIfFalse) {
|
||||
// arg1 in low .. high
|
||||
// arg1 >= low && arg1 <[=] high
|
||||
val cmpHighLabel = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
AsmUtil.dup(v, operandType)
|
||||
|
||||
genLowBound().put(operandType, v)
|
||||
comparisonGenerator.jumpIfGreaterOrEqual(v, cmpHighLabel)
|
||||
|
||||
AsmUtil.pop(v, operandType)
|
||||
v.goTo(jumpLabel)
|
||||
|
||||
v.mark(cmpHighLabel)
|
||||
genHighBound().put(operandType, v)
|
||||
if (isInclusiveHighBound) {
|
||||
comparisonGenerator.jumpIfGreater(v, jumpLabel)
|
||||
}
|
||||
else {
|
||||
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// arg1 !in low .. high
|
||||
// arg1 < low || arg1 >[=] high
|
||||
val trueLabel1 = Label()
|
||||
val trueLabel2 = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
AsmUtil.dup(v, operandType)
|
||||
|
||||
genLowBound().put(operandType, v)
|
||||
comparisonGenerator.jumpIfLess(v, trueLabel1)
|
||||
|
||||
genHighBound().put(operandType, v)
|
||||
if (isInclusiveHighBound) {
|
||||
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
|
||||
}
|
||||
else {
|
||||
comparisonGenerator.jumpIfLess(v, jumpLabel)
|
||||
}
|
||||
v.goTo(trueLabel2)
|
||||
|
||||
v.mark(trueLabel1)
|
||||
AsmUtil.pop(v, operandType)
|
||||
|
||||
v.mark(trueLabel2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.range
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
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.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class InComparableRangeLiteralGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||
) : AbstractInRangeWithKnownBoundsExpressionGenerator(
|
||||
codegen, operatorReference, true,
|
||||
Type.getType("Ljava/lang/Comparable;")
|
||||
) {
|
||||
private val from: ReceiverValue = rangeCall.extensionReceiver!!
|
||||
private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(rangeCall)!!
|
||||
|
||||
override fun genLowBound(): StackValue = codegen.generateReceiverValue(from, false)
|
||||
|
||||
override fun genHighBound(): StackValue = codegen.gen(to)
|
||||
|
||||
override val comparisonGenerator: ComparisonGenerator = ComparableComparisonGenerator
|
||||
|
||||
private object ComparableComparisonGenerator : ComparisonGenerator {
|
||||
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
|
||||
invokeCompare(v)
|
||||
v.ifge(label)
|
||||
}
|
||||
|
||||
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) {
|
||||
invokeCompare(v)
|
||||
v.ifle(label)
|
||||
}
|
||||
|
||||
override fun jumpIfGreater(v: InstructionAdapter, label: Label) {
|
||||
invokeCompare(v)
|
||||
v.ifgt(label)
|
||||
}
|
||||
|
||||
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
|
||||
invokeCompare(v)
|
||||
v.iflt(label)
|
||||
}
|
||||
|
||||
private fun invokeCompare(v: InstructionAdapter) {
|
||||
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen.range
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.forLoop.*
|
||||
import org.jetbrains.kotlin.codegen.isClosedRangeContains
|
||||
import org.jetbrains.kotlin.codegen.isPrimitiveRange
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
@@ -86,7 +87,7 @@ abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall<out
|
||||
}
|
||||
|
||||
abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): CallIntrinsicRangeValue(rangeCall) {
|
||||
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>): Boolean =
|
||||
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
|
||||
resolvedCallForIn.resultingDescriptor.dispatchReceiverParameter?.let {
|
||||
isPrimitiveRange(it.type)
|
||||
} ?: false
|
||||
@@ -96,7 +97,7 @@ class PrimitiveNumberRangeLiteralRangeValue(rangeCall: ResolvedCall<out Callable
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInRangeLiteralLoopGenerator(codegen, forExpression, rangeCall)
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
|
||||
InPrimitiveNumberRangeLiteralGenerator(codegen, operatorReference, rangeCall)
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ class DownToProgressionRangeValue(rangeCall: ResolvedCall<out CallableDescriptor
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInDownToProgressionLoopGenerator(codegen, forExpression, rangeCall)
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
|
||||
InPrimitiveNumberDownToGenerator(codegen, operatorReference, rangeCall)
|
||||
}
|
||||
|
||||
@@ -112,7 +113,7 @@ class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescrip
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInUntilRangeLoopGenerator(codegen, forExpression, rangeCall)
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
|
||||
InPrimitiveNumberUntilGenerator(codegen, operatorReference, rangeCall)
|
||||
}
|
||||
|
||||
@@ -120,7 +121,7 @@ class ArrayIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): P
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInArrayIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
|
||||
InArrayIndicesGenerator(codegen, operatorReference, rangeCall)
|
||||
}
|
||||
|
||||
@@ -128,7 +129,7 @@ class CollectionIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInCollectionIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
|
||||
InCollectionIndicesGenerator(codegen, operatorReference, rangeCall)
|
||||
}
|
||||
|
||||
@@ -136,6 +137,17 @@ class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescript
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInCharSequenceIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) =
|
||||
InCharSequenceIndicesGenerator(codegen, operatorReference, rangeCall)
|
||||
}
|
||||
|
||||
class ComparableRangeLiteralRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): CallIntrinsicRangeValue(rangeCall) {
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
IteratorForLoopGenerator(codegen, forExpression)
|
||||
|
||||
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
|
||||
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression)=
|
||||
InComparableRangeLiteralGenerator(codegen, operatorReference, rangeCall)
|
||||
}
|
||||
@@ -95,6 +95,8 @@ private fun createIntrinsifiedRangeValueOrNull(rangeCall: ResolvedCall<out Calla
|
||||
CollectionIndicesRangeValue(rangeCall)
|
||||
isCharSequenceIndices(rangeCallee) ->
|
||||
CharSequenceIndicesRangeValue(rangeCall)
|
||||
isComparableRangeTo(rangeCallee) ->
|
||||
ComparableRangeLiteralRangeValue(rangeCall)
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun box(): String {
|
||||
if ("z" in "Alpha" .. "Omega") return "Fail 1"
|
||||
if ("Gamma" !in "Alpha" .. "Omega") return "Fail 2"
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -13249,6 +13249,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inRangeOfComparable.kt")
|
||||
public void testInRangeOfComparable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeOfComparable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inRangeWithCustomContains.kt")
|
||||
public void testInRangeWithCustomContains() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
||||
|
||||
@@ -13249,6 +13249,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inRangeOfComparable.kt")
|
||||
public void testInRangeOfComparable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeOfComparable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inRangeWithCustomContains.kt")
|
||||
public void testInRangeWithCustomContains() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
||||
|
||||
@@ -13249,6 +13249,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inRangeOfComparable.kt")
|
||||
public void testInRangeOfComparable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeOfComparable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inRangeWithCustomContains.kt")
|
||||
public void testInRangeWithCustomContains() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
||||
|
||||
@@ -14899,6 +14899,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inRangeOfComparable.kt")
|
||||
public void testInRangeOfComparable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeOfComparable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inRangeWithCustomContains.kt")
|
||||
public void testInRangeWithCustomContains() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
||||
|
||||
Reference in New Issue
Block a user