Add DefaultProgressionHandler that handles for-loops over
non-specialized progressions, including "step" progressions. DefaultProgressionHandler uses the "first/last/step" properties of the progression when building the loop header.
This commit is contained in:
committed by
max-kammerer
parent
301ac90770
commit
ea9572ad28
+11
-3
@@ -134,12 +134,20 @@ private class ProgressionHeaderInfoBuilder(val context: CommonBackendContext) :
|
||||
}
|
||||
|
||||
internal class HeaderInfoBuilder(context: CommonBackendContext) {
|
||||
private val progressionInfoBuilder = ProgressionHeaderInfoBuilder(context)
|
||||
private val progressionHeaderInfoBuilder = ProgressionHeaderInfoBuilder(context)
|
||||
private val arrayIterationHandler = ArrayIterationHandler(context)
|
||||
private val defaultProgressionHandler = DefaultProgressionHandler(context)
|
||||
|
||||
fun build(variable: IrVariable): HeaderInfo? {
|
||||
val initializer = variable.initializer!! as IrCall
|
||||
// TODO: Merge DefaultProgressionHandler into ProgressionHeaderInfoBuilder. Not
|
||||
// straightforward because ProgressionHeaderInfoBuilder works only on calls and not just
|
||||
// any progression expression (i.e., progression may not be a call result).
|
||||
|
||||
// DefaultProgressionHandler must come AFTER ProgressionHeaderInfoBuilder, which handles
|
||||
// more specialized forms of progressions.
|
||||
val initializer = variable.initializer as IrCall
|
||||
return arrayIterationHandler.handle(initializer, null)
|
||||
?: initializer.dispatchReceiver?.accept(progressionInfoBuilder, null)
|
||||
?: initializer.dispatchReceiver?.accept(progressionHeaderInfoBuilder, null)
|
||||
?: defaultProgressionHandler.handle(initializer, null)
|
||||
}
|
||||
}
|
||||
+38
@@ -161,6 +161,44 @@ internal class IndicesHandler(val context: CommonBackendContext) : ProgressionHa
|
||||
}
|
||||
}
|
||||
|
||||
/** Builds a [HeaderInfo] for progressions not handled by more specialized handlers. */
|
||||
internal class DefaultProgressionHandler(private val context: CommonBackendContext) : HeaderInfoHandler<Nothing?> {
|
||||
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
override val matcher = createIrCallMatcher {
|
||||
origin { it == IrStatementOrigin.FOR_LOOP_ITERATOR }
|
||||
dispatchReceiver { it != null && ProgressionType.fromIrType(it.type, symbols) != null }
|
||||
}
|
||||
|
||||
override fun build(call: IrCall, progressionType: Nothing?): HeaderInfo? =
|
||||
with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) {
|
||||
// Directly use the `first/last/step` properties of the progression.
|
||||
val progression = scope.createTemporaryVariable(call.dispatchReceiver!!)
|
||||
val progressionClass = progression.type.getClass()!!
|
||||
val firstProperty = progressionClass.properties.first { it.name.asString() == "first" }
|
||||
val first = irCall(firstProperty.getter!!).apply {
|
||||
dispatchReceiver = irGet(progression)
|
||||
}
|
||||
val lastProperty = progressionClass.properties.first { it.name.asString() == "last" }
|
||||
val last = irCall(lastProperty.getter!!).apply {
|
||||
dispatchReceiver = irGet(progression)
|
||||
}
|
||||
val stepProperty = progressionClass.properties.first { it.name.asString() == "step" }
|
||||
val step = irCall(stepProperty.getter!!).apply {
|
||||
dispatchReceiver = irGet(progression)
|
||||
}
|
||||
|
||||
ProgressionHeaderInfo(
|
||||
ProgressionType.fromIrType(progression.type, symbols)!!,
|
||||
first,
|
||||
last,
|
||||
step,
|
||||
additionalVariables = listOf(progression)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class ArrayIterationHandler(private val context: CommonBackendContext) : HeaderInfoHandler<Nothing?> {
|
||||
|
||||
private val intDecFun = ProgressionType.INT_PROGRESSION.decFun(context.irBuiltIns)
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun test(coll: Collection<*>?): Int {
|
||||
|
||||
+1
@@ -11,3 +11,4 @@ fun Int.digitsUpto(end: Int): Int {
|
||||
// 0 getEnd
|
||||
// 0 getFirst
|
||||
// 0 getLast
|
||||
// 0 getStep
|
||||
@@ -7,4 +7,5 @@ fun f() {
|
||||
// 0 getStart
|
||||
// 0 getEnd
|
||||
// 0 getFirst
|
||||
// 0 getLast
|
||||
// 0 getLast
|
||||
// 0 getStep
|
||||
@@ -7,4 +7,5 @@ fun f(a: Int, b: Int) {
|
||||
// 0 getStart
|
||||
// 0 getEnd
|
||||
// 0 getFirst
|
||||
// 0 getLast
|
||||
// 0 getLast
|
||||
// 0 getStep
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
fun f() {
|
||||
for (i in 0..5 step 2) {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
fun f(r: IntRange) {
|
||||
for (i in r) {
|
||||
}
|
||||
@@ -8,4 +7,5 @@ fun f(r: IntRange) {
|
||||
// 0 getStart
|
||||
// 0 getEnd
|
||||
// 1 getFirst
|
||||
// 1 getLast
|
||||
// 1 getLast
|
||||
// 1 getStep
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
fun Int.until(other: Int) = this..other - 1
|
||||
fun foo() {
|
||||
val range = 1 until 2
|
||||
|
||||
Reference in New Issue
Block a user