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)
|
||||
|
||||
Reference in New Issue
Block a user