Minor: format code in org.jetbrains.kotlin.codegen.range
This commit is contained in:
@@ -24,10 +24,10 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
abstract class AbstractBoundedValue(
|
||||
protected val codegen: ExpressionCodegen,
|
||||
protected val rangeCall: ResolvedCall<out CallableDescriptor>,
|
||||
override val isLowInclusive: Boolean = true,
|
||||
override val isHighInclusive: Boolean = true
|
||||
protected val codegen: ExpressionCodegen,
|
||||
protected val rangeCall: ResolvedCall<out CallableDescriptor>,
|
||||
override val isLowInclusive: Boolean = true,
|
||||
override val isHighInclusive: Boolean = true
|
||||
) : BoundedValue {
|
||||
override val instanceType: Type = codegen.asmType(rangeCall.resultingDescriptor.returnType!!)
|
||||
|
||||
|
||||
@@ -29,27 +29,27 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class ArrayIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
|
||||
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
|
||||
|
||||
override fun getBoundedValue(codegen: ExpressionCodegen) =
|
||||
SimpleBoundedValue(
|
||||
codegen, rangeCall,
|
||||
lowBound = StackValue.constant(0, asmElementType),
|
||||
isLowInclusive = true,
|
||||
highBound = StackValue.operation(Type.INT_TYPE) { v ->
|
||||
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
|
||||
v.arraylength()
|
||||
},
|
||||
isHighInclusive = false
|
||||
)
|
||||
SimpleBoundedValue(
|
||||
codegen, rangeCall,
|
||||
lowBound = StackValue.constant(0, asmElementType),
|
||||
isLowInclusive = true,
|
||||
highBound = StackValue.operation(Type.INT_TYPE) { v ->
|
||||
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
|
||||
v.arraylength()
|
||||
},
|
||||
isHighInclusive = false
|
||||
)
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
|
||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
codegen, forExpression, getBoundedValue(codegen)
|
||||
)
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
codegen, forExpression, getBoundedValue(codegen)
|
||||
)
|
||||
}
|
||||
@@ -24,12 +24,12 @@ import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
|
||||
class ArrayRangeValue(
|
||||
private val canCacheArrayLength: Boolean,
|
||||
private val shouldAlwaysStoreArrayInNewVar: Boolean
|
||||
private val canCacheArrayLength: Boolean,
|
||||
private val shouldAlwaysStoreArrayInNewVar: Boolean
|
||||
) : RangeValue {
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInArrayLoopGenerator(codegen, forExpression, canCacheArrayLength, shouldAlwaysStoreArrayInNewVar)
|
||||
ForInArrayLoopGenerator(codegen, forExpression, canCacheArrayLength, shouldAlwaysStoreArrayInNewVar)
|
||||
|
||||
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.codegen.range
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
|
||||
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
|
||||
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
@@ -25,10 +24,14 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall<out CallableDescriptor>): RangeValue {
|
||||
abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall<out CallableDescriptor>) : RangeValue {
|
||||
protected abstract fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>): Boolean
|
||||
|
||||
protected abstract fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression, resolvedCall: ResolvedCall<out CallableDescriptor>): InExpressionGenerator
|
||||
protected abstract fun createIntrinsicInExpressionGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>
|
||||
): InExpressionGenerator
|
||||
|
||||
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator {
|
||||
val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext)
|
||||
|
||||
+15
-15
@@ -28,27 +28,27 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
|
||||
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
|
||||
|
||||
override fun getBoundedValue(codegen: ExpressionCodegen) =
|
||||
SimpleBoundedValue(
|
||||
codegen, rangeCall,
|
||||
lowBound = StackValue.constant(0, asmElementType),
|
||||
isLowInclusive = true,
|
||||
highBound = StackValue.operation(Type.INT_TYPE) { v ->
|
||||
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
|
||||
v.invokeinterface("java/lang/CharSequence", "length", "()I")
|
||||
},
|
||||
isHighInclusive = false
|
||||
)
|
||||
SimpleBoundedValue(
|
||||
codegen, rangeCall,
|
||||
lowBound = StackValue.constant(0, asmElementType),
|
||||
isLowInclusive = true,
|
||||
highBound = StackValue.operation(Type.INT_TYPE) { v ->
|
||||
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
|
||||
v.invokeinterface("java/lang/CharSequence", "length", "()I")
|
||||
},
|
||||
isHighInclusive = false
|
||||
)
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
|
||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
codegen, forExpression, getBoundedValue(codegen)
|
||||
)
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
codegen, forExpression, getBoundedValue(codegen)
|
||||
)
|
||||
}
|
||||
@@ -26,8 +26,8 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class CharSequenceRangeValue(private val canCacheLength: Boolean, private val charSequenceClassType: Type?) : RangeValue {
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInCharSequenceLoopGenerator(codegen, forExpression, canCacheLength, charSequenceClassType)
|
||||
ForInCharSequenceLoopGenerator(codegen, forExpression, canCacheLength, charSequenceClassType)
|
||||
|
||||
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
}
|
||||
+15
-15
@@ -28,27 +28,27 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class CollectionIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
|
||||
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
|
||||
|
||||
override fun getBoundedValue(codegen: ExpressionCodegen) =
|
||||
SimpleBoundedValue(
|
||||
codegen, rangeCall,
|
||||
lowBound = StackValue.constant(0, asmElementType),
|
||||
isLowInclusive = true,
|
||||
highBound = StackValue.operation(Type.INT_TYPE) { v ->
|
||||
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
|
||||
v.invokeinterface("java/util/Collection", "size", "()I")
|
||||
},
|
||||
isHighInclusive = false
|
||||
)
|
||||
SimpleBoundedValue(
|
||||
codegen, rangeCall,
|
||||
lowBound = StackValue.constant(0, asmElementType),
|
||||
isLowInclusive = true,
|
||||
highBound = StackValue.operation(Type.INT_TYPE) { v ->
|
||||
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
|
||||
v.invokeinterface("java/util/Collection", "size", "()I")
|
||||
},
|
||||
isHighInclusive = false
|
||||
)
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
|
||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
codegen, forExpression, getBoundedValue(codegen)
|
||||
)
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
codegen, forExpression, getBoundedValue(codegen)
|
||||
)
|
||||
}
|
||||
+7
-7
@@ -26,20 +26,20 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class ComparableRangeLiteralRangeValue(
|
||||
codegen: ExpressionCodegen,
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||
codegen: ExpressionCodegen,
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||
) : CallIntrinsicRangeValue(rangeCall) {
|
||||
private val boundedValue = SimpleBoundedValue(codegen, rangeCall)
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
IteratorForLoopGenerator(codegen, forExpression)
|
||||
IteratorForLoopGenerator(codegen, forExpression)
|
||||
|
||||
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
|
||||
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
|
||||
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>
|
||||
codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>
|
||||
) = InContinuousRangeOfComparableExpressionGenerator(operatorReference, boundedValue, codegen.frameMap)
|
||||
}
|
||||
+23
-23
@@ -28,49 +28,49 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class DownToProgressionRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
|
||||
override fun getBoundedValue(codegen: ExpressionCodegen) =
|
||||
SimpleBoundedValue(
|
||||
codegen, rangeCall,
|
||||
lowBound = codegen.generateCallSingleArgument(rangeCall),
|
||||
highBound = codegen.generateCallReceiver(rangeCall)
|
||||
)
|
||||
SimpleBoundedValue(
|
||||
codegen, rangeCall,
|
||||
lowBound = codegen.generateCallSingleArgument(rangeCall),
|
||||
highBound = codegen.generateCallReceiver(rangeCall)
|
||||
)
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
createConstBoundedForInDownToGenerator(codegen, forExpression) ?:
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen))
|
||||
createConstBoundedForInDownToGenerator(codegen, forExpression)
|
||||
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen))
|
||||
|
||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
createConstBoundedForInReversedDownToGenerator(codegen, forExpression) ?:
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
|
||||
createConstBoundedForInReversedDownToGenerator(codegen, forExpression)
|
||||
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
|
||||
codegen, forExpression, getBoundedValue(codegen),
|
||||
inverseBoundsEvaluationOrder = true
|
||||
)
|
||||
)
|
||||
|
||||
private fun createConstBoundedForInDownToGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
): ForLoopGenerator? {
|
||||
val endExpression = rangeCall.getFirstArgumentExpression() ?: return null
|
||||
return createConstBoundedForLoopGeneratorOrNull(
|
||||
codegen, forExpression,
|
||||
codegen.generateCallReceiver(rangeCall),
|
||||
endExpression,
|
||||
-1
|
||||
codegen, forExpression,
|
||||
codegen.generateCallReceiver(rangeCall),
|
||||
endExpression,
|
||||
-1
|
||||
)
|
||||
}
|
||||
|
||||
private fun createConstBoundedForInReversedDownToGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
): ForLoopGenerator? {
|
||||
val endExpression = rangeCall.getReceiverExpression() ?: return null
|
||||
return createConstBoundedForLoopGeneratorOrNull(
|
||||
codegen, forExpression,
|
||||
codegen.generateCallSingleArgument(rangeCall),
|
||||
endExpression,
|
||||
1
|
||||
codegen, forExpression,
|
||||
codegen.generateCallSingleArgument(rangeCall),
|
||||
endExpression,
|
||||
1
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,8 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
|
||||
class IterableRangeValue : RangeValue {
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
IteratorForLoopGenerator(codegen, forExpression)
|
||||
IteratorForLoopGenerator(codegen, forExpression)
|
||||
|
||||
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
}
|
||||
+50
-50
@@ -34,21 +34,21 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||
): CallIntrinsicRangeValue(rangeCall) {
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||
) : CallIntrinsicRangeValue(rangeCall) {
|
||||
protected val asmElementType = getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCall.resultingDescriptor)
|
||||
|
||||
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
|
||||
resolvedCallForIn.resultingDescriptor.let {
|
||||
isPrimitiveRangeContains(it) ||
|
||||
isClosedFloatingPointRangeContains(it) ||
|
||||
isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(it)
|
||||
}
|
||||
resolvedCallForIn.resultingDescriptor.let {
|
||||
isPrimitiveRangeContains(it) ||
|
||||
isClosedFloatingPointRangeContains(it) ||
|
||||
isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(it)
|
||||
}
|
||||
|
||||
override fun createIntrinsicInExpressionGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>
|
||||
codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>
|
||||
): InExpressionGenerator {
|
||||
val comparisonGenerator = getComparisonGeneratorForRangeContainsCall(codegen, resolvedCall)
|
||||
val comparedType = comparisonGenerator?.comparedType
|
||||
@@ -57,14 +57,14 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
||||
comparisonGenerator == null -> CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
|
||||
comparedType == Type.DOUBLE_TYPE || comparedType == Type.FLOAT_TYPE -> {
|
||||
val rangeLiteral = getBoundedValue(codegen) as? SimpleBoundedValue ?:
|
||||
throw AssertionError("Floating point intrinsic range value should be a range literal")
|
||||
val rangeLiteral = getBoundedValue(codegen) as? SimpleBoundedValue
|
||||
?: throw AssertionError("Floating point intrinsic range value should be a range literal")
|
||||
InFloatingPointRangeLiteralExpressionGenerator(operatorReference, rangeLiteral, comparisonGenerator, codegen.frameMap)
|
||||
}
|
||||
|
||||
else ->
|
||||
InIntegralContinuousRangeExpressionGenerator(
|
||||
operatorReference, getBoundedValue(codegen), comparisonGenerator, codegen.frameMap
|
||||
operatorReference, getBoundedValue(codegen), comparisonGenerator, codegen.frameMap
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -72,12 +72,12 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
||||
protected abstract fun getBoundedValue(codegen: ExpressionCodegen): BoundedValue
|
||||
|
||||
protected fun createConstBoundedForLoopGeneratorOrNull(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
startValue: StackValue,
|
||||
endExpression: KtExpression,
|
||||
step: Int,
|
||||
isStartInclusive: Boolean = true
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
startValue: StackValue,
|
||||
endExpression: KtExpression,
|
||||
step: Int,
|
||||
isStartInclusive: Boolean = true
|
||||
): ForLoopGenerator? {
|
||||
val endConstValue = codegen.getCompileTimeConstant(endExpression).safeAs<IntegerValueConstant<*>>() ?: return null
|
||||
|
||||
@@ -127,46 +127,46 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
|
||||
}
|
||||
|
||||
private fun createConstBoundedIntForLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
startValue: StackValue,
|
||||
endIntValue: Int,
|
||||
step: Int,
|
||||
isStartInclusive: Boolean
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
startValue: StackValue,
|
||||
endIntValue: Int,
|
||||
step: Int,
|
||||
isStartInclusive: Boolean
|
||||
): ForLoopGenerator? =
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
||||
codegen, forExpression,
|
||||
startValue = startValue,
|
||||
isStartInclusive = isStartInclusive,
|
||||
endValue = StackValue.integerConstant(endIntValue, asmElementType),
|
||||
isEndInclusive = true,
|
||||
step = step
|
||||
)
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
||||
codegen, forExpression,
|
||||
startValue = startValue,
|
||||
isStartInclusive = isStartInclusive,
|
||||
endValue = StackValue.integerConstant(endIntValue, asmElementType),
|
||||
isEndInclusive = true,
|
||||
step = step
|
||||
)
|
||||
|
||||
private fun createConstBoundedLongForLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
startValue: StackValue,
|
||||
endLongValue: Long,
|
||||
step: Int,
|
||||
isStartInclusive: Boolean
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
startValue: StackValue,
|
||||
endLongValue: Long,
|
||||
step: Int,
|
||||
isStartInclusive: Boolean
|
||||
): ForLoopGenerator? =
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
||||
codegen, forExpression,
|
||||
startValue = startValue,
|
||||
isStartInclusive = isStartInclusive,
|
||||
endValue = StackValue.constant(endLongValue, asmElementType),
|
||||
isEndInclusive = true,
|
||||
step = step
|
||||
)
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
||||
codegen, forExpression,
|
||||
startValue = startValue,
|
||||
isStartInclusive = isStartInclusive,
|
||||
endValue = StackValue.constant(endLongValue, asmElementType),
|
||||
isEndInclusive = true,
|
||||
step = step
|
||||
)
|
||||
|
||||
private fun isProhibitedCharConstEndValue(step: Int, endValue: Char) =
|
||||
endValue == if (step == 1) java.lang.Character.MAX_VALUE else java.lang.Character.MIN_VALUE
|
||||
endValue == if (step == 1) java.lang.Character.MAX_VALUE else java.lang.Character.MIN_VALUE
|
||||
|
||||
private fun isProhibitedIntConstEndValue(step: Int, endValue: Int) =
|
||||
endValue == if (step == 1) Int.MAX_VALUE else Int.MIN_VALUE
|
||||
endValue == if (step == 1) Int.MAX_VALUE else Int.MIN_VALUE
|
||||
|
||||
private fun isProhibitedLongConstEndValue(step: Int, endValue: Long) =
|
||||
endValue == if (step == 1) Long.MAX_VALUE else Long.MIN_VALUE
|
||||
endValue == if (step == 1) Long.MAX_VALUE else Long.MIN_VALUE
|
||||
|
||||
}
|
||||
+21
-21
@@ -23,52 +23,52 @@ import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGene
|
||||
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class PrimitiveNumberRangeLiteralRangeValue(
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>
|
||||
) : PrimitiveNumberRangeIntrinsicRangeValue(rangeCall),
|
||||
ReversableRangeValue {
|
||||
ReversableRangeValue {
|
||||
|
||||
override fun getBoundedValue(codegen: ExpressionCodegen) =
|
||||
SimpleBoundedValue(codegen, rangeCall)
|
||||
SimpleBoundedValue(codegen, rangeCall)
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
|
||||
createConstBoundedForInRangeLiteralGenerator(codegen, forExpression) ?:
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
createConstBoundedForInRangeLiteralGenerator(codegen, forExpression)
|
||||
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
|
||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
|
||||
createConstBoundedRangeForInReversedRangeLiteralGenerator(codegen, forExpression) ?:
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
createConstBoundedRangeForInReversedRangeLiteralGenerator(codegen, forExpression)
|
||||
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
codegen, forExpression, getBoundedValue(codegen),
|
||||
inverseBoundsEvaluationOrder = true
|
||||
)
|
||||
)
|
||||
|
||||
private fun createConstBoundedForInRangeLiteralGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
): ForLoopGenerator? {
|
||||
val endExpression = rangeCall.getFirstArgumentExpression() ?: return null
|
||||
return createConstBoundedForLoopGeneratorOrNull(
|
||||
codegen, forExpression,
|
||||
codegen.generateCallReceiver(rangeCall),
|
||||
endExpression,
|
||||
1
|
||||
codegen, forExpression,
|
||||
codegen.generateCallReceiver(rangeCall),
|
||||
endExpression,
|
||||
1
|
||||
)
|
||||
}
|
||||
|
||||
private fun createConstBoundedRangeForInReversedRangeLiteralGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
): ForLoopGenerator? {
|
||||
val endExpression = rangeCall.getReceiverExpression() ?: return null
|
||||
return createConstBoundedForLoopGeneratorOrNull(
|
||||
codegen, forExpression,
|
||||
codegen.generateCallSingleArgument(rangeCall),
|
||||
endExpression,
|
||||
-1
|
||||
codegen, forExpression,
|
||||
codegen.generateCallSingleArgument(rangeCall),
|
||||
endExpression,
|
||||
-1
|
||||
)
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -26,32 +26,32 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
|
||||
|
||||
override fun getBoundedValue(codegen: ExpressionCodegen) =
|
||||
SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
|
||||
SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
|
||||
|
||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
createConstBoundedForInReversedUntilGenerator(codegen, forExpression) ?:
|
||||
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
createConstBoundedForInReversedUntilGenerator(codegen, forExpression)
|
||||
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
|
||||
codegen, forExpression, getBoundedValue(codegen),
|
||||
inverseBoundsEvaluationOrder = true
|
||||
)
|
||||
)
|
||||
|
||||
private fun createConstBoundedForInReversedUntilGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression
|
||||
): ForLoopGenerator? {
|
||||
val endExpression = rangeCall.getReceiverExpression() ?: return null
|
||||
return createConstBoundedForLoopGeneratorOrNull(
|
||||
codegen, forExpression,
|
||||
codegen.generateCallSingleArgument(rangeCall),
|
||||
endExpression,
|
||||
step = -1,
|
||||
isStartInclusive = false
|
||||
codegen, forExpression,
|
||||
codegen.generateCallSingleArgument(rangeCall),
|
||||
endExpression,
|
||||
step = -1,
|
||||
isStartInclusive = false
|
||||
)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -27,8 +27,8 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
class PrimitiveProgressionRangeValue(private val rangeExpression: KtExpression) : RangeValue {
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInProgressionExpressionLoopGenerator(codegen, forExpression, rangeExpression)
|
||||
ForInProgressionExpressionLoopGenerator(codegen, forExpression, rangeExpression)
|
||||
|
||||
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
}
|
||||
@@ -28,11 +28,11 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
class PrimitiveRangeRangeValue(private val rangeExpression: KtExpression) : ReversableRangeValue {
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
|
||||
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = false)
|
||||
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = false)
|
||||
|
||||
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
CallBasedInExpressionGenerator(codegen, operatorReference)
|
||||
|
||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
|
||||
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = true)
|
||||
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = true)
|
||||
}
|
||||
@@ -51,8 +51,8 @@ interface BoundedValue {
|
||||
}
|
||||
|
||||
fun BoundedValue.asStackValue(): StackValue =
|
||||
object : StackValue(instanceType) {
|
||||
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||
putInstance(v, type)
|
||||
}
|
||||
object : StackValue(instanceType) {
|
||||
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||
putInstance(v, type)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,10 +51,10 @@ fun ExpressionCodegen.createRangeValueForExpression(rangeExpression: KtExpressio
|
||||
return when {
|
||||
asmRangeType.sort == Type.ARRAY -> {
|
||||
val properForInArraySemantics =
|
||||
state.languageVersionSettings.supportsFeature(LanguageFeature.ProperForInArrayLoopRangeVariableAssignmentSemantic)
|
||||
state.languageVersionSettings.supportsFeature(LanguageFeature.ProperForInArrayLoopRangeVariableAssignmentSemantic)
|
||||
ArrayRangeValue(
|
||||
properForInArraySemantics || !isLocalVarReference(rangeExpression, bindingContext),
|
||||
properForInArraySemantics
|
||||
properForInArraySemantics || !isLocalVarReference(rangeExpression, bindingContext),
|
||||
properForInArraySemantics
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,20 +75,20 @@ fun isLocalVarReference(rangeExpression: KtExpression, bindingContext: BindingCo
|
||||
if (rangeExpression !is KtSimpleNameExpression) return false
|
||||
val resultingDescriptor = rangeExpression.getResolvedCall(bindingContext)?.resultingDescriptor ?: return false
|
||||
return resultingDescriptor is LocalVariableDescriptor &&
|
||||
resultingDescriptor !is SyntheticFieldDescriptor &&
|
||||
!resultingDescriptor.isDelegated &&
|
||||
resultingDescriptor.isVar
|
||||
resultingDescriptor !is SyntheticFieldDescriptor &&
|
||||
!resultingDescriptor.isDelegated &&
|
||||
resultingDescriptor.isVar
|
||||
}
|
||||
|
||||
private fun isSubtypeOfString(type: KotlinType, builtIns: KotlinBuiltIns) =
|
||||
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.stringType)
|
||||
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.stringType)
|
||||
|
||||
private fun isSubtypeOfCharSequence(type: KotlinType, builtIns: KotlinBuiltIns) =
|
||||
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.getBuiltInClassByName(Name.identifier("CharSequence")).defaultType)
|
||||
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.getBuiltInClassByName(Name.identifier("CharSequence")).defaultType)
|
||||
|
||||
private fun getResolvedCallForRangeExpression(
|
||||
bindingContext: BindingContext,
|
||||
rangeExpression: KtExpression
|
||||
bindingContext: BindingContext,
|
||||
rangeExpression: KtExpression
|
||||
): ResolvedCall<out CallableDescriptor>? {
|
||||
val expression = KtPsiUtil.deparenthesize(rangeExpression) ?: return null
|
||||
|
||||
|
||||
@@ -24,11 +24,11 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
|
||||
class ReversedRangeValue(private val original: ReversableRangeValue) : RangeValue, ReversableRangeValue {
|
||||
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
|
||||
original.createInExpressionGenerator(codegen, operatorReference)
|
||||
original.createInExpressionGenerator(codegen, operatorReference)
|
||||
|
||||
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
|
||||
original.createForInReversedLoopGenerator(codegen, forExpression)
|
||||
original.createForInReversedLoopGenerator(codegen, forExpression)
|
||||
|
||||
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
|
||||
original.createForLoopGenerator(codegen, forExpression)
|
||||
original.createForLoopGenerator(codegen, forExpression)
|
||||
}
|
||||
@@ -23,40 +23,39 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class SimpleBoundedValue(
|
||||
codegen: ExpressionCodegen,
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>,
|
||||
val lowBound: StackValue,
|
||||
isLowInclusive: Boolean,
|
||||
val highBound: StackValue,
|
||||
isHighInclusive: Boolean
|
||||
) : AbstractBoundedValue(codegen, rangeCall, isLowInclusive, isHighInclusive) {
|
||||
constructor(
|
||||
codegen: ExpressionCodegen,
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>,
|
||||
val lowBound: StackValue,
|
||||
isLowInclusive: Boolean,
|
||||
val highBound: StackValue,
|
||||
isHighInclusive: Boolean
|
||||
): AbstractBoundedValue(codegen, rangeCall, isLowInclusive, isHighInclusive) {
|
||||
constructor(
|
||||
codegen: ExpressionCodegen,
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>,
|
||||
isLowInclusive: Boolean = true,
|
||||
isHighInclusive: Boolean = true
|
||||
isLowInclusive: Boolean = true,
|
||||
isHighInclusive: Boolean = true
|
||||
) : this(
|
||||
codegen,
|
||||
rangeCall,
|
||||
codegen.generateCallReceiver(rangeCall),
|
||||
isLowInclusive,
|
||||
codegen.generateCallSingleArgument(rangeCall),
|
||||
isHighInclusive
|
||||
codegen,
|
||||
rangeCall,
|
||||
codegen.generateCallReceiver(rangeCall),
|
||||
isLowInclusive,
|
||||
codegen.generateCallSingleArgument(rangeCall),
|
||||
isHighInclusive
|
||||
)
|
||||
|
||||
constructor(
|
||||
codegen: ExpressionCodegen,
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>,
|
||||
lowBound: StackValue,
|
||||
highBound: StackValue
|
||||
codegen: ExpressionCodegen,
|
||||
rangeCall: ResolvedCall<out CallableDescriptor>,
|
||||
lowBound: StackValue,
|
||||
highBound: StackValue
|
||||
) : this(codegen, rangeCall, lowBound, true, highBound, true)
|
||||
|
||||
override fun putHighLow(v: InstructionAdapter, type: Type) {
|
||||
if (!lowBound.canHaveSideEffects() || !highBound.canHaveSideEffects()) {
|
||||
highBound.put(type, v)
|
||||
lowBound.put(type, v)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
lowBound.put(type, v)
|
||||
highBound.put(type, v)
|
||||
AsmUtil.swap(v, type, type)
|
||||
|
||||
+14
-11
@@ -34,15 +34,18 @@ interface ComparisonGenerator {
|
||||
}
|
||||
|
||||
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
|
||||
when {
|
||||
type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
|
||||
type == Type.LONG_TYPE -> LongComparisonGenerator
|
||||
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
|
||||
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
|
||||
else -> throw UnsupportedOperationException("Unexpected primitive type: " + type)
|
||||
}
|
||||
when {
|
||||
type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
|
||||
type == Type.LONG_TYPE -> LongComparisonGenerator
|
||||
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
|
||||
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
|
||||
else -> throw UnsupportedOperationException("Unexpected primitive type: " + type)
|
||||
}
|
||||
|
||||
fun getComparisonGeneratorForRangeContainsCall(codegen: ExpressionCodegen, call: ResolvedCall<out CallableDescriptor>): ComparisonGenerator? {
|
||||
fun getComparisonGeneratorForRangeContainsCall(
|
||||
codegen: ExpressionCodegen,
|
||||
call: ResolvedCall<out CallableDescriptor>
|
||||
): ComparisonGenerator? {
|
||||
val descriptor = call.resultingDescriptor
|
||||
|
||||
val receiverType = descriptor.extensionReceiverParameter?.type ?: descriptor.dispatchReceiverParameter?.type ?: return null
|
||||
@@ -62,11 +65,11 @@ fun getComparisonGeneratorForRangeContainsCall(codegen: ExpressionCodegen, call:
|
||||
IntComparisonGenerator
|
||||
|
||||
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType == Type.LONG_TYPE ||
|
||||
asmValueParameterType.isRepresentedAsPrimitiveInt() && asmElementType == Type.LONG_TYPE ->
|
||||
asmValueParameterType.isRepresentedAsPrimitiveInt() && asmElementType == Type.LONG_TYPE ->
|
||||
LongComparisonGenerator
|
||||
|
||||
asmElementType == Type.FLOAT_TYPE && asmValueParameterType == Type.DOUBLE_TYPE ||
|
||||
asmElementType == Type.DOUBLE_TYPE && asmValueParameterType == Type.FLOAT_TYPE ->
|
||||
asmElementType == Type.DOUBLE_TYPE && asmValueParameterType == Type.FLOAT_TYPE ->
|
||||
DoubleComparisonGenerator
|
||||
|
||||
else -> null
|
||||
@@ -74,4 +77,4 @@ fun getComparisonGeneratorForRangeContainsCall(codegen: ExpressionCodegen, call:
|
||||
}
|
||||
|
||||
private fun Type.isRepresentedAsPrimitiveInt() =
|
||||
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE || this == Type.CHAR_TYPE
|
||||
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE || this == Type.CHAR_TYPE
|
||||
+1
-1
@@ -20,7 +20,7 @@ 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 {
|
||||
sealed class FloatingPointComparisonGenerator(override val comparedType: Type) : ComparisonGenerator {
|
||||
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
|
||||
v.cmpg(comparedType)
|
||||
v.ifge(label)
|
||||
|
||||
+3
-5
@@ -24,9 +24,8 @@ import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
abstract class AbstractForInProgressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
|
||||
: AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression)
|
||||
{
|
||||
abstract class AbstractForInProgressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) :
|
||||
AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) {
|
||||
protected var incrementVar: Int = -1
|
||||
protected val asmLoopRangeType: Type
|
||||
protected val incrementType: Type
|
||||
@@ -73,8 +72,7 @@ abstract class AbstractForInProgressionLoopGenerator(codegen: ExpressionCodegen,
|
||||
v.lcmp()
|
||||
v.iflt(loopExit)
|
||||
v.mark(afterIf)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ifle(negativeIncrement) // if increment < 0, jump
|
||||
|
||||
// increment > 0
|
||||
|
||||
+9
-11
@@ -22,20 +22,19 @@ import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
|
||||
: AbstractForLoopGenerator(codegen, forExpression)
|
||||
{
|
||||
abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) :
|
||||
AbstractForLoopGenerator(codegen, forExpression) {
|
||||
protected var endVar: Int = -1
|
||||
|
||||
private var loopParameter: StackValue? = null
|
||||
|
||||
init {
|
||||
assert(
|
||||
asmElementType.sort == Type.INT ||
|
||||
asmElementType.sort == Type.BYTE ||
|
||||
asmElementType.sort == Type.SHORT ||
|
||||
asmElementType.sort == Type.CHAR ||
|
||||
asmElementType.sort == Type.LONG
|
||||
asmElementType.sort == Type.INT ||
|
||||
asmElementType.sort == Type.BYTE ||
|
||||
asmElementType.sort == Type.SHORT ||
|
||||
asmElementType.sort == Type.CHAR ||
|
||||
asmElementType.sort == Type.LONG
|
||||
) {
|
||||
"Unexpected range element type: " + asmElementType
|
||||
}
|
||||
@@ -56,8 +55,7 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
|
||||
if (asmElementType.sort == Type.LONG) {
|
||||
v.lcmp()
|
||||
v.ifeq(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ificmpeq(loopExit)
|
||||
}
|
||||
}
|
||||
@@ -65,5 +63,5 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
|
||||
override fun checkPreCondition(loopExit: Label) {}
|
||||
|
||||
protected fun loopParameter(): StackValue =
|
||||
loopParameter ?: StackValue.local(loopParameterVar, loopParameterType).also { loopParameter = it }
|
||||
loopParameter ?: StackValue.local(loopParameterVar, loopParameterType).also { loopParameter = it }
|
||||
}
|
||||
|
||||
+10
-15
@@ -16,18 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.range.forLoop
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.genIncrement
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.genIncrement
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
|
||||
abstract class AbstractForInRangeLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
protected val step: Int
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
protected val step: Int
|
||||
) : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) {
|
||||
|
||||
override fun beforeLoop() {
|
||||
@@ -45,16 +44,13 @@ abstract class AbstractForInRangeLoopGenerator(
|
||||
v.lcmp()
|
||||
if (step > 0) {
|
||||
v.ifgt(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.iflt(loopExit)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (step > 0) {
|
||||
v.ificmpgt(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ificmplt(loopExit)
|
||||
}
|
||||
}
|
||||
@@ -71,8 +67,7 @@ abstract class AbstractForInRangeLoopGenerator(
|
||||
protected fun incrementLoopVariable() {
|
||||
if (loopParameterType === Type.INT_TYPE) {
|
||||
v.iinc(loopParameterVar, step)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val loopParameter = loopParameter()
|
||||
loopParameter.put(asmElementType, v)
|
||||
genIncrement(asmElementType, step, v)
|
||||
|
||||
+26
-22
@@ -29,8 +29,8 @@ import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
abstract class AbstractForLoopGenerator(
|
||||
protected val codegen: ExpressionCodegen,
|
||||
override val forExpression: KtForExpression
|
||||
protected val codegen: ExpressionCodegen,
|
||||
override val forExpression: KtForExpression
|
||||
) : ForLoopGenerator {
|
||||
protected val bindingContext = codegen.bindingContext
|
||||
protected val v = codegen.v!!
|
||||
@@ -47,8 +47,8 @@ abstract class AbstractForLoopGenerator(
|
||||
|
||||
private fun BindingContext.getElementType(forExpression: KtForExpression): KotlinType {
|
||||
val loopRange = forExpression.loopRange!!
|
||||
val nextCall = get(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange) ?:
|
||||
throw AssertionError("No next() function " + DiagnosticUtils.atLocation(loopRange))
|
||||
val nextCall = get(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange)
|
||||
?: throw AssertionError("No next() function " + DiagnosticUtils.atLocation(loopRange))
|
||||
return nextCall.resultingDescriptor.returnType!!
|
||||
}
|
||||
|
||||
@@ -59,18 +59,19 @@ abstract class AbstractForLoopGenerator(
|
||||
// E tmp<e> = tmp<iterator>.next()
|
||||
loopParameterType = asmElementType
|
||||
loopParameterVar = createLoopTempVariable(asmElementType)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// E e = tmp<iterator>.next()
|
||||
val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter)
|
||||
loopParameterType = codegen.asmType(parameterDescriptor!!.type)
|
||||
loopParameterVar = codegen.myFrameMap.enter(parameterDescriptor, loopParameterType)
|
||||
scheduleLeaveVariable(Runnable {
|
||||
codegen.myFrameMap.leave(parameterDescriptor)
|
||||
v.visitLocalVariable(parameterDescriptor.name.asString(),
|
||||
loopParameterType.descriptor, null,
|
||||
loopParameterStartLabel, bodyEnd,
|
||||
loopParameterVar)
|
||||
v.visitLocalVariable(
|
||||
parameterDescriptor.name.asString(),
|
||||
loopParameterType.descriptor, null,
|
||||
loopParameterStartLabel, bodyEnd,
|
||||
loopParameterVar
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -95,19 +96,22 @@ abstract class AbstractForLoopGenerator(
|
||||
val componentVarIndex = codegen.myFrameMap.enter(componentDescriptor, componentAsmType)
|
||||
scheduleLeaveVariable(Runnable {
|
||||
codegen.myFrameMap.leave(componentDescriptor)
|
||||
v.visitLocalVariable(componentDescriptor.name.asString(),
|
||||
componentAsmType.descriptor, null,
|
||||
destructuringStartLabel, bodyEnd,
|
||||
componentVarIndex)
|
||||
v.visitLocalVariable(
|
||||
componentDescriptor.name.asString(),
|
||||
componentAsmType.descriptor, null,
|
||||
destructuringStartLabel, bodyEnd,
|
||||
componentVarIndex
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
v.visitLabel(destructuringStartLabel)
|
||||
|
||||
codegen.initializeDestructuringDeclarationVariables(
|
||||
destructuringDeclaration,
|
||||
TransientReceiver(elementType),
|
||||
StackValue.local(loopParameterVar, asmElementType))
|
||||
destructuringDeclaration,
|
||||
TransientReceiver(elementType),
|
||||
StackValue.local(loopParameterVar, asmElementType)
|
||||
)
|
||||
}
|
||||
|
||||
protected abstract fun assignToLoopParameter()
|
||||
@@ -145,11 +149,11 @@ abstract class AbstractForLoopGenerator(
|
||||
// This method consumes range/progression from stack
|
||||
// The result is stored to local variable
|
||||
protected fun generateRangeOrProgressionProperty(
|
||||
loopRangeType: Type,
|
||||
getterName: String,
|
||||
getterReturnType: Type,
|
||||
varType: Type,
|
||||
varToStore: Int
|
||||
loopRangeType: Type,
|
||||
getterName: String,
|
||||
getterReturnType: Type,
|
||||
varType: Type,
|
||||
varToStore: Int
|
||||
) {
|
||||
v.invokevirtual(loopRangeType.internalName, getterName, "()" + getterReturnType.descriptor, false)
|
||||
StackValue.local(varToStore, varType).store(StackValue.onStack(getterReturnType), v)
|
||||
|
||||
+6
-8
@@ -27,10 +27,10 @@ import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class ForInArrayLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val canCacheArrayLength: Boolean,
|
||||
private val shouldAlwaysStoreArrayInNewVar: Boolean
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val canCacheArrayLength: Boolean,
|
||||
private val shouldAlwaysStoreArrayInNewVar: Boolean
|
||||
) : AbstractForLoopGenerator(codegen, forExpression) {
|
||||
private var indexVar: Int = 0
|
||||
private var arrayVar: Int = 0
|
||||
@@ -47,8 +47,7 @@ class ForInArrayLoopGenerator(
|
||||
val asmLoopRangeType = codegen.asmType(loopRangeType)
|
||||
if (!shouldAlwaysStoreArrayInNewVar && value is StackValue.Local && value.type == asmLoopRangeType) {
|
||||
arrayVar = value.index // no need to copy local variable into another variable
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
arrayVar = createLoopTempVariable(OBJECT_TYPE)
|
||||
value.put(asmLoopRangeType, v)
|
||||
v.store(arrayVar, OBJECT_TYPE)
|
||||
@@ -71,8 +70,7 @@ class ForInArrayLoopGenerator(
|
||||
v.load(indexVar, Type.INT_TYPE)
|
||||
if (canCacheArrayLength) {
|
||||
v.load(arrayLengthVar, Type.INT_TYPE)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.load(arrayVar, OBJECT_TYPE)
|
||||
v.arraylength()
|
||||
}
|
||||
|
||||
+6
-8
@@ -25,10 +25,10 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class ForInCharSequenceLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val canCacheLength: Boolean,
|
||||
private val charSequenceClassType: Type?
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val canCacheLength: Boolean,
|
||||
private val charSequenceClassType: Type?
|
||||
) : AbstractForLoopGenerator(codegen, forExpression) {
|
||||
private var indexVar: Int = 0
|
||||
private var charSequenceVar: Int = 0
|
||||
@@ -70,8 +70,7 @@ class ForInCharSequenceLoopGenerator(
|
||||
v.load(indexVar, Type.INT_TYPE)
|
||||
if (canCacheLength) {
|
||||
v.load(charSequenceLengthVar, Type.INT_TYPE)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.load(charSequenceVar, charSequenceType)
|
||||
v.invokeCharSequenceMethod("length", "()I")
|
||||
}
|
||||
@@ -94,8 +93,7 @@ class ForInCharSequenceLoopGenerator(
|
||||
val charSequenceClassType = charSequenceClassType
|
||||
if (charSequenceClassType != null) {
|
||||
invokevirtual(charSequenceClassType.internalName, name, desc, false)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
invokeinterface(CHAR_SEQUENCE_TYPE.internalName, name, desc)
|
||||
}
|
||||
}
|
||||
|
||||
+26
-33
@@ -39,35 +39,35 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
* This generator is suitable for cases where arithmetic overflow is impossible.
|
||||
*/
|
||||
class ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val startValue: StackValue,
|
||||
private val isStartInclusive: Boolean,
|
||||
private val endValue: StackValue,
|
||||
private val isEndInclusive: Boolean,
|
||||
step: Int
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val startValue: StackValue,
|
||||
private val isStartInclusive: Boolean,
|
||||
private val endValue: StackValue,
|
||||
private val isEndInclusive: Boolean,
|
||||
step: Int
|
||||
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step) {
|
||||
|
||||
constructor(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
boundedValue: SimpleBoundedValue,
|
||||
step: Int
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
boundedValue: SimpleBoundedValue,
|
||||
step: Int
|
||||
) : this(
|
||||
codegen, forExpression,
|
||||
startValue = if (step == 1) boundedValue.lowBound else boundedValue.highBound,
|
||||
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
|
||||
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
|
||||
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
|
||||
step = step
|
||||
codegen, forExpression,
|
||||
startValue = if (step == 1) boundedValue.lowBound else boundedValue.highBound,
|
||||
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
|
||||
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
|
||||
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
|
||||
step = step
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun fromBoundedValueWithStep1(codegen: ExpressionCodegen, forExpression: KtForExpression, boundedValue: SimpleBoundedValue) =
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, 1)
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, 1)
|
||||
|
||||
fun fromBoundedValueWithStepMinus1(codegen: ExpressionCodegen, forExpression: KtForExpression, boundedValue: SimpleBoundedValue) =
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, -1)
|
||||
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, -1)
|
||||
}
|
||||
|
||||
override fun storeRangeStartAndEnd() {
|
||||
@@ -89,34 +89,27 @@ class ForInDefinitelySafeSimpleProgressionLoopGenerator(
|
||||
if (step > 0) {
|
||||
if (isEndInclusive) {
|
||||
v.ifgt(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ifge(loopExit)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (isEndInclusive) {
|
||||
v.iflt(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ifle(loopExit)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (step > 0) {
|
||||
if (isEndInclusive) {
|
||||
v.ificmpgt(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ificmpge(loopExit)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (isEndInclusive) {
|
||||
v.ificmplt(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ificmple(loopExit)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -21,9 +21,9 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
|
||||
class ForInProgressionExpressionLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val rangeExpression: KtExpression
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val rangeExpression: KtExpression
|
||||
) : AbstractForInProgressionLoopGenerator(codegen, forExpression) {
|
||||
override fun storeProgressionParametersToLocalVars() {
|
||||
codegen.gen(rangeExpression, asmLoopRangeType)
|
||||
|
||||
+5
-6
@@ -21,10 +21,10 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
|
||||
class ForInRangeInstanceLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val rangeExpression: KtExpression,
|
||||
private val reversed: Boolean
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val rangeExpression: KtExpression,
|
||||
private val reversed: Boolean
|
||||
) : AbstractForInRangeLoopGenerator(codegen, forExpression, if (reversed) -1 else 1) {
|
||||
|
||||
override fun storeRangeStartAndEnd() {
|
||||
@@ -37,8 +37,7 @@ class ForInRangeInstanceLoopGenerator(
|
||||
if (reversed) {
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, loopParameterType, loopParameterVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, asmElementType, endVar)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
|
||||
}
|
||||
|
||||
+35
-40
@@ -24,56 +24,55 @@ import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class ForInSimpleProgressionLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val startValue: StackValue,
|
||||
private val isStartInclusive: Boolean,
|
||||
private val endValue: StackValue,
|
||||
private val isEndInclusive: Boolean,
|
||||
private val inverseBoundsEvaluationOrder: Boolean,
|
||||
step: Int
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
private val startValue: StackValue,
|
||||
private val isStartInclusive: Boolean,
|
||||
private val endValue: StackValue,
|
||||
private val isEndInclusive: Boolean,
|
||||
private val inverseBoundsEvaluationOrder: Boolean,
|
||||
step: Int
|
||||
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step) {
|
||||
|
||||
constructor(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
boundedValue: SimpleBoundedValue,
|
||||
inverseBoundsEvaluationOrder: Boolean,
|
||||
step: Int
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
boundedValue: SimpleBoundedValue,
|
||||
inverseBoundsEvaluationOrder: Boolean,
|
||||
step: Int
|
||||
) : this(
|
||||
codegen, forExpression,
|
||||
startValue = if (step == 1) boundedValue.lowBound else boundedValue.highBound,
|
||||
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
|
||||
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
|
||||
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
|
||||
inverseBoundsEvaluationOrder = inverseBoundsEvaluationOrder,
|
||||
step = step
|
||||
codegen, forExpression,
|
||||
startValue = if (step == 1) boundedValue.lowBound else boundedValue.highBound,
|
||||
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
|
||||
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
|
||||
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
|
||||
inverseBoundsEvaluationOrder = inverseBoundsEvaluationOrder,
|
||||
step = step
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun fromBoundedValueWithStep1(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
boundedValue: SimpleBoundedValue,
|
||||
inverseBoundsEvaluationOrder: Boolean = false
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
boundedValue: SimpleBoundedValue,
|
||||
inverseBoundsEvaluationOrder: Boolean = false
|
||||
) =
|
||||
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, 1)
|
||||
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, 1)
|
||||
|
||||
fun fromBoundedValueWithStepMinus1(
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
boundedValue: SimpleBoundedValue,
|
||||
inverseBoundsEvaluationOrder: Boolean = false
|
||||
codegen: ExpressionCodegen,
|
||||
forExpression: KtForExpression,
|
||||
boundedValue: SimpleBoundedValue,
|
||||
inverseBoundsEvaluationOrder: Boolean = false
|
||||
) =
|
||||
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, -1)
|
||||
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, -1)
|
||||
}
|
||||
|
||||
override fun storeRangeStartAndEnd() {
|
||||
if (inverseBoundsEvaluationOrder) {
|
||||
StackValue.local(endVar, asmElementType).store(endValue, v)
|
||||
loopParameter().store(startValue, v)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
loopParameter().store(startValue, v)
|
||||
StackValue.local(endVar, asmElementType).store(endValue, v)
|
||||
}
|
||||
@@ -98,16 +97,13 @@ class ForInSimpleProgressionLoopGenerator(
|
||||
v.lcmp()
|
||||
if (step > 0) {
|
||||
v.ifge(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ifle(loopExit)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (step > 0) {
|
||||
v.ificmpge(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
v.ificmple(loopExit)
|
||||
}
|
||||
}
|
||||
@@ -119,8 +115,7 @@ class ForInSimpleProgressionLoopGenerator(
|
||||
// Otherwise, just increment the loop variable.
|
||||
if (isEndInclusive) {
|
||||
super.checkPostConditionAndIncrement(loopExit)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
incrementLoopVariable()
|
||||
}
|
||||
}
|
||||
|
||||
+15
-12
@@ -28,9 +28,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
|
||||
: AbstractForLoopGenerator(codegen, forExpression)
|
||||
{
|
||||
class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) :
|
||||
AbstractForLoopGenerator(codegen, forExpression) {
|
||||
private var iteratorVarIndex: Int = 0
|
||||
private val iteratorCall: ResolvedCall<FunctionDescriptor>
|
||||
private val nextCall: ResolvedCall<FunctionDescriptor>
|
||||
@@ -38,16 +37,20 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
|
||||
|
||||
init {
|
||||
val loopRange = forExpression.loopRange!!
|
||||
this.iteratorCall = getNotNull(bindingContext,
|
||||
LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
|
||||
"No .iterator() function " + DiagnosticUtils.atLocation(loopRange))
|
||||
this.iteratorCall = getNotNull(
|
||||
bindingContext,
|
||||
LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
|
||||
"No .iterator() function " + DiagnosticUtils.atLocation(loopRange)
|
||||
)
|
||||
|
||||
val iteratorType = iteratorCall.resultingDescriptor.returnType!!
|
||||
this.asmTypeForIterator = codegen.asmType(iteratorType)
|
||||
|
||||
this.nextCall = getNotNull(bindingContext,
|
||||
LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
|
||||
"No next() function " + DiagnosticUtils.atLocation(loopRange))
|
||||
this.nextCall = getNotNull(
|
||||
bindingContext,
|
||||
LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
|
||||
"No next() function " + DiagnosticUtils.atLocation(loopRange)
|
||||
)
|
||||
}
|
||||
|
||||
override fun beforeLoop() {
|
||||
@@ -65,9 +68,9 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
|
||||
|
||||
val loopRange = forExpression.loopRange
|
||||
val hasNextCall = getNotNull(
|
||||
codegen.bindingContext, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL,
|
||||
loopRange!!,
|
||||
"No hasNext() function " + DiagnosticUtils.atLocation(loopRange)
|
||||
codegen.bindingContext, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL,
|
||||
loopRange!!,
|
||||
"No hasNext() function " + DiagnosticUtils.atLocation(loopRange)
|
||||
)
|
||||
val fakeCall = codegen.makeFakeCall(TransientReceiver(iteratorCall.resultingDescriptor.returnType!!))
|
||||
val result = codegen.invokeFunction(fakeCall, hasNextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator))
|
||||
|
||||
+23
-20
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.range.inExpression
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.BranchedValue
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.Invert
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
@@ -26,30 +29,30 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class CallBasedInExpressionGenerator(
|
||||
val codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression
|
||||
val codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression
|
||||
) : InExpressionGenerator {
|
||||
private val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext)
|
||||
private val isInverted = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
|
||||
private val isInverted = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
|
||||
|
||||
override fun generate(argument: StackValue): BranchedValue =
|
||||
gen(argument).let { if (isInverted) Invert(it) else it }
|
||||
gen(argument).let { if (isInverted) Invert(it) else it }
|
||||
|
||||
private fun gen(argument: StackValue): BranchedValue =
|
||||
object : BranchedValue(argument, null, argument.type, Opcodes.IFEQ) {
|
||||
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||
invokeFunction(v)
|
||||
coerceTo(type, v)
|
||||
}
|
||||
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
invokeFunction(v)
|
||||
v.visitJumpInsn(if (jumpIfFalse) Opcodes.IFEQ else Opcodes.IFNE, jumpLabel)
|
||||
}
|
||||
|
||||
private fun invokeFunction(v: InstructionAdapter) {
|
||||
val result = codegen.invokeFunction(resolvedCall.call, resolvedCall, none())
|
||||
result.put(result.type, v)
|
||||
}
|
||||
object : BranchedValue(argument, null, argument.type, Opcodes.IFEQ) {
|
||||
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||
invokeFunction(v)
|
||||
coerceTo(type, v)
|
||||
}
|
||||
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
invokeFunction(v)
|
||||
v.visitJumpInsn(if (jumpIfFalse) Opcodes.IFEQ else Opcodes.IFNE, jumpLabel)
|
||||
}
|
||||
|
||||
private fun invokeFunction(v: InstructionAdapter) {
|
||||
val result = codegen.invokeFunction(resolvedCall.call, resolvedCall, none())
|
||||
result.put(result.type, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
+89
-94
@@ -26,120 +26,115 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class InContinuousRangeOfComparableExpressionGenerator(
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
private val boundedValue: BoundedValue,
|
||||
private val frameMap: FrameMap
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
private val boundedValue: BoundedValue,
|
||||
private val frameMap: FrameMap
|
||||
) : InExpressionGenerator {
|
||||
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
|
||||
private val comparisonGenerator = ObjectComparisonGenerator
|
||||
|
||||
override fun generate(argument: StackValue): BranchedValue =
|
||||
gen(argument).let { if (isNotIn) Invert(it) else it }
|
||||
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)
|
||||
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
|
||||
|
||||
frameMap.useTmpVar(operandType) { arg1Var ->
|
||||
val exitLabel1 = Label()
|
||||
val exitLabel2 = Label()
|
||||
|
||||
boundedValue.putHighLow(v, operandType)
|
||||
|
||||
arg1.put(operandType, v)
|
||||
v.store(arg1Var, operandType)
|
||||
v.load(arg1Var, operandType)
|
||||
|
||||
// On stack: high low arg
|
||||
// if (low bound is NOT satisfied) goto exitLabel1
|
||||
if (boundedValue.isLowInclusive) {
|
||||
// arg < low
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfLess(v, exitLabel1)
|
||||
} else {
|
||||
// arg <= low
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfLessOrEqual(v, exitLabel1)
|
||||
}
|
||||
else {
|
||||
genJumpIfTrue(v, jumpLabel)
|
||||
|
||||
v.load(arg1Var, operandType)
|
||||
// On stack: high arg
|
||||
// if (high bound is satisfied) goto jumpLabel
|
||||
if (boundedValue.isHighInclusive) {
|
||||
// arg <= high
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
|
||||
} else {
|
||||
// arg < high
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfLess(v, jumpLabel)
|
||||
}
|
||||
v.goTo(exitLabel2)
|
||||
|
||||
v.mark(exitLabel1)
|
||||
AsmUtil.pop(v, operandType)
|
||||
|
||||
v.mark(exitLabel2)
|
||||
}
|
||||
|
||||
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
|
||||
// if (arg is in range) goto jumpLabel
|
||||
}
|
||||
|
||||
frameMap.useTmpVar(operandType) { arg1Var ->
|
||||
val exitLabel1 = Label()
|
||||
val exitLabel2 = Label()
|
||||
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
|
||||
// if (arg is NOT in range) goto jumpLabel
|
||||
|
||||
boundedValue.putHighLow(v, operandType)
|
||||
frameMap.useTmpVar(operandType) { arg1Var ->
|
||||
val cmpHighLabel = Label()
|
||||
|
||||
arg1.put(operandType, v)
|
||||
v.store(arg1Var, operandType)
|
||||
v.load(arg1Var, operandType)
|
||||
boundedValue.putHighLow(v, operandType)
|
||||
|
||||
// On stack: high low arg
|
||||
// if (low bound is NOT satisfied) goto exitLabel1
|
||||
if (boundedValue.isLowInclusive) {
|
||||
// arg < low
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfLess(v, exitLabel1)
|
||||
}
|
||||
else {
|
||||
// arg <= low
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfLessOrEqual(v, exitLabel1)
|
||||
}
|
||||
arg1.put(operandType, v)
|
||||
v.store(arg1Var, operandType)
|
||||
v.load(arg1Var, operandType)
|
||||
|
||||
v.load(arg1Var, operandType)
|
||||
// On stack: high arg
|
||||
// if (high bound is satisfied) goto jumpLabel
|
||||
if (boundedValue.isHighInclusive) {
|
||||
// arg <= high
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
|
||||
}
|
||||
else {
|
||||
// arg < high
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfLess(v, jumpLabel)
|
||||
}
|
||||
v.goTo(exitLabel2)
|
||||
|
||||
v.mark(exitLabel1)
|
||||
AsmUtil.pop(v, operandType)
|
||||
|
||||
v.mark(exitLabel2)
|
||||
// On stack: high low arg
|
||||
// if ([low bound is satisfied]) goto cmpHighLabel
|
||||
if (boundedValue.isLowInclusive) {
|
||||
// arg >= low
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfGreaterOrEqual(v, cmpHighLabel)
|
||||
} else {
|
||||
// arg > low
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfGreater(v, cmpHighLabel)
|
||||
}
|
||||
|
||||
}
|
||||
// Low bound is NOT satisfied, clear stack and goto jumpLabel
|
||||
AsmUtil.pop(v, operandType)
|
||||
v.goTo(jumpLabel)
|
||||
|
||||
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
|
||||
// if (arg is NOT in range) goto jumpLabel
|
||||
|
||||
frameMap.useTmpVar(operandType) { arg1Var ->
|
||||
val cmpHighLabel = Label()
|
||||
|
||||
boundedValue.putHighLow(v, operandType)
|
||||
|
||||
arg1.put(operandType, v)
|
||||
v.store(arg1Var, operandType)
|
||||
v.load(arg1Var, operandType)
|
||||
|
||||
// On stack: high low arg
|
||||
// if ([low bound is satisfied]) goto cmpHighLabel
|
||||
if (boundedValue.isLowInclusive) {
|
||||
// arg >= low
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfGreaterOrEqual(v, cmpHighLabel)
|
||||
}
|
||||
else {
|
||||
// arg > low
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfGreater(v, cmpHighLabel)
|
||||
}
|
||||
|
||||
// Low bound is NOT satisfied, clear stack and goto jumpLabel
|
||||
AsmUtil.pop(v, operandType)
|
||||
v.goTo(jumpLabel)
|
||||
|
||||
v.mark(cmpHighLabel)
|
||||
v.load(arg1Var, operandType)
|
||||
// On stack: high arg
|
||||
// if ([high bound is NOT satisfied]) goto jumpLabel
|
||||
if (boundedValue.isHighInclusive) {
|
||||
// arg > high
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfGreater(v, jumpLabel)
|
||||
}
|
||||
else {
|
||||
// arg >= high
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
|
||||
}
|
||||
v.mark(cmpHighLabel)
|
||||
v.load(arg1Var, operandType)
|
||||
// On stack: high arg
|
||||
// if ([high bound is NOT satisfied]) goto jumpLabel
|
||||
if (boundedValue.isHighInclusive) {
|
||||
// arg > high
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfGreater(v, jumpLabel)
|
||||
} else {
|
||||
// arg >= high
|
||||
v.swap()
|
||||
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
-75
@@ -27,10 +27,10 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class InFloatingPointRangeLiteralExpressionGenerator(
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
private val rangeLiteral: SimpleBoundedValue,
|
||||
private val comparisonGenerator: ComparisonGenerator,
|
||||
private val frameMap: FrameMap
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
private val rangeLiteral: SimpleBoundedValue,
|
||||
private val comparisonGenerator: ComparisonGenerator,
|
||||
private val frameMap: FrameMap
|
||||
) : InExpressionGenerator {
|
||||
init {
|
||||
assert(rangeLiteral.isLowInclusive && rangeLiteral.isHighInclusive) { "Floating point range literal bounds should be inclusive" }
|
||||
@@ -39,79 +39,77 @@ class InFloatingPointRangeLiteralExpressionGenerator(
|
||||
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
|
||||
|
||||
override fun generate(argument: StackValue): BranchedValue =
|
||||
gen(argument).let { if (isNotIn) Invert(it) else it }
|
||||
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
|
||||
// =>
|
||||
// if (arg is NOT in range) goto exitLabel
|
||||
// goto jumpLabel
|
||||
// exitLabel:
|
||||
|
||||
frameMap.useTmpVar(operandType) { argVar ->
|
||||
val exitLabel = Label()
|
||||
genJumpIfFalse(v, exitLabel)
|
||||
v.goTo(jumpLabel)
|
||||
v.mark(exitLabel)
|
||||
}
|
||||
}
|
||||
|
||||
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
|
||||
// if (arg is NOT in range) goto jumpLabel
|
||||
|
||||
frameMap.useTmpVar(operandType) { argVar ->
|
||||
// Evaluate low and high bounds once (unless they have no side effects)
|
||||
val (lowValue, lowTmpType) = introduceTemporaryIfRequired(v, rangeLiteral.lowBound, operandType)
|
||||
val (highValue, highTmpType) = introduceTemporaryIfRequired(v, rangeLiteral.highBound, operandType)
|
||||
|
||||
val argValue = StackValue.local(argVar, operandType)
|
||||
argValue.store(arg1, v)
|
||||
|
||||
// if (low bound is NOT satisfied) goto jumpLabel
|
||||
// arg < low
|
||||
argValue.put(operandType, v)
|
||||
lowValue.put(operandType, v)
|
||||
comparisonGenerator.jumpIfLess(v, jumpLabel)
|
||||
|
||||
// if (high bound is NOT satisfied) goto jumpLabel
|
||||
// arg > high
|
||||
argValue.put(operandType, v)
|
||||
highValue.put(operandType, v)
|
||||
comparisonGenerator.jumpIfGreater(v, jumpLabel)
|
||||
|
||||
highTmpType?.let { frameMap.leaveTemp(it) }
|
||||
lowTmpType?.let { frameMap.leaveTemp(it) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun introduceTemporaryIfRequired(v: InstructionAdapter, value: StackValue, type: Type): Pair<StackValue, Type?> {
|
||||
val resultValue: StackValue
|
||||
val resultType: Type?
|
||||
|
||||
if (value.canHaveSideEffects()) {
|
||||
val index = frameMap.enterTemp(type)
|
||||
resultValue = StackValue.local(index, type)
|
||||
resultType = type
|
||||
resultValue.store(value, v)
|
||||
}
|
||||
else {
|
||||
resultValue = value
|
||||
resultType = null
|
||||
}
|
||||
|
||||
return Pair(resultValue, resultType)
|
||||
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
|
||||
// =>
|
||||
// if (arg is NOT in range) goto exitLabel
|
||||
// goto jumpLabel
|
||||
// exitLabel:
|
||||
|
||||
frameMap.useTmpVar(operandType) { argVar ->
|
||||
val exitLabel = Label()
|
||||
genJumpIfFalse(v, exitLabel)
|
||||
v.goTo(jumpLabel)
|
||||
v.mark(exitLabel)
|
||||
}
|
||||
}
|
||||
|
||||
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
|
||||
// if (arg is NOT in range) goto jumpLabel
|
||||
|
||||
frameMap.useTmpVar(operandType) { argVar ->
|
||||
// Evaluate low and high bounds once (unless they have no side effects)
|
||||
val (lowValue, lowTmpType) = introduceTemporaryIfRequired(v, rangeLiteral.lowBound, operandType)
|
||||
val (highValue, highTmpType) = introduceTemporaryIfRequired(v, rangeLiteral.highBound, operandType)
|
||||
|
||||
val argValue = StackValue.local(argVar, operandType)
|
||||
argValue.store(arg1, v)
|
||||
|
||||
// if (low bound is NOT satisfied) goto jumpLabel
|
||||
// arg < low
|
||||
argValue.put(operandType, v)
|
||||
lowValue.put(operandType, v)
|
||||
comparisonGenerator.jumpIfLess(v, jumpLabel)
|
||||
|
||||
// if (high bound is NOT satisfied) goto jumpLabel
|
||||
// arg > high
|
||||
argValue.put(operandType, v)
|
||||
highValue.put(operandType, v)
|
||||
comparisonGenerator.jumpIfGreater(v, jumpLabel)
|
||||
|
||||
highTmpType?.let { frameMap.leaveTemp(it) }
|
||||
lowTmpType?.let { frameMap.leaveTemp(it) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun introduceTemporaryIfRequired(v: InstructionAdapter, value: StackValue, type: Type): Pair<StackValue, Type?> {
|
||||
val resultValue: StackValue
|
||||
val resultType: Type?
|
||||
|
||||
if (value.canHaveSideEffects()) {
|
||||
val index = frameMap.enterTemp(type)
|
||||
resultValue = StackValue.local(index, type)
|
||||
resultType = type
|
||||
resultValue.store(value, v)
|
||||
} else {
|
||||
resultValue = value
|
||||
resultType = null
|
||||
}
|
||||
|
||||
return Pair(resultValue, resultType)
|
||||
}
|
||||
}
|
||||
}
|
||||
+94
-99
@@ -26,111 +26,106 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class InIntegralContinuousRangeExpressionGenerator(
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
private val boundedValue: BoundedValue,
|
||||
private val comparisonGenerator: ComparisonGenerator,
|
||||
private val frameMap: FrameMap
|
||||
operatorReference: KtSimpleNameExpression,
|
||||
private val boundedValue: BoundedValue,
|
||||
private val comparisonGenerator: ComparisonGenerator,
|
||||
private val frameMap: FrameMap
|
||||
) : InExpressionGenerator {
|
||||
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
|
||||
|
||||
override fun generate(argument: StackValue): BranchedValue =
|
||||
gen(argument).let { if (isNotIn) Invert(it) else it }
|
||||
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
|
||||
frameMap.useTmpVar(operandType) { arg1Var ->
|
||||
val exitLabel1 = Label()
|
||||
val exitLabel2 = Label()
|
||||
|
||||
boundedValue.putHighLow(v, operandType)
|
||||
|
||||
arg1.put(operandType, v)
|
||||
v.store(arg1Var, operandType)
|
||||
v.load(arg1Var, operandType)
|
||||
|
||||
// On stack: high 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)
|
||||
}
|
||||
|
||||
v.load(arg1Var, operandType)
|
||||
// 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.pop(v, operandType)
|
||||
|
||||
v.mark(exitLabel2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
|
||||
// if (arg is NOT in range) goto jumpLabel
|
||||
|
||||
frameMap.useTmpVar(operandType) { arg1Var ->
|
||||
val cmpHighLabel = Label()
|
||||
|
||||
boundedValue.putHighLow(v, operandType)
|
||||
|
||||
arg1.put(operandType, v)
|
||||
v.store(arg1Var, operandType)
|
||||
v.load(arg1Var, operandType)
|
||||
|
||||
// On stack: high 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.pop(v, operandType)
|
||||
v.goTo(jumpLabel)
|
||||
|
||||
v.mark(cmpHighLabel)
|
||||
v.load(arg1Var, operandType)
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
frameMap.useTmpVar(operandType) { arg1Var ->
|
||||
val exitLabel1 = Label()
|
||||
val exitLabel2 = Label()
|
||||
|
||||
boundedValue.putHighLow(v, operandType)
|
||||
|
||||
arg1.put(operandType, v)
|
||||
v.store(arg1Var, operandType)
|
||||
v.load(arg1Var, operandType)
|
||||
|
||||
// On stack: high 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)
|
||||
}
|
||||
|
||||
v.load(arg1Var, operandType)
|
||||
// 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.pop(v, operandType)
|
||||
|
||||
v.mark(exitLabel2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
|
||||
// if (arg is NOT in range) goto jumpLabel
|
||||
|
||||
frameMap.useTmpVar(operandType) { arg1Var ->
|
||||
val cmpHighLabel = Label()
|
||||
|
||||
boundedValue.putHighLow(v, operandType)
|
||||
|
||||
arg1.put(operandType, v)
|
||||
v.store(arg1Var, operandType)
|
||||
v.load(arg1Var, operandType)
|
||||
|
||||
// On stack: high 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.pop(v, operandType)
|
||||
v.goTo(jumpLabel)
|
||||
|
||||
v.mark(cmpHighLabel)
|
||||
v.load(arg1Var, operandType)
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user