Ranges support. (#73)
This commit is contained in:
+8
-2
@@ -224,6 +224,11 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitConstructor(constructorDeclaration: IrConstructor) {
|
override fun visitConstructor(constructorDeclaration: IrConstructor) {
|
||||||
|
if (constructorDeclaration.descriptor.containingDeclaration.isIntrinsic) {
|
||||||
|
// Do not generate any ctors for intrinsic classes.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
codegen.prologue(constructorDeclaration)
|
codegen.prologue(constructorDeclaration)
|
||||||
val constructorDescriptor = constructorDeclaration.descriptor
|
val constructorDescriptor = constructorDeclaration.descriptor
|
||||||
val classDescriptor = DescriptorUtils.getContainingClass(constructorDescriptor)
|
val classDescriptor = DescriptorUtils.getContainingClass(constructorDescriptor)
|
||||||
@@ -389,8 +394,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration.descriptor.isIntrinsic) {
|
if (KotlinBuiltIns.isUnit(declaration.descriptor.defaultType)) {
|
||||||
// do not generate any code for intrinsic classes as they require special handling
|
// Do not generate any code for Unit.
|
||||||
|
// TODO: Unit has toString() operation, which we may want to support.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -574,3 +574,8 @@ task unreachable1(type: RunKonanTest) {
|
|||||||
goldValue = "1\n"
|
goldValue = "1\n"
|
||||||
source = "codegen/controlflow/unreachable1.kt"
|
source = "codegen/controlflow/unreachable1.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task range0(type: RunKonanTest) {
|
||||||
|
goldValue = "123\nabcd\n"
|
||||||
|
source = "runtime/collections/range0.kt"
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun main(args : Array<String>) {
|
||||||
|
for (i in 1..3) print(i)
|
||||||
|
println()
|
||||||
|
for (i in 'a'..'d') print(i)
|
||||||
|
println()
|
||||||
|
}
|
||||||
@@ -33,7 +33,9 @@ public final class Char : Comparable<Char> {
|
|||||||
external public operator fun dec(): Char
|
external public operator fun dec(): Char
|
||||||
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Char): CharRange
|
public operator fun rangeTo(other: Char): CharRange {
|
||||||
|
return CharRange(this, other)
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the value of this character as a `Byte`. */
|
/** Returns the value of this character as a `Byte`. */
|
||||||
@SymbolName("Kotlin_Char_toByte")
|
@SymbolName("Kotlin_Char_toByte")
|
||||||
|
|||||||
@@ -168,15 +168,6 @@ public final class Byte : Number(), Comparable<Byte> {
|
|||||||
@SymbolName("Kotlin_Byte_unaryMinus")
|
@SymbolName("Kotlin_Byte_unaryMinus")
|
||||||
external public operator fun unaryMinus(): Int
|
external public operator fun unaryMinus(): Int
|
||||||
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
|
||||||
// external public operator fun rangeTo(other: Byte): IntRange
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
|
||||||
// external public operator fun rangeTo(other: Short): IntRange
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
|
||||||
// external public operator fun rangeTo(other: Int): IntRange
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
|
||||||
// external public operator fun rangeTo(other: Long): LongRange
|
|
||||||
|
|
||||||
@SymbolName("Kotlin_Byte_toByte")
|
@SymbolName("Kotlin_Byte_toByte")
|
||||||
external public override fun toByte(): Byte
|
external public override fun toByte(): Byte
|
||||||
@SymbolName("Kotlin_Byte_toChar")
|
@SymbolName("Kotlin_Byte_toChar")
|
||||||
@@ -192,6 +183,23 @@ public final class Byte : Number(), Comparable<Byte> {
|
|||||||
@SymbolName("Kotlin_Byte_toDouble")
|
@SymbolName("Kotlin_Byte_toDouble")
|
||||||
external public override fun toDouble(): Double
|
external public override fun toDouble(): Double
|
||||||
|
|
||||||
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
|
public operator fun rangeTo(other: Byte): IntRange {
|
||||||
|
return IntRange(this.toInt(), other.toInt())
|
||||||
|
}
|
||||||
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
|
public operator fun rangeTo(other: Short): IntRange {
|
||||||
|
return IntRange(this.toInt(), other.toInt())
|
||||||
|
}
|
||||||
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
|
public operator fun rangeTo(other: Int): IntRange {
|
||||||
|
return IntRange(this.toInt(), other.toInt())
|
||||||
|
}
|
||||||
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
|
public operator fun rangeTo(other: Long): LongRange {
|
||||||
|
return LongRange(this.toLong(), other.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
// Konan-specific.
|
// Konan-specific.
|
||||||
@SymbolName("Kotlin_Byte_toString")
|
@SymbolName("Kotlin_Byte_toString")
|
||||||
external public override fun toString(): String
|
external public override fun toString(): String
|
||||||
@@ -206,7 +214,7 @@ public final class Short : Number(), Comparable<Short> {
|
|||||||
/**
|
/**
|
||||||
* A constant holding the minimum value an instance of Short can have.
|
* A constant holding the minimum value an instance of Short can have.
|
||||||
*/
|
*/
|
||||||
// public const val MIN_VALUE: Short = -32768
|
public const val MIN_VALUE: Short = -32768
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A constant holding the maximum value an instance of Short can have.
|
* A constant holding the maximum value an instance of Short can have.
|
||||||
@@ -366,13 +374,21 @@ public final class Short : Number(), Comparable<Short> {
|
|||||||
external public operator fun unaryMinus(): Int
|
external public operator fun unaryMinus(): Int
|
||||||
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Byte): IntRange
|
public operator fun rangeTo(other: Byte): IntRange {
|
||||||
|
return IntRange(this.toInt(), other.toInt())
|
||||||
|
}
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Short): IntRange
|
public operator fun rangeTo(other: Short): IntRange {
|
||||||
|
return IntRange(this.toInt(), other.toInt())
|
||||||
|
}
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Int): IntRange
|
public operator fun rangeTo(other: Int): IntRange {
|
||||||
|
return IntRange(this.toInt(), other.toInt())
|
||||||
|
}
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Long): LongRange
|
public operator fun rangeTo(other: Long): LongRange {
|
||||||
|
return LongRange(this.toLong(), other.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
@SymbolName("Kotlin_Short_toByte")
|
@SymbolName("Kotlin_Short_toByte")
|
||||||
external public override fun toByte(): Byte
|
external public override fun toByte(): Byte
|
||||||
@@ -562,15 +578,6 @@ public final class Int : Number(), Comparable<Int> {
|
|||||||
@SymbolName("Kotlin_Int_unaryMinus")
|
@SymbolName("Kotlin_Int_unaryMinus")
|
||||||
external public operator fun unaryMinus(): Int
|
external public operator fun unaryMinus(): Int
|
||||||
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
|
||||||
// external public operator fun rangeTo(other: Byte): IntRange
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
|
||||||
// external public operator fun rangeTo(other: Short): IntRange
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
|
||||||
// external public operator fun rangeTo(other: Int): IntRange
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
|
||||||
// external public operator fun rangeTo(other: Long): LongRange
|
|
||||||
|
|
||||||
/** Shifts this value left by [bits]. */
|
/** Shifts this value left by [bits]. */
|
||||||
@SymbolName("Kotlin_Int_shl_Int")
|
@SymbolName("Kotlin_Int_shl_Int")
|
||||||
external public infix fun shl(bitCount: Int): Int
|
external public infix fun shl(bitCount: Int): Int
|
||||||
@@ -593,6 +600,23 @@ public final class Int : Number(), Comparable<Int> {
|
|||||||
@SymbolName("Kotlin_Int_inv")
|
@SymbolName("Kotlin_Int_inv")
|
||||||
external public fun inv(): Int
|
external public fun inv(): Int
|
||||||
|
|
||||||
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
|
public operator fun rangeTo(other: Byte): IntRange {
|
||||||
|
return IntRange(this, other.toInt())
|
||||||
|
}
|
||||||
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
|
public operator fun rangeTo(other: Short): IntRange {
|
||||||
|
return IntRange(this, other.toInt())
|
||||||
|
}
|
||||||
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
|
public operator fun rangeTo(other: Int): IntRange {
|
||||||
|
return IntRange(this, other.toInt())
|
||||||
|
}
|
||||||
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
|
public operator fun rangeTo(other: Long): LongRange {
|
||||||
|
return LongRange(this.toLong(), other.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
@SymbolName("Kotlin_Int_toByte")
|
@SymbolName("Kotlin_Int_toByte")
|
||||||
external public override fun toByte(): Byte
|
external public override fun toByte(): Byte
|
||||||
@SymbolName("Kotlin_Int_toChar")
|
@SymbolName("Kotlin_Int_toChar")
|
||||||
@@ -782,13 +806,21 @@ public final class Long : Number(), Comparable<Long> {
|
|||||||
external public operator fun unaryMinus(): Long
|
external public operator fun unaryMinus(): Long
|
||||||
|
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Byte): LongRange
|
external public operator fun rangeTo(other: Byte): LongRange {
|
||||||
|
return LongRange(this, other.toLong())
|
||||||
|
}
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Short): LongRange
|
public operator fun rangeTo(other: Short): LongRange {
|
||||||
|
return LongRange(this, other.toLong())
|
||||||
|
}
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Int): LongRange
|
public operator fun rangeTo(other: Int): LongRange {
|
||||||
|
return LongRange(this, other.toLong())
|
||||||
|
}
|
||||||
/** Creates a range from this value to the specified [other] value. */
|
/** Creates a range from this value to the specified [other] value. */
|
||||||
// external public operator fun rangeTo(other: Long): LongRange
|
public operator fun rangeTo(other: Long): LongRange {
|
||||||
|
return LongRange(this, other.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
/** Shifts this value left by [bits]. */
|
/** Shifts this value left by [bits]. */
|
||||||
@SymbolName("Kotlin_Long_shl_Long")
|
@SymbolName("Kotlin_Long_shl_Long")
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package kotlin.internal
|
||||||
|
|
||||||
|
// a mod b (in arithmetical sense)
|
||||||
|
private fun mod(a: Int, b: Int): Int {
|
||||||
|
val mod = a % b
|
||||||
|
return if (mod >= 0) mod else mod + b
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mod(a: Long, b: Long): Long {
|
||||||
|
val mod = a % b
|
||||||
|
return if (mod >= 0) mod else mod + b
|
||||||
|
}
|
||||||
|
|
||||||
|
// (a - b) mod c
|
||||||
|
private fun differenceModulo(a: Int, b: Int, c: Int): Int {
|
||||||
|
return mod(mod(a, c) - mod(b, c), c)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun differenceModulo(a: Long, b: Long, c: Long): Long {
|
||||||
|
return mod(mod(a, c) - mod(b, c), c)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range
|
||||||
|
* from [start] to [end] in case of a positive [step], or from [end] to [start] in case of a negative
|
||||||
|
* [step].
|
||||||
|
*
|
||||||
|
* No validation on passed parameters is performed. The given parameters should satisfy the condition: either
|
||||||
|
* `step > 0` and `start >= end`, or `step < 0` and`start >= end`.
|
||||||
|
* @param start first element of the progression
|
||||||
|
* @param end ending bound for the progression
|
||||||
|
* @param step increment, or difference of successive elements in the progression
|
||||||
|
* @return the final element of the progression
|
||||||
|
* @suppress
|
||||||
|
*/
|
||||||
|
internal fun getProgressionLastElement(start: Int, end: Int, step: Int): Int {
|
||||||
|
if (step > 0) {
|
||||||
|
return end - differenceModulo(end, start, step)
|
||||||
|
}
|
||||||
|
else if (step < 0) {
|
||||||
|
return end + differenceModulo(start, end, -step)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw kotlin.IllegalArgumentException("Step is zero.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the final element of a bounded arithmetic progression, i.e. the last element of the progression which is in the range
|
||||||
|
* from [start] to [end] in case of a positive [step], or from [end] to [start] in case of a negative
|
||||||
|
* [step].
|
||||||
|
*
|
||||||
|
* No validation on passed parameters is performed. The given parameters should satisfy the condition: either
|
||||||
|
* `step > 0` and `start >= end`, or `step < 0` and`start >= end`.
|
||||||
|
* @param start first element of the progression
|
||||||
|
* @param end ending bound for the progression
|
||||||
|
* @param step increment, or difference of successive elements in the progression
|
||||||
|
* @return the final element of the progression
|
||||||
|
* @suppress
|
||||||
|
*/
|
||||||
|
internal fun getProgressionLastElement(start: Long, end: Long, step: Long): Long {
|
||||||
|
if (step > 0) {
|
||||||
|
return end - differenceModulo(end, start, step)
|
||||||
|
}
|
||||||
|
else if (step < 0) {
|
||||||
|
return end + differenceModulo(start, end, -step)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw kotlin.IllegalArgumentException("Step is zero.")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package kotlin.ranges
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iterator over a progression of values of type `Char`.
|
||||||
|
* @property step the number by which the value is incremented on each step.
|
||||||
|
*/
|
||||||
|
internal class CharProgressionIterator(first: Char, last: Char, val step: Int) : CharIterator() {
|
||||||
|
private var next = first.toInt()
|
||||||
|
private val finalElement = last.toInt()
|
||||||
|
private var hasNext: Boolean = if (step > 0) first <= last else first >= last
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean = hasNext
|
||||||
|
|
||||||
|
override fun nextChar(): Char {
|
||||||
|
val value = next
|
||||||
|
if (value == finalElement) {
|
||||||
|
hasNext = false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next += step
|
||||||
|
}
|
||||||
|
return value.toChar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iterator over a progression of values of type `Int`.
|
||||||
|
* @property step the number by which the value is incremented on each step.
|
||||||
|
*/
|
||||||
|
internal class IntProgressionIterator(first: Int, last: Int, val step: Int) : IntIterator() {
|
||||||
|
private var next = first
|
||||||
|
private val finalElement = last
|
||||||
|
private var hasNext: Boolean = if (step > 0) first <= last else first >= last
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean = hasNext
|
||||||
|
|
||||||
|
override fun nextInt(): Int {
|
||||||
|
val value = next
|
||||||
|
if (value == finalElement) {
|
||||||
|
hasNext = false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next += step
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iterator over a progression of values of type `Long`.
|
||||||
|
* @property step the number by which the value is incremented on each step.
|
||||||
|
*/
|
||||||
|
internal class LongProgressionIterator(first: Long, last: Long, val step: Long) : LongIterator() {
|
||||||
|
private var next = first
|
||||||
|
private val finalElement = last
|
||||||
|
private var hasNext: Boolean = if (step > 0) first <= last else first >= last
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean = hasNext
|
||||||
|
|
||||||
|
override fun nextLong(): Long {
|
||||||
|
val value = next
|
||||||
|
if (value == finalElement) {
|
||||||
|
hasNext = false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next += step
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
package kotlin.ranges
|
||||||
|
|
||||||
|
import kotlin.internal.getProgressionLastElement
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A progression of values of type `Char`.
|
||||||
|
*/
|
||||||
|
public open class CharProgression
|
||||||
|
internal constructor
|
||||||
|
(
|
||||||
|
start: Char,
|
||||||
|
endInclusive: Char,
|
||||||
|
step: Int
|
||||||
|
) : Iterable<Char> {
|
||||||
|
init {
|
||||||
|
if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first element in the progression.
|
||||||
|
*/
|
||||||
|
public val first: Char = start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last element in the progression.
|
||||||
|
*/
|
||||||
|
public val last: Char = getProgressionLastElement(start.toInt(), endInclusive.toInt(), step).toChar()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The step of the progression.
|
||||||
|
*/
|
||||||
|
public val step: Int = step
|
||||||
|
|
||||||
|
override fun iterator(): CharIterator = CharProgressionIterator(first, last, step)
|
||||||
|
|
||||||
|
/** Checks if the progression is empty. */
|
||||||
|
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
other is CharProgression && (isEmpty() && other.isEmpty() ||
|
||||||
|
first == other.first && last == other.last && step == other.step)
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
if (isEmpty()) -1 else (31 * (31 * first.toInt() + last.toInt()) + step)
|
||||||
|
|
||||||
|
override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates CharProgression within the specified bounds of a closed range.
|
||||||
|
|
||||||
|
* The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step].
|
||||||
|
* In order to go backwards the [step] must be negative.
|
||||||
|
*/
|
||||||
|
public fun fromClosedRange(rangeStart: Char, rangeEnd: Char, step: Int): CharProgression = CharProgression(rangeStart, rangeEnd, step)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A progression of values of type `Int`.
|
||||||
|
*/
|
||||||
|
public open class IntProgression
|
||||||
|
internal constructor
|
||||||
|
(
|
||||||
|
start: Int,
|
||||||
|
endInclusive: Int,
|
||||||
|
step: Int
|
||||||
|
) : Iterable<Int> {
|
||||||
|
init {
|
||||||
|
if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first element in the progression.
|
||||||
|
*/
|
||||||
|
public val first: Int = start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last element in the progression.
|
||||||
|
*/
|
||||||
|
public val last: Int = getProgressionLastElement(start.toInt(), endInclusive.toInt(), step).toInt()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The step of the progression.
|
||||||
|
*/
|
||||||
|
public val step: Int = step
|
||||||
|
|
||||||
|
override fun iterator(): IntIterator = IntProgressionIterator(first, last, step)
|
||||||
|
|
||||||
|
/** Checks if the progression is empty. */
|
||||||
|
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
other is IntProgression && (isEmpty() && other.isEmpty() ||
|
||||||
|
first == other.first && last == other.last && step == other.step)
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
if (isEmpty()) -1 else (31 * (31 * first + last) + step)
|
||||||
|
|
||||||
|
override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates IntProgression within the specified bounds of a closed range.
|
||||||
|
|
||||||
|
* The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step].
|
||||||
|
* In order to go backwards the [step] must be negative.
|
||||||
|
*/
|
||||||
|
public fun fromClosedRange(rangeStart: Int, rangeEnd: Int, step: Int): IntProgression = IntProgression(rangeStart, rangeEnd, step)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A progression of values of type `Long`.
|
||||||
|
*/
|
||||||
|
public open class LongProgression
|
||||||
|
internal constructor
|
||||||
|
(
|
||||||
|
start: Long,
|
||||||
|
endInclusive: Long,
|
||||||
|
step: Long
|
||||||
|
) : Iterable<Long> {
|
||||||
|
init {
|
||||||
|
if (step == 0L) throw kotlin.IllegalArgumentException("Step must be non-zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first element in the progression.
|
||||||
|
*/
|
||||||
|
public val first: Long = start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last element in the progression.
|
||||||
|
*/
|
||||||
|
public val last: Long = getProgressionLastElement(start.toLong(), endInclusive.toLong(), step).toLong()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The step of the progression.
|
||||||
|
*/
|
||||||
|
public val step: Long = step
|
||||||
|
|
||||||
|
override fun iterator(): LongIterator = LongProgressionIterator(first, last, step)
|
||||||
|
|
||||||
|
/** Checks if the progression is empty. */
|
||||||
|
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
other is LongProgression && (isEmpty() && other.isEmpty() ||
|
||||||
|
first == other.first && last == other.last && step == other.step)
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
if (isEmpty()) -1 else (31 * (31 * (first xor (first ushr 32)) + (last xor (last ushr 32))) + (step xor (step ushr 32))).toInt()
|
||||||
|
|
||||||
|
override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates LongProgression within the specified bounds of a closed range.
|
||||||
|
|
||||||
|
* The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step].
|
||||||
|
* In order to go backwards the [step] must be negative.
|
||||||
|
*/
|
||||||
|
public fun fromClosedRange(rangeStart: Long, rangeEnd: Long, step: Long): LongProgression = LongProgression(rangeStart, rangeEnd, step)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package kotlin.ranges
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a range of values (for example, numbers or characters).
|
||||||
|
* See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/ranges.html) for more information.
|
||||||
|
*/
|
||||||
|
public interface ClosedRange<T: Comparable<T>> {
|
||||||
|
/**
|
||||||
|
* The minimum value in the range.
|
||||||
|
*/
|
||||||
|
public val start: T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum value in the range (inclusive).
|
||||||
|
*/
|
||||||
|
public val endInclusive: T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the specified [value] belongs to the range.
|
||||||
|
*/
|
||||||
|
public operator fun contains(value: T): Boolean = value >= start && value <= endInclusive
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the range is empty.
|
||||||
|
*/
|
||||||
|
public fun isEmpty(): Boolean = start > endInclusive
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package kotlin.ranges
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A range of values of type `Char`.
|
||||||
|
*/
|
||||||
|
public class CharRange(start: Char, endInclusive: Char) : CharProgression(start, endInclusive, 1), ClosedRange<Char> {
|
||||||
|
override val start: Char get() = first
|
||||||
|
override val endInclusive: Char get() = last
|
||||||
|
|
||||||
|
override fun contains(value: Char): Boolean = first <= value && value <= last
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean = first > last
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
other is CharRange && (isEmpty() && other.isEmpty() ||
|
||||||
|
first == other.first && last == other.last)
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
if (isEmpty()) -1 else (31 * first.toInt() + last.toInt())
|
||||||
|
|
||||||
|
override fun toString(): String = "$first..$last"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** An empty range of values of type Char. */
|
||||||
|
public val EMPTY: CharRange = CharRange(1.toChar(), 0.toChar())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A range of values of type `Int`.
|
||||||
|
*/
|
||||||
|
public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, endInclusive, 1), ClosedRange<Int> {
|
||||||
|
override val start: Int get() = first
|
||||||
|
override val endInclusive: Int get() = last
|
||||||
|
|
||||||
|
override fun contains(value: Int): Boolean = first <= value && value <= last
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean = first > last
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
other is IntRange && (isEmpty() && other.isEmpty() ||
|
||||||
|
first == other.first && last == other.last)
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
if (isEmpty()) -1 else (31 * first + last)
|
||||||
|
|
||||||
|
override fun toString(): String = "$first..$last"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** An empty range of values of type Int. */
|
||||||
|
public val EMPTY: IntRange = IntRange(1, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A range of values of type `Long`.
|
||||||
|
*/
|
||||||
|
public class LongRange(start: Long, endInclusive: Long) : LongProgression(start, endInclusive, 1), ClosedRange<Long> {
|
||||||
|
override val start: Long get() = first
|
||||||
|
override val endInclusive: Long get() = last
|
||||||
|
|
||||||
|
override fun contains(value: Long): Boolean = first <= value && value <= last
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean = first > last
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
other is LongRange && (isEmpty() && other.isEmpty() ||
|
||||||
|
first == other.first && last == other.last)
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
if (isEmpty()) -1 else (31 * (first xor (first ushr 32)) + (last xor (last ushr 32))).toInt()
|
||||||
|
|
||||||
|
override fun toString(): String = "$first..$last"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** An empty range of values of type Long. */
|
||||||
|
public val EMPTY: LongRange = LongRange(1, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user