Intrinsics for 'reversed': support non-literal range expressions

#KT-21323 In Progress
This commit is contained in:
Dmitry Petrov
2017-12-11 13:57:17 +03:00
parent 1493805f8e
commit beff4a1b92
18 changed files with 355 additions and 25 deletions
@@ -20,12 +20,14 @@ import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.ForInProgressionExpressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class PrimitiveProgressionRangeValue : RangeValue {
class PrimitiveProgressionRangeValue(private val rangeExpression: KtExpression) : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInProgressionExpressionLoopGenerator(codegen, forExpression)
ForInProgressionExpressionLoopGenerator(codegen, forExpression, rangeExpression)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
@@ -18,15 +18,21 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.ForInRangeInstanceLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class PrimitiveRangeRangeValue : RangeValue {
class PrimitiveRangeRangeValue(private val rangeExpression: KtExpression) : ReversableRangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInRangeInstanceLoopGenerator(codegen, forExpression)
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = false)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = true)
}
@@ -59,9 +59,9 @@ fun ExpressionCodegen.createRangeValueForExpression(rangeExpression: KtExpressio
}
isPrimitiveRange(rangeType) ->
PrimitiveRangeRangeValue()
PrimitiveRangeRangeValue(rangeExpression)
isPrimitiveProgression(rangeType) ->
PrimitiveProgressionRangeValue()
PrimitiveProgressionRangeValue(rangeExpression)
isSubtypeOfString(rangeType, builtIns) ->
CharSequenceRangeValue(true, AsmTypes.JAVA_STRING_TYPE)
isSubtypeOfCharSequence(rangeType, builtIns) ->
@@ -24,15 +24,11 @@ import org.jetbrains.kotlin.codegen.AsmUtil.genIncrement
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
abstract class AbstractForInRangeLoopGenerator : AbstractForInProgressionOrRangeLoopGenerator {
protected val step: Int
constructor(codegen: ExpressionCodegen, forExpression: KtForExpression, step: Int) : super(codegen, forExpression) {
assert(step == 1 || step == -1) { "'step' should be either 1 or -1: " + step }
this.step = step
}
constructor(codegen: ExpressionCodegen, forExpression: KtForExpression) : this(codegen, forExpression, 1)
abstract class AbstractForInRangeLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
protected val step: Int
) : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) {
override fun beforeLoop() {
super.beforeLoop()
@@ -83,4 +79,8 @@ abstract class AbstractForInRangeLoopGenerator : AbstractForInProgressionOrRange
loopParameter.store(StackValue.onStack(asmElementType), v)
}
}
init {
assert(step == 1 || step == -1) { "'step' should be either 1 or -1: " + step }
}
}
@@ -17,13 +17,16 @@
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
class ForInProgressionExpressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
: AbstractForInProgressionLoopGenerator(codegen, forExpression)
{
class ForInProgressionExpressionLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val rangeExpression: KtExpression
) : AbstractForInProgressionLoopGenerator(codegen, forExpression) {
override fun storeProgressionParametersToLocalVars() {
codegen.gen(forExpression.loopRange, asmLoopRangeType)
codegen.gen(rangeExpression, asmLoopRangeType)
v.dup()
v.dup()
@@ -17,21 +17,30 @@
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
class ForInRangeInstanceLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
) : AbstractForInRangeLoopGenerator(codegen, forExpression) {
forExpression: KtForExpression,
private val rangeExpression: KtExpression,
private val reversed: Boolean
) : AbstractForInRangeLoopGenerator(codegen, forExpression, if (reversed) -1 else 1) {
override fun storeRangeStartAndEnd() {
val loopRangeType = codegen.bindingContext.getType(forExpression.loopRange!!)!!
val loopRangeType = codegen.bindingContext.getType(rangeExpression)!!
val asmLoopRangeType = codegen.asmType(loopRangeType)
codegen.gen(forExpression.loopRange, asmLoopRangeType)
codegen.gen(rangeExpression, asmLoopRangeType)
v.dup()
// ranges inherit first and last from corresponding progressions
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
if (reversed) {
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, asmElementType, endVar)
}
else {
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
}
}
}