Primitive number range literal as BoundedValue
This commit is contained in:
@@ -24,7 +24,9 @@ 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.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
private val RANGE_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
|
private val RANGE_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
|
||||||
supportedRangeTypes().associateBy {
|
supportedRangeTypes().associateBy {
|
||||||
@@ -188,3 +190,20 @@ private fun isTopLevelInPackage(descriptor: DeclarationDescriptor, name: String,
|
|||||||
val packageFqName = containingDeclaration.fqName.asString()
|
val packageFqName = containingDeclaration.fqName.asString()
|
||||||
return packageName == packageFqName
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+32
-3
@@ -17,17 +17,46 @@
|
|||||||
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.getAsmRangeElementTypeForPrimitiveRange
|
||||||
|
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.InPrimitiveNumberRangeLiteralGenerator
|
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 PrimitiveNumberRangeLiteralRangeValue(
|
||||||
|
private val codegen: ExpressionCodegen,
|
||||||
|
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||||
|
): 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<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(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) =
|
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
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ private fun ExpressionCodegen.createIntrinsifiedRangeValueOrNull(rangeCall: Reso
|
|||||||
|
|
||||||
return when {
|
return when {
|
||||||
isPrimitiveNumberRangeTo(rangeCallee) ->
|
isPrimitiveNumberRangeTo(rangeCallee) ->
|
||||||
PrimitiveNumberRangeLiteralRangeValue(rangeCall)
|
PrimitiveNumberRangeLiteralRangeValue(this, rangeCall)
|
||||||
isPrimitiveNumberDownTo(rangeCallee) ->
|
isPrimitiveNumberDownTo(rangeCallee) ->
|
||||||
DownToProgressionRangeValue(rangeCall)
|
DownToProgressionRangeValue(rangeCall)
|
||||||
isPrimitiveNumberUntil(rangeCallee) ->
|
isPrimitiveNumberUntil(rangeCallee) ->
|
||||||
|
|||||||
+8
@@ -29,3 +29,11 @@ interface ComparisonGenerator {
|
|||||||
fun jumpIfLess(v: InstructionAdapter, label: Label)
|
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)
|
||||||
|
}
|
||||||
+2
-33
@@ -16,18 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.range.inExpression
|
package org.jetbrains.kotlin.codegen.range.inExpression
|
||||||
|
|
||||||
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.getAsmRangeElementTypeForPrimitiveRange
|
||||||
import org.jetbrains.kotlin.codegen.getPrimitiveRangeElementType
|
|
||||||
import org.jetbrains.kotlin.codegen.range.comparison.*
|
import org.jetbrains.kotlin.codegen.range.comparison.*
|
||||||
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
|
||||||
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.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
|
||||||
|
|
||||||
abstract class AbstractInPrimitiveNumberRangeExpressionGenerator(
|
abstract class AbstractInPrimitiveNumberRangeExpressionGenerator(
|
||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
@@ -38,30 +32,5 @@ abstract class AbstractInPrimitiveNumberRangeExpressionGenerator(
|
|||||||
codegen, operatorReference, isInclusiveHighBound,
|
codegen, operatorReference, isInclusiveHighBound,
|
||||||
getAsmRangeElementTypeForPrimitiveRange(rangeCall.resultingDescriptor)
|
getAsmRangeElementTypeForPrimitiveRange(rangeCall.resultingDescriptor)
|
||||||
) {
|
) {
|
||||||
override val comparisonGenerator: ComparisonGenerator =
|
override val comparisonGenerator: ComparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType)
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-48
@@ -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<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 = ObjectComparisonGenerator
|
|
||||||
}
|
|
||||||
-38
@@ -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)
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user