Introduce BoundedValue as a generalization of (low..high) range
Provide BoundedValue-based implementation of InExpressionGenerator, test it on range of comparable values. Drop unneeded test (range of comparables is already tested by ranges/contains/inComparableRanges.kt).
This commit is contained in:
@@ -798,6 +798,16 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void pop2(@NotNull MethodVisitor v, @NotNull Type type) {
|
||||||
|
if (type.getSize() == 2) {
|
||||||
|
v.visitInsn(Opcodes.POP2);
|
||||||
|
v.visitInsn(Opcodes.POP2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.visitInsn(Opcodes.POP2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) {
|
public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) {
|
||||||
dup(v, type.getSize());
|
dup(v, type.getSize());
|
||||||
}
|
}
|
||||||
@@ -814,6 +824,22 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void dupx(@NotNull InstructionAdapter v, @NotNull Type type) {
|
||||||
|
dupx(v, type.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void dupx(@NotNull InstructionAdapter v, int size) {
|
||||||
|
if (size == 2) {
|
||||||
|
v.dup2X2();
|
||||||
|
}
|
||||||
|
else if (size == 1) {
|
||||||
|
v.dupX1();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void dup(@NotNull InstructionAdapter v, @NotNull Type topOfStack, @NotNull Type afterTop) {
|
public static void dup(@NotNull InstructionAdapter v, @NotNull Type topOfStack, @NotNull Type afterTop) {
|
||||||
if (topOfStack.getSize() == 0 && afterTop.getSize() == 0) {
|
if (topOfStack.getSize() == 0 && afterTop.getSize() == 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+31
-4
@@ -17,15 +17,27 @@
|
|||||||
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.forLoop.IteratorForLoopGenerator
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.isClosedRangeContains
|
import org.jetbrains.kotlin.codegen.isClosedRangeContains
|
||||||
import org.jetbrains.kotlin.codegen.range.inExpression.InComparableRangeLiteralGenerator
|
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.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(
|
||||||
|
private val codegen: ExpressionCodegen,
|
||||||
|
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||||
|
) : CallIntrinsicRangeValue(rangeCall), BoundedValue {
|
||||||
|
private val from: ReceiverValue = rangeCall.extensionReceiver!!
|
||||||
|
private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(rangeCall)!!
|
||||||
|
|
||||||
class ComparableRangeLiteralRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): CallIntrinsicRangeValue(rangeCall) {
|
|
||||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||||
IteratorForLoopGenerator(codegen, forExpression)
|
IteratorForLoopGenerator(codegen, forExpression)
|
||||||
|
|
||||||
@@ -33,5 +45,20 @@ class ComparableRangeLiteralRangeValue(rangeCall: ResolvedCall<out CallableDescr
|
|||||||
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
|
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
|
||||||
|
|
||||||
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression)=
|
override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression)=
|
||||||
InComparableRangeLiteralGenerator(codegen, operatorReference, rangeCall)
|
InContinuousRangeExpressionGenerator(operatorReference, this, ObjectComparisonGenerator)
|
||||||
|
|
||||||
|
override val instanceType: Type =
|
||||||
|
codegen.asmType(rangeCall.resultingDescriptor.returnType!!)
|
||||||
|
|
||||||
|
override fun putInstance(v: InstructionAdapter) {
|
||||||
|
codegen.invokeFunction(rangeCall.call, rangeCall, StackValue.none()).put(instanceType, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putHighLow(v: InstructionAdapter, type: Type) {
|
||||||
|
codegen.gen(to).put(type, v)
|
||||||
|
codegen.generateReceiverValue(from, false).put(type, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isLowInclusive = true
|
||||||
|
override val isHighInclusive = true
|
||||||
}
|
}
|
||||||
@@ -17,13 +17,35 @@
|
|||||||
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.range.forLoop.ForLoopGenerator
|
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
|
||||||
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
|
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
|
||||||
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.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
interface RangeValue {
|
interface RangeValue {
|
||||||
fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator
|
fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator
|
||||||
|
|
||||||
fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator
|
fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface BoundedValue {
|
||||||
|
val instanceType: Type
|
||||||
|
|
||||||
|
fun putInstance(v: InstructionAdapter)
|
||||||
|
|
||||||
|
fun putHighLow(v: InstructionAdapter, type: Type)
|
||||||
|
val isLowInclusive: Boolean
|
||||||
|
val isHighInclusive: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
fun BoundedValue.asStackValue(): StackValue =
|
||||||
|
object : StackValue(instanceType) {
|
||||||
|
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||||
|
putInstance(v)
|
||||||
|
StackValue.onStack(instanceType).put(type, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ private fun getResolvedCallForRangeExpression(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createIntrinsifiedRangeValueOrNull(rangeCall: ResolvedCall<out CallableDescriptor>): RangeValue? {
|
private fun ExpressionCodegen.createIntrinsifiedRangeValueOrNull(rangeCall: ResolvedCall<out CallableDescriptor>): RangeValue? {
|
||||||
val rangeCallee = rangeCall.resultingDescriptor
|
val rangeCallee = rangeCall.resultingDescriptor
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
@@ -96,7 +96,7 @@ private fun createIntrinsifiedRangeValueOrNull(rangeCall: ResolvedCall<out Calla
|
|||||||
isCharSequenceIndices(rangeCallee) ->
|
isCharSequenceIndices(rangeCallee) ->
|
||||||
CharSequenceIndicesRangeValue(rangeCall)
|
CharSequenceIndicesRangeValue(rangeCall)
|
||||||
isComparableRangeTo(rangeCallee) ->
|
isComparableRangeTo(rangeCallee) ->
|
||||||
ComparableRangeLiteralRangeValue(rangeCall)
|
ComparableRangeLiteralRangeValue(this, rangeCall)
|
||||||
else ->
|
else ->
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.comparison
|
||||||
|
|
||||||
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
|
interface ComparisonGenerator {
|
||||||
|
val comparedType: Type
|
||||||
|
|
||||||
|
fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label)
|
||||||
|
fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label)
|
||||||
|
fun jumpIfGreater(v: InstructionAdapter, label: Label)
|
||||||
|
fun jumpIfLess(v: InstructionAdapter, label: Label)
|
||||||
|
}
|
||||||
|
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.comparison
|
||||||
|
|
||||||
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
|
sealed class FloatingPointComparisonGenerator(override val comparedType: Type): ComparisonGenerator {
|
||||||
|
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
|
||||||
|
v.cmpl(comparedType)
|
||||||
|
v.ifge(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) {
|
||||||
|
v.cmpg(comparedType)
|
||||||
|
v.ifle(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun jumpIfGreater(v: InstructionAdapter, label: Label) {
|
||||||
|
v.cmpl(comparedType)
|
||||||
|
v.ifgt(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
|
||||||
|
v.cmpg(comparedType)
|
||||||
|
v.iflt(label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object FloatComparisonGenerator : FloatingPointComparisonGenerator(Type.FLOAT_TYPE)
|
||||||
|
|
||||||
|
object DoubleComparisonGenerator : FloatingPointComparisonGenerator(Type.DOUBLE_TYPE)
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.comparison
|
||||||
|
|
||||||
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
|
object IntComparisonGenerator : ComparisonGenerator {
|
||||||
|
override val comparedType: Type = Type.INT_TYPE
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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.comparison
|
||||||
|
|
||||||
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
|
object LongComparisonGenerator : ComparisonGenerator {
|
||||||
|
override val comparedType: Type = Type.LONG_TYPE
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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.comparison
|
||||||
|
|
||||||
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
|
object ObjectComparisonGenerator : ComparisonGenerator {
|
||||||
|
override val comparedType: Type = Type.getObjectType("java/lang/Comparable")
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-60
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|||||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.getClosedFloatingPointRangeElementType
|
import org.jetbrains.kotlin.codegen.getClosedFloatingPointRangeElementType
|
||||||
import org.jetbrains.kotlin.codegen.getPrimitiveRangeElementType
|
import org.jetbrains.kotlin.codegen.getPrimitiveRangeElementType
|
||||||
|
import org.jetbrains.kotlin.codegen.range.comparison.*
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
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
|
||||||
@@ -39,62 +40,12 @@ abstract class AbstractInPrimitiveNumberRangeExpressionGenerator(
|
|||||||
) {
|
) {
|
||||||
override val comparisonGenerator: ComparisonGenerator =
|
override val comparisonGenerator: ComparisonGenerator =
|
||||||
when (asmElementType) {
|
when (asmElementType) {
|
||||||
Type.INT_TYPE, Type.SHORT_TYPE, Type.BYTE_TYPE, Type.CHAR_TYPE -> PrimitiveIntegerComparisonGenerator
|
Type.INT_TYPE, Type.SHORT_TYPE, Type.BYTE_TYPE, Type.CHAR_TYPE -> IntComparisonGenerator
|
||||||
Type.LONG_TYPE -> PrimitiveLongComparisonGenerator
|
Type.LONG_TYPE -> LongComparisonGenerator
|
||||||
Type.FLOAT_TYPE, Type.DOUBLE_TYPE -> PrimitiveFloatComparisonGenerator(asmElementType)
|
Type.FLOAT_TYPE -> FloatComparisonGenerator
|
||||||
|
Type.DOUBLE_TYPE -> DoubleComparisonGenerator
|
||||||
else -> throw UnsupportedOperationException("Unexpected type: " + 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -108,10 +59,9 @@ internal fun getAsmRangeElementTypeForPrimitiveRange(rangeCallee: CallableDescri
|
|||||||
val floatingPointElementType = getClosedFloatingPointRangeElementType(rangeType) ?:
|
val floatingPointElementType = getClosedFloatingPointRangeElementType(rangeType) ?:
|
||||||
throw AssertionError("Unexpected range type: $rangeType")
|
throw AssertionError("Unexpected range type: $rangeType")
|
||||||
|
|
||||||
if (KotlinBuiltIns.isDouble(floatingPointElementType))
|
return when {
|
||||||
return Type.DOUBLE_TYPE
|
KotlinBuiltIns.isDouble(floatingPointElementType) -> Type.DOUBLE_TYPE
|
||||||
else if (KotlinBuiltIns.isFloat(floatingPointElementType))
|
KotlinBuiltIns.isFloat(floatingPointElementType) -> Type.FLOAT_TYPE
|
||||||
return Type.FLOAT_TYPE
|
else -> throw AssertionError("Unexpected ClosedFloatingPointRange element type: $floatingPointElementType")
|
||||||
else
|
}
|
||||||
throw AssertionError("Unexpected ClosedFloatingPointRange element type: $floatingPointElementType")
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-7
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.codegen.range.inExpression
|
package org.jetbrains.kotlin.codegen.range.inExpression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
|
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
@@ -35,13 +36,6 @@ abstract class AbstractInRangeWithKnownBoundsExpressionGenerator(
|
|||||||
protected abstract fun genLowBound(): StackValue
|
protected abstract fun genLowBound(): StackValue
|
||||||
protected abstract fun genHighBound(): 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
|
protected abstract val comparisonGenerator: ComparisonGenerator
|
||||||
|
|
||||||
override fun generate(argument: StackValue): BranchedValue =
|
override fun generate(argument: StackValue): BranchedValue =
|
||||||
|
|||||||
+3
-27
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.codegen.range.inExpression
|
|||||||
|
|
||||||
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.range.comparison.ComparisonGenerator
|
||||||
|
import org.jetbrains.kotlin.codegen.range.comparison.ObjectComparisonGenerator
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
@@ -42,31 +44,5 @@ class InComparableRangeLiteralGenerator(
|
|||||||
|
|
||||||
override fun genHighBound(): StackValue = codegen.gen(to)
|
override fun genHighBound(): StackValue = codegen.gen(to)
|
||||||
|
|
||||||
override val comparisonGenerator: ComparisonGenerator = ComparableComparisonGenerator
|
override val comparisonGenerator: ComparisonGenerator = ObjectComparisonGenerator
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+128
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* 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.inExpression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.BranchedValue
|
||||||
|
import org.jetbrains.kotlin.codegen.Invert
|
||||||
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
|
import org.jetbrains.kotlin.codegen.range.BoundedValue
|
||||||
|
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
|
||||||
|
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.commons.InstructionAdapter
|
||||||
|
|
||||||
|
class InContinuousRangeExpressionGenerator(
|
||||||
|
operatorReference: KtSimpleNameExpression,
|
||||||
|
private val boundedValue: BoundedValue,
|
||||||
|
private val comparisonGenerator: ComparisonGenerator
|
||||||
|
) : InExpressionGenerator {
|
||||||
|
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
|
||||||
|
|
||||||
|
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, comparisonGenerator.comparedType, Opcodes.IFEQ) {
|
||||||
|
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||||
|
if (jumpIfFalse) {
|
||||||
|
genJumpIfFalse(v, jumpLabel)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
genJumpIfTrue(v, jumpLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
|
||||||
|
// if (arg is in range) goto jumpLabel
|
||||||
|
|
||||||
|
val exitLabel1 = Label()
|
||||||
|
val exitLabel2 = Label()
|
||||||
|
|
||||||
|
boundedValue.putHighLow(v, operandType)
|
||||||
|
arg1.put(operandType, v)
|
||||||
|
AsmUtil.dupx(v, operandType)
|
||||||
|
|
||||||
|
// On stack: high arg low arg
|
||||||
|
// if (low bound is NOT satisfied) goto exitLabel1
|
||||||
|
if (boundedValue.isLowInclusive) {
|
||||||
|
// low > arg
|
||||||
|
comparisonGenerator.jumpIfGreater(v, exitLabel1)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// low >= arg
|
||||||
|
comparisonGenerator.jumpIfGreaterOrEqual(v, exitLabel1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// On stack: high arg
|
||||||
|
// if (high bound is satisfied) goto jumpLabel
|
||||||
|
if (boundedValue.isHighInclusive) {
|
||||||
|
// high >= arg
|
||||||
|
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// high > arg
|
||||||
|
comparisonGenerator.jumpIfGreater(v, jumpLabel)
|
||||||
|
}
|
||||||
|
v.goTo(exitLabel2)
|
||||||
|
|
||||||
|
v.mark(exitLabel1)
|
||||||
|
AsmUtil.pop2(v, operandType)
|
||||||
|
|
||||||
|
v.mark(exitLabel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
|
||||||
|
// if (arg is NOT in range) goto jumpLabel
|
||||||
|
|
||||||
|
val cmpHighLabel = Label()
|
||||||
|
|
||||||
|
boundedValue.putHighLow(v, operandType)
|
||||||
|
arg1.put(operandType, v)
|
||||||
|
AsmUtil.dupx(v, operandType)
|
||||||
|
|
||||||
|
// On stack: high arg low arg
|
||||||
|
// if ([low bound is satisfied]) goto cmpHighLabel
|
||||||
|
if (boundedValue.isLowInclusive) {
|
||||||
|
// low <= arg
|
||||||
|
comparisonGenerator.jumpIfLessOrEqual(v, cmpHighLabel)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// low < arg
|
||||||
|
comparisonGenerator.jumpIfLess(v, cmpHighLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low bound is NOT satisfied, clear stack and goto jumpLabel
|
||||||
|
AsmUtil.pop2(v, operandType)
|
||||||
|
v.goTo(jumpLabel)
|
||||||
|
|
||||||
|
v.mark(cmpHighLabel)
|
||||||
|
// On stack: high arg
|
||||||
|
// if ([high bound is NOT satisfied]) goto jumpLabel
|
||||||
|
if (boundedValue.isHighInclusive) {
|
||||||
|
// high < arg
|
||||||
|
comparisonGenerator.jumpIfLess(v, jumpLabel)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// high <= arg
|
||||||
|
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
// WITH_RUNTIME
|
|
||||||
|
|
||||||
fun box(): String {
|
|
||||||
if ("z" in "Alpha" .. "Omega") return "Fail 1"
|
|
||||||
if ("Gamma" !in "Alpha" .. "Omega") return "Fail 2"
|
|
||||||
return "OK"
|
|
||||||
}
|
|
||||||
-6
@@ -13279,12 +13279,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("inRangeWithCustomContains.kt")
|
||||||
public void testInRangeWithCustomContains() throws Exception {
|
public void testInRangeWithCustomContains() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
||||||
|
|||||||
@@ -13279,12 +13279,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("inRangeWithCustomContains.kt")
|
||||||
public void testInRangeWithCustomContains() throws Exception {
|
public void testInRangeWithCustomContains() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
||||||
|
|||||||
@@ -13279,12 +13279,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("inRangeWithCustomContains.kt")
|
||||||
public void testInRangeWithCustomContains() throws Exception {
|
public void testInRangeWithCustomContains() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
||||||
|
|||||||
@@ -14935,12 +14935,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("inRangeWithCustomContains.kt")
|
||||||
public void testInRangeWithCustomContains() throws Exception {
|
public void testInRangeWithCustomContains() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inRangeWithCustomContains.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user