Refactor ForLoopHeader to clarify the purpose of its functions.

This commit is contained in:
Mark Punzalan
2019-10-31 13:06:18 -07:00
committed by max-kammerer
parent 7f803e60b6
commit 60c05362d2
2 changed files with 50 additions and 39 deletions
@@ -150,14 +150,13 @@ private class RangeLoopTransformer(
?: return null // If the for-loop cannot be lowered. ?: return null // If the for-loop cannot be lowered.
iteratorToLoopHeader[variable.symbol] = forLoopInfo iteratorToLoopHeader[variable.symbol] = forLoopInfo
// Lower into a composite with additional declarations (e.g., induction variable) // Lower into a composite with additional statements (e.g., induction variable) used in the loop condition and body.
// used in the loop condition and body.
return IrCompositeImpl( return IrCompositeImpl(
variable.startOffset, variable.startOffset,
variable.endOffset, variable.endOffset,
context.irBuiltIns.unitType, context.irBuiltIns.unitType,
null, null,
forLoopInfo.declarations forLoopInfo.loopInitStatements
) )
} }
@@ -213,26 +212,22 @@ private class RangeLoopTransformer(
val initializer = variable.initializer as IrCall val initializer = variable.initializer as IrCall
val forLoopInfo = getLoopHeader(initializer) val forLoopInfo = getLoopHeader(initializer)
?: return null // If the for-loop cannot be lowered. ?: return null // If the for-loop cannot be lowered.
forLoopInfo.loopVariable = variable
// The "next" statement (at the top of the loop): // The "next" statement (at the top of the loop):
// //
// val i = it.next() // val i = it.next()
// //
// ...is lowered into: // ...is lowered into something like:
// //
// val i = initializeLoopVariable() // `inductionVariable` for progressions // val i = inductionVariable // For progressions, or `array[inductionVariable]` for arrays
// // `array[inductionVariable]` for arrays
// inductionVariable = inductionVariable + step // inductionVariable = inductionVariable + step
return with(context.createIrBuilder(getScopeOwnerSymbol(), initializer.startOffset, initializer.endOffset)) { return with(context.createIrBuilder(getScopeOwnerSymbol(), initializer.startOffset, initializer.endOffset)) {
variable.initializer = forLoopInfo.initializeLoopVariable(symbols, this)
val increment = forLoopInfo.incrementInductionVariable(this)
IrCompositeImpl( IrCompositeImpl(
variable.startOffset, variable.startOffset,
variable.endOffset, variable.endOffset,
context.irBuiltIns.unitType, context.irBuiltIns.unitType,
IrStatementOrigin.FOR_LOOP_NEXT, IrStatementOrigin.FOR_LOOP_NEXT,
listOf(variable, increment) forLoopInfo.initializeIteration(variable, symbols, this)
) )
} }
} }
@@ -37,28 +37,36 @@ internal data class LoopReplacement(
val replacementExpression: IrExpression val replacementExpression: IrExpression
) )
/** Contains information about variables used in the loop. */ internal interface ForLoopHeader {
internal sealed class ForLoopHeader( /** Statements used to initialize the entire loop (e.g., declare induction variable). */
val loopInitStatements: List<IrStatement>
/** Statements used to initialize an iteration of the loop (e.g., assign loop variable). */
fun initializeIteration(
loopVariable: IrVariable,
symbols: Symbols<CommonBackendContext>,
builder: DeclarationIrBuilder
): List<IrStatement>
/** Builds a new loop from the old loop. */
fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?): LoopReplacement
}
internal abstract class NumericForLoopHeader(
protected open val headerInfo: HeaderInfo, protected open val headerInfo: HeaderInfo,
val inductionVariable: IrVariable, val inductionVariable: IrVariable,
lastExpression: IrExpression, lastExpression: IrExpression,
val step: IrVariable, val step: IrVariable,
var loopVariable: IrVariable? = null,
val isLastInclusive: Boolean, val isLastInclusive: Boolean,
val declarations: List<IrVariable> override val loopInitStatements: List<IrStatement>
) { ) : ForLoopHeader {
val lastExpression: IrExpression = lastExpression val lastExpression: IrExpression = lastExpression
// Always copy `lastExpression` is it may be used in multiple conditions. // Always copy `lastExpression` is it may be used in multiple conditions.
get() = field.deepCopyWithSymbols() get() = field.deepCopyWithSymbols()
/** Expression used to initialize the loop variable at the beginning of the loop. */
abstract fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder): IrExpression
/** Builds a new loop from the old loop. */
abstract fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?): LoopReplacement
/** Statement used to increment the induction variable. */ /** Statement used to increment the induction variable. */
fun incrementInductionVariable(builder: DeclarationIrBuilder): IrStatement = with(builder) { protected fun incrementInductionVariable(builder: DeclarationIrBuilder): IrStatement = with(builder) {
// inductionVariable = inductionVariable + step // inductionVariable = inductionVariable + step
val plusFun = inductionVariable.type.getClass()!!.functions.single { val plusFun = inductionVariable.type.getClass()!!.functions.single {
it.name == OperatorNameConventions.PLUS && it.name == OperatorNameConventions.PLUS &&
@@ -133,19 +141,25 @@ internal class ProgressionLoopHeader(
inductionVariable: IrVariable, inductionVariable: IrVariable,
lastExpression: IrExpression, lastExpression: IrExpression,
step: IrVariable, step: IrVariable,
declarations: List<IrVariable> loopInitStatements: List<IrStatement>
) : ForLoopHeader( ) : NumericForLoopHeader(
headerInfo, inductionVariable, headerInfo, inductionVariable,
lastExpression = lastExpression, lastExpression = lastExpression,
step = step, step = step,
isLastInclusive = true, isLastInclusive = true,
declarations = declarations loopInitStatements = loopInitStatements
) { ) {
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) { private var loopVariable: IrVariable? = null
// loopVariable = inductionVariable
irGet(inductionVariable) override fun initializeIteration(loopVariable: IrVariable, symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) =
} with(builder) {
this@ProgressionLoopHeader.loopVariable = loopVariable
// loopVariable = inductionVariable
// inductionVariable = inductionVariable + step
loopVariable.initializer = irGet(inductionVariable)
listOf(loopVariable, incrementInductionVariable(this))
}
override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?) = override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?) =
with(builder) { with(builder) {
@@ -198,21 +212,23 @@ internal class IndexedGetLoopHeader(
inductionVariable: IrVariable, inductionVariable: IrVariable,
lastExpression: IrExpression, lastExpression: IrExpression,
step: IrVariable, step: IrVariable,
declarations: List<IrVariable> loopInitStatements: List<IrStatement>
) : ForLoopHeader( ) : NumericForLoopHeader(
headerInfo, inductionVariable, lastExpression, step, headerInfo, inductionVariable, lastExpression, step,
isLastInclusive = false, isLastInclusive = false,
declarations = declarations loopInitStatements = loopInitStatements
) { ) {
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) { override fun initializeIteration(loopVariable: IrVariable, symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) =
// inductionVar = loopVar[inductionVariable] with(builder) {
val indexedGetFun = with(headerInfo.expressionHandler) { headerInfo.objectVariable.type.getFunction } // loopVariable = objectVariable[inductionVariable]
irCall(indexedGetFun).apply { val indexedGetFun = with(headerInfo.expressionHandler) { headerInfo.objectVariable.type.getFunction }
dispatchReceiver = irGet(headerInfo.objectVariable) loopVariable.initializer = irCall(indexedGetFun).apply {
putValueArgument(0, irGet(inductionVariable)) dispatchReceiver = irGet(headerInfo.objectVariable)
putValueArgument(0, irGet(inductionVariable))
}
listOf(loopVariable, incrementInductionVariable(this))
} }
}
override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?): LoopReplacement = with(builder) { override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?): LoopReplacement = with(builder) {
// Loop is lowered into something like: // Loop is lowered into something like: