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.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<FqName, PrimitiveType> =
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
+32
-3
@@ -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<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) =
|
||||
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
|
||||
}
|
||||
@@ -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) ->
|
||||
|
||||
+8
@@ -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)
|
||||
}
|
||||
+2
-33
@@ -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)
|
||||
}
|
||||
|
||||
-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