From ed9ede8936151a38d3e2604a26a561a9e77cd201 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Tue, 19 Mar 2019 16:51:26 -0700 Subject: [PATCH] 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. --- .../backend/common/lower/loops/HeaderInfo.kt | 16 ++-- .../common/lower/loops/HeaderProcessor.kt | 30 +------ .../common/lower/loops/ProgressionHandlers.kt | 79 +++++++++++++------ 3 files changed, 65 insertions(+), 60 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt index 012fc6a2eba..2aefa6c28f6 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt @@ -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 diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt index daca346dc8e..cd39256eb92 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt @@ -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, 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() - } - } } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt index 22c080e02db..114ba8a701e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/ProgressionHandlers.kt @@ -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) : ProgressionHandler { +internal class RangeToHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection) : + 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) : ProgressionHandler { +internal class DownToHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection) : + 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) : ProgressionHandler { +internal class UntilHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection) : + 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.") } - 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.") } + 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 + ) } }