Make HeaderInfo.step not nullable and have handlers explicitly provide
the step expression. The semantics of "step" are now clearer: It will no longer be negated based on the "increasing" property; if the progression is decreasing (i.e., for "downTo" progressions), then it must be negative. The "increasing" property is still used when building the emptiness condition.
This commit is contained in:
committed by
max-kammerer
parent
40dbf8a3fd
commit
ed9ede8936
+8
-8
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||
import org.jetbrains.kotlin.backend.common.lower.matchers.IrCallMatcher
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
@@ -52,7 +51,7 @@ internal sealed class HeaderInfo(
|
||||
val progressionType: ProgressionType,
|
||||
val lowerBound: IrExpression,
|
||||
val upperBound: IrExpression,
|
||||
val step: IrExpression?, // null value denotes default step (1)
|
||||
val step: IrExpression,
|
||||
val increasing: Boolean,
|
||||
val closed: Boolean
|
||||
)
|
||||
@@ -61,7 +60,7 @@ internal class ProgressionHeaderInfo(
|
||||
progressionType: ProgressionType,
|
||||
lowerBound: IrExpression,
|
||||
upperBound: IrExpression,
|
||||
step: IrExpression? = null,
|
||||
step: IrExpression,
|
||||
increasing: Boolean = true,
|
||||
closed: Boolean = true
|
||||
) : HeaderInfo(progressionType, lowerBound, upperBound, step, increasing, closed)
|
||||
@@ -69,12 +68,13 @@ internal class ProgressionHeaderInfo(
|
||||
internal class ArrayHeaderInfo(
|
||||
lowerBound: IrExpression,
|
||||
upperBound: IrExpression,
|
||||
val arrayDeclaration: IrValueDeclaration
|
||||
step: IrExpression,
|
||||
val arrayVariable: IrVariable
|
||||
) : HeaderInfo(
|
||||
ProgressionType.INT_PROGRESSION,
|
||||
lowerBound,
|
||||
upperBound,
|
||||
step = null,
|
||||
step,
|
||||
increasing = true,
|
||||
closed = false
|
||||
)
|
||||
@@ -102,9 +102,9 @@ private class ProgressionHeaderInfoBuilder(val context: CommonBackendContext) :
|
||||
|
||||
private val progressionHandlers = listOf(
|
||||
IndicesHandler(context),
|
||||
UntilHandler(progressionElementTypes),
|
||||
DownToHandler(progressionElementTypes),
|
||||
RangeToHandler(progressionElementTypes)
|
||||
UntilHandler(context, progressionElementTypes),
|
||||
DownToHandler(context, progressionElementTypes),
|
||||
RangeToHandler(context, progressionElementTypes)
|
||||
)
|
||||
|
||||
override fun visitElement(element: IrElement, data: Nothing?): HeaderInfo? = null
|
||||
|
||||
+3
-27
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrWhileLoopImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
@@ -93,7 +92,7 @@ internal class ArrayLoopHeader(
|
||||
step: IrVariable
|
||||
) : ForLoopHeader(inductionVariable, bound, last, step, ProgressionType.INT_PROGRESSION) {
|
||||
|
||||
private val arrayDeclaration = headerInfo.arrayDeclaration
|
||||
private val arrayDeclaration = headerInfo.arrayVariable
|
||||
|
||||
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) {
|
||||
val arrayClass = (arrayDeclaration.type.classifierOrNull) as IrClassSymbol
|
||||
@@ -143,7 +142,7 @@ internal class HeaderProcessor(
|
||||
val progressionInfo = headerInfoBuilder.build(variable)
|
||||
?: return null
|
||||
if (progressionInfo is ArrayHeaderInfo) {
|
||||
progressionInfo.arrayDeclaration.parent = variable.parent
|
||||
progressionInfo.arrayVariable.parent = variable.parent
|
||||
}
|
||||
with(builder) {
|
||||
with(progressionInfo) {
|
||||
@@ -168,11 +167,7 @@ internal class HeaderProcessor(
|
||||
origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE
|
||||
)
|
||||
|
||||
val stepExpression = if (step != null) {
|
||||
ensureNotNullable(if (increasing) step else step.unaryMinus())
|
||||
} else {
|
||||
defaultStep(startOffset, endOffset)
|
||||
}
|
||||
val stepExpression = ensureNotNullable(step)
|
||||
|
||||
val stepValue = scope.createTemporaryVariable(
|
||||
stepExpression,
|
||||
@@ -237,23 +232,4 @@ internal class HeaderProcessor(
|
||||
} else {
|
||||
expression
|
||||
}
|
||||
|
||||
private fun IrExpression.unaryMinus(): IrExpression {
|
||||
val unaryOperator = symbols.getUnaryOperator(OperatorNameConventions.UNARY_MINUS, type.toKotlinType())
|
||||
return IrCallImpl(startOffset, endOffset, unaryOperator.owner.returnType, unaryOperator).apply {
|
||||
dispatchReceiver = this@unaryMinus
|
||||
}
|
||||
}
|
||||
|
||||
private fun HeaderInfo.defaultStep(startOffset: Int, endOffset: Int): IrExpression {
|
||||
val type = progressionType.elementType(context.irBuiltIns)
|
||||
val step = if (increasing) 1 else -1
|
||||
return when {
|
||||
type.isInt() || type.isChar() ->
|
||||
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, step)
|
||||
type.isLong() ->
|
||||
IrConstImpl.long(startOffset, endOffset, context.irBuiltIns.longType, step.toLong())
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
-25
@@ -14,16 +14,19 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.builders.irInt
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.properties
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
|
||||
// TODO: What if functions like Int.rangeTo(Char) will be added to stdlib later?
|
||||
internal class RangeToHandler(val progressionElementTypes: Collection<SimpleType>) : ProgressionHandler {
|
||||
internal class RangeToHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<SimpleType>) :
|
||||
ProgressionHandler {
|
||||
override val matcher = SimpleCalleeMatcher {
|
||||
dispatchReceiver { it != null && it.type.toKotlinType() in progressionElementTypes }
|
||||
fqName { it.pathSegments().last() == Name.identifier("rangeTo") }
|
||||
@@ -32,49 +35,64 @@ internal class RangeToHandler(val progressionElementTypes: Collection<SimpleType
|
||||
}
|
||||
|
||||
override fun build(call: IrCall, data: ProgressionType) =
|
||||
ProgressionHeaderInfo(data, call.dispatchReceiver!!, call.getValueArgument(0)!!)
|
||||
with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) {
|
||||
ProgressionHeaderInfo(
|
||||
data,
|
||||
lowerBound = call.dispatchReceiver!!,
|
||||
upperBound = call.getValueArgument(0)!!,
|
||||
step = irInt(1)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class DownToHandler(val progressionElementTypes: Collection<SimpleType>) : ProgressionHandler {
|
||||
internal class DownToHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<SimpleType>) :
|
||||
ProgressionHandler {
|
||||
override val matcher = SimpleCalleeMatcher {
|
||||
singleArgumentExtension(FqName("kotlin.ranges.downTo"), progressionElementTypes)
|
||||
parameterCount { it == 1 }
|
||||
parameter(0) { it.type.toKotlinType() in progressionElementTypes }
|
||||
}
|
||||
|
||||
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
||||
ProgressionHeaderInfo(
|
||||
data,
|
||||
call.extensionReceiver!!,
|
||||
call.getValueArgument(0)!!,
|
||||
increasing = false
|
||||
)
|
||||
with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) {
|
||||
ProgressionHeaderInfo(
|
||||
data,
|
||||
lowerBound = call.extensionReceiver!!,
|
||||
upperBound = call.getValueArgument(0)!!,
|
||||
step = irInt(-1),
|
||||
increasing = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class UntilHandler(val progressionElementTypes: Collection<SimpleType>) : ProgressionHandler {
|
||||
internal class UntilHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<SimpleType>) :
|
||||
ProgressionHandler {
|
||||
override val matcher = SimpleCalleeMatcher {
|
||||
singleArgumentExtension(FqName("kotlin.ranges.until"), progressionElementTypes)
|
||||
parameterCount { it == 1 }
|
||||
parameter(0) { it.type.toKotlinType() in progressionElementTypes }
|
||||
}
|
||||
|
||||
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
||||
ProgressionHeaderInfo(
|
||||
data,
|
||||
call.extensionReceiver!!,
|
||||
call.getValueArgument(0)!!,
|
||||
closed = false
|
||||
)
|
||||
with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) {
|
||||
ProgressionHeaderInfo(
|
||||
data,
|
||||
lowerBound = call.extensionReceiver!!,
|
||||
upperBound = call.getValueArgument(0)!!,
|
||||
step = irInt(1),
|
||||
closed = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class IndicesHandler(val context: CommonBackendContext) : ProgressionHandler {
|
||||
|
||||
override val matcher = createIrCallMatcher {
|
||||
callee {
|
||||
fqName { it == FqName("kotlin.collections.<get-indices>") }
|
||||
parameterCount { it == 0 }
|
||||
}
|
||||
override val matcher = SimpleCalleeMatcher {
|
||||
// TODO: Handle Collection<*>.indices
|
||||
// TODO: Handle CharSequence.indices
|
||||
extensionReceiver { it != null && KotlinBuiltIns.isArrayOrPrimitiveArray(it.type.toKotlinType()) }
|
||||
fqName { it == FqName("kotlin.collections.<get-indices>") }
|
||||
parameterCount { it == 0 }
|
||||
}
|
||||
|
||||
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
||||
@@ -85,7 +103,13 @@ internal class IndicesHandler(val context: CommonBackendContext) : ProgressionHa
|
||||
val upperBound = irCall(arraySizeProperty.getter!!).apply {
|
||||
dispatchReceiver = call.extensionReceiver
|
||||
}
|
||||
ProgressionHeaderInfo(data, lowerBound, upperBound, closed = false)
|
||||
ProgressionHeaderInfo(
|
||||
data,
|
||||
lowerBound,
|
||||
upperBound,
|
||||
step = irInt(1),
|
||||
closed = false
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -114,6 +138,11 @@ internal class ArrayIterationHandler(val context: CommonBackendContext) : Header
|
||||
val upperBound = irCall(arraySizeProperty.getter!!).apply {
|
||||
dispatchReceiver = irGet(arrayReference)
|
||||
}
|
||||
ArrayHeaderInfo(irInt(0), upperBound, arrayReference)
|
||||
ArrayHeaderInfo(
|
||||
lowerBound = irInt(0),
|
||||
upperBound = upperBound,
|
||||
step = irInt(1),
|
||||
arrayVariable = arrayReference
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user