From a3409b46b00ac560de8fbc828e46fb06f1aed3f1 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 5 Jul 2017 16:23:27 +0300 Subject: [PATCH] Primitive number range literal as BoundedValue --- .../kotlin/codegen/RangeCodegenUtil.kt | 19 ++++++++ .../PrimitiveNumberRangeLiteralRangeValue.kt | 35 ++++++++++++-- .../kotlin/codegen/range/RangeValues.kt | 2 +- .../range/comparison/ComparisonGenerator.kt | 8 ++++ ...PrimitiveNumberRangeExpressionGenerator.kt | 35 +------------- .../InComparableRangeLiteralGenerator.kt | 48 ------------------- .../InPrimitiveNumberRangeLiteralGenerator.kt | 38 --------------- 7 files changed, 62 insertions(+), 123 deletions(-) delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InComparableRangeLiteralGenerator.kt delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberRangeLiteralGenerator.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt index 21cfeef555c..cc330bf7de4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt @@ -24,7 +24,9 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.org.objectweb.asm.Type private val RANGE_TO_ELEMENT_TYPE: Map = supportedRangeTypes().associateBy { @@ -188,3 +190,20 @@ private fun isTopLevelInPackage(descriptor: DeclarationDescriptor, name: String, val packageFqName = containingDeclaration.fqName.asString() return packageName == packageFqName } + +fun getAsmRangeElementTypeForPrimitiveRange(rangeCallee: CallableDescriptor): Type { + val rangeType = rangeCallee.returnType!! + + getPrimitiveRangeElementType(rangeType)?.let { + return AsmTypes.valueTypeForPrimitive(it) + } + + val floatingPointElementType = getClosedFloatingPointRangeElementType(rangeType) ?: + throw AssertionError("Unexpected range type: $rangeType") + + return when { + KotlinBuiltIns.isDouble(floatingPointElementType) -> Type.DOUBLE_TYPE + KotlinBuiltIns.isFloat(floatingPointElementType) -> Type.FLOAT_TYPE + else -> throw AssertionError("Unexpected ClosedFloatingPointRange element type: $floatingPointElementType") + } +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt index ed66de564a6..ec26da9878e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt @@ -17,17 +17,46 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.codegen.getAsmRangeElementTypeForPrimitiveRange +import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType import org.jetbrains.kotlin.codegen.range.forLoop.ForInRangeLiteralLoopGenerator -import org.jetbrains.kotlin.codegen.range.inExpression.InPrimitiveNumberRangeLiteralGenerator +import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +class PrimitiveNumberRangeLiteralRangeValue( + private val codegen: ExpressionCodegen, + rangeCall: ResolvedCall +): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), BoundedValue { + private val asmElementType = getAsmRangeElementTypeForPrimitiveRange(rangeCall.resultingDescriptor) + private val from: ReceiverValue = rangeCall.dispatchReceiver ?: rangeCall.extensionReceiver!! + private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(rangeCall)!! -class PrimitiveNumberRangeLiteralRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInRangeLiteralLoopGenerator(codegen, forExpression, rangeCall) override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) = - InPrimitiveNumberRangeLiteralGenerator(codegen, operatorReference, rangeCall) + InContinuousRangeExpressionGenerator(operatorReference, this, getComparisonGeneratorForPrimitiveType(asmElementType)) + + 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: Boolean = true + override val isHighInclusive: Boolean = true } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt index 7a72585169e..14fc71f006b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt @@ -84,7 +84,7 @@ private fun ExpressionCodegen.createIntrinsifiedRangeValueOrNull(rangeCall: Reso return when { isPrimitiveNumberRangeTo(rangeCallee) -> - PrimitiveNumberRangeLiteralRangeValue(rangeCall) + PrimitiveNumberRangeLiteralRangeValue(this, rangeCall) isPrimitiveNumberDownTo(rangeCallee) -> DownToProgressionRangeValue(rangeCall) isPrimitiveNumberUntil(rangeCallee) -> diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/comparison/ComparisonGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/comparison/ComparisonGenerator.kt index dd0b6b022be..79f878efcfd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/comparison/ComparisonGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/comparison/ComparisonGenerator.kt @@ -29,3 +29,11 @@ interface ComparisonGenerator { fun jumpIfLess(v: InstructionAdapter, label: Label) } +fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator = + when (type) { + Type.INT_TYPE, Type.SHORT_TYPE, Type.BYTE_TYPE, Type.CHAR_TYPE -> IntComparisonGenerator + Type.LONG_TYPE -> LongComparisonGenerator + Type.FLOAT_TYPE -> FloatComparisonGenerator + Type.DOUBLE_TYPE -> DoubleComparisonGenerator + else -> throw UnsupportedOperationException("Unexpected primitive type: " + type) + } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInPrimitiveNumberRangeExpressionGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInPrimitiveNumberRangeExpressionGenerator.kt index ebafb111222..9dfa0f966d6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInPrimitiveNumberRangeExpressionGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInPrimitiveNumberRangeExpressionGenerator.kt @@ -16,18 +16,12 @@ package org.jetbrains.kotlin.codegen.range.inExpression -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.getClosedFloatingPointRangeElementType -import org.jetbrains.kotlin.codegen.getPrimitiveRangeElementType +import org.jetbrains.kotlin.codegen.getAsmRangeElementTypeForPrimitiveRange import org.jetbrains.kotlin.codegen.range.comparison.* -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.jvm.AsmTypes -import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Type -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter abstract class AbstractInPrimitiveNumberRangeExpressionGenerator( codegen: ExpressionCodegen, @@ -38,30 +32,5 @@ abstract class AbstractInPrimitiveNumberRangeExpressionGenerator( codegen, operatorReference, isInclusiveHighBound, getAsmRangeElementTypeForPrimitiveRange(rangeCall.resultingDescriptor) ) { - override val comparisonGenerator: ComparisonGenerator = - when (asmElementType) { - Type.INT_TYPE, Type.SHORT_TYPE, Type.BYTE_TYPE, Type.CHAR_TYPE -> IntComparisonGenerator - Type.LONG_TYPE -> LongComparisonGenerator - Type.FLOAT_TYPE -> FloatComparisonGenerator - Type.DOUBLE_TYPE -> DoubleComparisonGenerator - else -> throw UnsupportedOperationException("Unexpected type: " + asmElementType) - } -} - - -internal fun getAsmRangeElementTypeForPrimitiveRange(rangeCallee: CallableDescriptor): Type { - val rangeType = rangeCallee.returnType!! - - getPrimitiveRangeElementType(rangeType)?.let { - return AsmTypes.valueTypeForPrimitive(it) - } - - val floatingPointElementType = getClosedFloatingPointRangeElementType(rangeType) ?: - throw AssertionError("Unexpected range type: $rangeType") - - return when { - KotlinBuiltIns.isDouble(floatingPointElementType) -> Type.DOUBLE_TYPE - KotlinBuiltIns.isFloat(floatingPointElementType) -> Type.FLOAT_TYPE - else -> throw AssertionError("Unexpected ClosedFloatingPointRange element type: $floatingPointElementType") - } + override val comparisonGenerator: ComparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InComparableRangeLiteralGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InComparableRangeLiteralGenerator.kt deleted file mode 100644 index a607865316f..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InComparableRangeLiteralGenerator.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.ExpressionCodegen -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.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 -) : 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 = ObjectComparisonGenerator -} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberRangeLiteralGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberRangeLiteralGenerator.kt deleted file mode 100644 index a3e6e2d0acd..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberRangeLiteralGenerator.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -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 - -class InPrimitiveNumberRangeLiteralGenerator( - codegen: ExpressionCodegen, - operatorReference: KtSimpleNameExpression, - rangeCall: ResolvedCall<*> -) : AbstractInPrimitiveNumberRangeExpressionGenerator(codegen, operatorReference, rangeCall, isInclusiveHighBound = true) { - private val from: ReceiverValue = rangeCall.dispatchReceiver ?: rangeCall.extensionReceiver!! - private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(rangeCall)!! - - override fun genLowBound(): StackValue = codegen.generateReceiverValue(from, false) - - override fun genHighBound(): StackValue = codegen.gen(to) -} -