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.ir.Symbols
|
||||||
import org.jetbrains.kotlin.backend.common.lower.matchers.IrCallMatcher
|
import org.jetbrains.kotlin.backend.common.lower.matchers.IrCallMatcher
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
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.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
@@ -52,7 +51,7 @@ internal sealed class HeaderInfo(
|
|||||||
val progressionType: ProgressionType,
|
val progressionType: ProgressionType,
|
||||||
val lowerBound: IrExpression,
|
val lowerBound: IrExpression,
|
||||||
val upperBound: IrExpression,
|
val upperBound: IrExpression,
|
||||||
val step: IrExpression?, // null value denotes default step (1)
|
val step: IrExpression,
|
||||||
val increasing: Boolean,
|
val increasing: Boolean,
|
||||||
val closed: Boolean
|
val closed: Boolean
|
||||||
)
|
)
|
||||||
@@ -61,7 +60,7 @@ internal class ProgressionHeaderInfo(
|
|||||||
progressionType: ProgressionType,
|
progressionType: ProgressionType,
|
||||||
lowerBound: IrExpression,
|
lowerBound: IrExpression,
|
||||||
upperBound: IrExpression,
|
upperBound: IrExpression,
|
||||||
step: IrExpression? = null,
|
step: IrExpression,
|
||||||
increasing: Boolean = true,
|
increasing: Boolean = true,
|
||||||
closed: Boolean = true
|
closed: Boolean = true
|
||||||
) : HeaderInfo(progressionType, lowerBound, upperBound, step, increasing, closed)
|
) : HeaderInfo(progressionType, lowerBound, upperBound, step, increasing, closed)
|
||||||
@@ -69,12 +68,13 @@ internal class ProgressionHeaderInfo(
|
|||||||
internal class ArrayHeaderInfo(
|
internal class ArrayHeaderInfo(
|
||||||
lowerBound: IrExpression,
|
lowerBound: IrExpression,
|
||||||
upperBound: IrExpression,
|
upperBound: IrExpression,
|
||||||
val arrayDeclaration: IrValueDeclaration
|
step: IrExpression,
|
||||||
|
val arrayVariable: IrVariable
|
||||||
) : HeaderInfo(
|
) : HeaderInfo(
|
||||||
ProgressionType.INT_PROGRESSION,
|
ProgressionType.INT_PROGRESSION,
|
||||||
lowerBound,
|
lowerBound,
|
||||||
upperBound,
|
upperBound,
|
||||||
step = null,
|
step,
|
||||||
increasing = true,
|
increasing = true,
|
||||||
closed = false
|
closed = false
|
||||||
)
|
)
|
||||||
@@ -102,9 +102,9 @@ private class ProgressionHeaderInfoBuilder(val context: CommonBackendContext) :
|
|||||||
|
|
||||||
private val progressionHandlers = listOf(
|
private val progressionHandlers = listOf(
|
||||||
IndicesHandler(context),
|
IndicesHandler(context),
|
||||||
UntilHandler(progressionElementTypes),
|
UntilHandler(context, progressionElementTypes),
|
||||||
DownToHandler(progressionElementTypes),
|
DownToHandler(context, progressionElementTypes),
|
||||||
RangeToHandler(progressionElementTypes)
|
RangeToHandler(context, progressionElementTypes)
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun visitElement(element: IrElement, data: Nothing?): HeaderInfo? = null
|
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.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
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.IrDoWhileLoopImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrWhileLoopImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrWhileLoopImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
@@ -93,7 +92,7 @@ internal class ArrayLoopHeader(
|
|||||||
step: IrVariable
|
step: IrVariable
|
||||||
) : ForLoopHeader(inductionVariable, bound, last, step, ProgressionType.INT_PROGRESSION) {
|
) : 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) {
|
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) {
|
||||||
val arrayClass = (arrayDeclaration.type.classifierOrNull) as IrClassSymbol
|
val arrayClass = (arrayDeclaration.type.classifierOrNull) as IrClassSymbol
|
||||||
@@ -143,7 +142,7 @@ internal class HeaderProcessor(
|
|||||||
val progressionInfo = headerInfoBuilder.build(variable)
|
val progressionInfo = headerInfoBuilder.build(variable)
|
||||||
?: return null
|
?: return null
|
||||||
if (progressionInfo is ArrayHeaderInfo) {
|
if (progressionInfo is ArrayHeaderInfo) {
|
||||||
progressionInfo.arrayDeclaration.parent = variable.parent
|
progressionInfo.arrayVariable.parent = variable.parent
|
||||||
}
|
}
|
||||||
with(builder) {
|
with(builder) {
|
||||||
with(progressionInfo) {
|
with(progressionInfo) {
|
||||||
@@ -168,11 +167,7 @@ internal class HeaderProcessor(
|
|||||||
origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE
|
origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE
|
||||||
)
|
)
|
||||||
|
|
||||||
val stepExpression = if (step != null) {
|
val stepExpression = ensureNotNullable(step)
|
||||||
ensureNotNullable(if (increasing) step else step.unaryMinus())
|
|
||||||
} else {
|
|
||||||
defaultStep(startOffset, endOffset)
|
|
||||||
}
|
|
||||||
|
|
||||||
val stepValue = scope.createTemporaryVariable(
|
val stepValue = scope.createTemporaryVariable(
|
||||||
stepExpression,
|
stepExpression,
|
||||||
@@ -237,23 +232,4 @@ internal class HeaderProcessor(
|
|||||||
} else {
|
} else {
|
||||||
expression
|
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.irCall
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
import org.jetbrains.kotlin.ir.builders.irGet
|
||||||
import org.jetbrains.kotlin.ir.builders.irInt
|
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.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.ir.util.properties
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
|
|
||||||
// TODO: What if functions like Int.rangeTo(Char) will be added to stdlib later?
|
// 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 {
|
override val matcher = SimpleCalleeMatcher {
|
||||||
dispatchReceiver { it != null && it.type.toKotlinType() in progressionElementTypes }
|
dispatchReceiver { it != null && it.type.toKotlinType() in progressionElementTypes }
|
||||||
fqName { it.pathSegments().last() == Name.identifier("rangeTo") }
|
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) =
|
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 {
|
override val matcher = SimpleCalleeMatcher {
|
||||||
singleArgumentExtension(FqName("kotlin.ranges.downTo"), progressionElementTypes)
|
singleArgumentExtension(FqName("kotlin.ranges.downTo"), progressionElementTypes)
|
||||||
|
parameterCount { it == 1 }
|
||||||
parameter(0) { it.type.toKotlinType() in progressionElementTypes }
|
parameter(0) { it.type.toKotlinType() in progressionElementTypes }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
||||||
ProgressionHeaderInfo(
|
with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) {
|
||||||
data,
|
ProgressionHeaderInfo(
|
||||||
call.extensionReceiver!!,
|
data,
|
||||||
call.getValueArgument(0)!!,
|
lowerBound = call.extensionReceiver!!,
|
||||||
increasing = false
|
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 {
|
override val matcher = SimpleCalleeMatcher {
|
||||||
singleArgumentExtension(FqName("kotlin.ranges.until"), progressionElementTypes)
|
singleArgumentExtension(FqName("kotlin.ranges.until"), progressionElementTypes)
|
||||||
|
parameterCount { it == 1 }
|
||||||
parameter(0) { it.type.toKotlinType() in progressionElementTypes }
|
parameter(0) { it.type.toKotlinType() in progressionElementTypes }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
override fun build(call: IrCall, data: ProgressionType): HeaderInfo? =
|
||||||
ProgressionHeaderInfo(
|
with(context.createIrBuilder(call.symbol, call.startOffset, call.endOffset)) {
|
||||||
data,
|
ProgressionHeaderInfo(
|
||||||
call.extensionReceiver!!,
|
data,
|
||||||
call.getValueArgument(0)!!,
|
lowerBound = call.extensionReceiver!!,
|
||||||
closed = false
|
upperBound = call.getValueArgument(0)!!,
|
||||||
)
|
step = irInt(1),
|
||||||
|
closed = false
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class IndicesHandler(val context: CommonBackendContext) : ProgressionHandler {
|
internal class IndicesHandler(val context: CommonBackendContext) : ProgressionHandler {
|
||||||
|
|
||||||
override val matcher = createIrCallMatcher {
|
override val matcher = SimpleCalleeMatcher {
|
||||||
callee {
|
|
||||||
fqName { it == FqName("kotlin.collections.<get-indices>") }
|
|
||||||
parameterCount { it == 0 }
|
|
||||||
}
|
|
||||||
// TODO: Handle Collection<*>.indices
|
// TODO: Handle Collection<*>.indices
|
||||||
// TODO: Handle CharSequence.indices
|
// TODO: Handle CharSequence.indices
|
||||||
extensionReceiver { it != null && KotlinBuiltIns.isArrayOrPrimitiveArray(it.type.toKotlinType()) }
|
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? =
|
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 {
|
val upperBound = irCall(arraySizeProperty.getter!!).apply {
|
||||||
dispatchReceiver = call.extensionReceiver
|
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 {
|
val upperBound = irCall(arraySizeProperty.getter!!).apply {
|
||||||
dispatchReceiver = irGet(arrayReference)
|
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