From 08bdcc963f1276dd2a1a4826aa848231cb1c71c2 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Wed, 14 Dec 2016 16:46:39 +0300 Subject: [PATCH] Use lambdas in stdlib. (#140) --- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 6 +- runtime/src/main/cpp/Natives.cpp | 4 +- runtime/src/main/cpp/Operator.cpp | 3 + runtime/src/main/kotlin/konan/Annotations.kt | 22 ++ runtime/src/main/kotlin/kotlin/Array.kt | 1 + runtime/src/main/kotlin/kotlin/Arrays.kt | 174 ++++++++++ runtime/src/main/kotlin/kotlin/Exceptions.kt | 9 - .../kotlin/collections/AbstractCollection.kt | 3 +- .../kotlin/kotlin/collections/AbstractList.kt | 135 ++++++++ .../kotlin/kotlin/collections/ArrayUtil.kt | 8 +- .../kotlin/kotlin/collections/Collections.kt | 216 ++++++++++++- .../main/kotlin/kotlin/collections/HashSet.kt | 3 +- .../main/kotlin/kotlin/collections/Maps.kt | 182 ++++++++++- .../kotlin/collections/MutableCollections.kt | 303 ++++++++++++++++++ .../main/kotlin/kotlin/collections/Sets.kt | 4 +- .../kotlin/kotlin/internal/Annotations.kt | 48 ++- .../src/main/kotlin/kotlin/ranges/Ranges.kt | 9 + .../src/main/kotlin/kotlin/util/Standard.kt | 64 ++++ 18 files changed, 1145 insertions(+), 49 deletions(-) create mode 100644 runtime/src/main/kotlin/kotlin/collections/AbstractList.kt create mode 100644 runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt create mode 100644 runtime/src/main/kotlin/kotlin/util/Standard.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 4bdfd50528c..14e8c21e2d7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -51,12 +51,14 @@ internal fun emitLLVM(context: Context) { LLVMWriteBitcodeToFile(llvmModule, outFile) } -internal fun verifyModule(llvmModule: LLVMModuleRef) { +internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") { memScoped { val errorRef = allocPointerTo() // TODO: use LLVMDisposeMessage() on errorRef, once possible in interop. if (LLVMVerifyModule( llvmModule, LLVMVerifierFailureAction.LLVMPrintMessageAction, errorRef.ptr) == 1) { + if (current.length > 0) + println("Error in ${current}") LLVMDumpModule(llvmModule) throw Error("Invalid module"); } @@ -516,7 +518,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid codegen.epilogue(declaration) - verifyModule(context.llvmModule!!) + verifyModule(context.llvmModule!!, ir2string(declaration)) } //-------------------------------------------------------------------------// diff --git a/runtime/src/main/cpp/Natives.cpp b/runtime/src/main/cpp/Natives.cpp index 9604b0f111d..1caa8280c40 100644 --- a/runtime/src/main/cpp/Natives.cpp +++ b/runtime/src/main/cpp/Natives.cpp @@ -149,7 +149,9 @@ KString Kotlin_String_plusImpl(KString thiz, KString other) { } KBoolean Kotlin_String_equals(KString thiz, KConstRef other) { - if (other == nullptr || other->type_info() != theStringTypeInfo) return 0; + if (other == nullptr || other->type_info() != theStringTypeInfo) return false; + // Important, due to literal internalization. + if (thiz == other) return true; KString otherString = reinterpret_cast(other); return thiz->count_ == otherString->count_ && memcmp(ByteArrayAddressOfElementAt(thiz, 0), diff --git a/runtime/src/main/cpp/Operator.cpp b/runtime/src/main/cpp/Operator.cpp index 4af2ac65b82..2c92a7f676e 100644 --- a/runtime/src/main/cpp/Operator.cpp +++ b/runtime/src/main/cpp/Operator.cpp @@ -191,6 +191,7 @@ KInt Kotlin_Int_dec (KInt a ) { return --a; } KInt Kotlin_Int_unaryPlus (KInt a ) { return +a; } KInt Kotlin_Int_unaryMinus (KInt a ) { return -a; } +KInt Kotlin_Int_or_Int (KInt a, KInt b) { return a | b; } KInt Kotlin_Int_xor_Int (KInt a, KInt b) { return a ^ b; } KInt Kotlin_Int_and_Int (KInt a, KInt b) { return a & b; } KInt Kotlin_Int_shl_Int (KInt a, KInt b) { return a << b; } @@ -257,6 +258,8 @@ KLong Kotlin_Long_unaryPlus (KLong a ) { return +a; } KLong Kotlin_Long_unaryMinus (KLong a ) { return -a; } KLong Kotlin_Long_xor_Long (KLong a, KLong b) { return a ^ b; } +KLong Kotlin_Long_or_Long (KLong a, KLong b) { return a | b; } +KLong Kotlin_Long_and_Long (KLong a, KLong b) { return a & b; } KLong Kotlin_Long_shr_Int (KLong a, KInt b) { return a >> b; } diff --git a/runtime/src/main/kotlin/konan/Annotations.kt b/runtime/src/main/kotlin/konan/Annotations.kt index d322e5d4fe9..4ff0173ecb6 100644 --- a/runtime/src/main/kotlin/konan/Annotations.kt +++ b/runtime/src/main/kotlin/konan/Annotations.kt @@ -23,3 +23,25 @@ annotation class ExportTypeInfo(val name: String) */ public annotation class Used + +// Following annotations can be used to mark functions that need to be fixed, +// once certain language feature is implemented. +/** + * Need to be fixed because of boxing. + */ +public annotation class FixmeBoxing + +/** + * Need to be fixed because of inner classes. + */ +public annotation class FixmeInner + +/** + * Need to be fixed because of lambdas. + */ +public annotation class FixmeLambda + +/** + * Need to be fixed. + */ +public annotation class Fixme diff --git a/runtime/src/main/kotlin/kotlin/Array.kt b/runtime/src/main/kotlin/kotlin/Array.kt index 3738678f69e..0e85653c63e 100644 --- a/runtime/src/main/kotlin/kotlin/Array.kt +++ b/runtime/src/main/kotlin/kotlin/Array.kt @@ -47,6 +47,7 @@ public fun > Array.toCollection(destinatio return destination } +@kotlin.internal.InlineOnly public inline operator fun Array.plus(elements: Array): Array { val result = copyOfUninitializedElements(this.size + elements.size) elements.copyRangeTo(result, 0, elements.size, this.size) diff --git a/runtime/src/main/kotlin/kotlin/Arrays.kt b/runtime/src/main/kotlin/kotlin/Arrays.kt index 9b38edbffc9..5134c411f75 100644 --- a/runtime/src/main/kotlin/kotlin/Arrays.kt +++ b/runtime/src/main/kotlin/kotlin/Arrays.kt @@ -333,3 +333,177 @@ private class BooleanIteratorImpl(val collection: BooleanArray) : BooleanIterato return index < collection.size } } + +// This part is from generated _Arrays.kt. + +/** + * Returns `true` if array has at least one element. + */ +public fun Array.any(): Boolean { + for (element in this) return true + return false +} + +/** + * Returns `true` if at least one element matches the given [predicate]. + */ +public inline fun Array.any(predicate: (T) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} + +/** + * Returns `true` if all elements match the given [predicate]. + */ +public inline fun Array.all(predicate: (T) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} + +/** + * Returns `true` if [element] is found in the array. + */ +public operator fun <@kotlin.internal.OnlyInputTypes T> Array.contains(element: T): Boolean { + return indexOf(element) >= 0 +} + +/** + * Returns first index of [element], or -1 if the array does not contain element. + */ +public fun <@kotlin.internal.OnlyInputTypes T> Array.indexOf(element: T): Int { + if (element == null) { + for (index in indices) { + if (this[index] == null) { + return index + } + } + } else { + for (index in indices) { + if (element == this[index]) { + return index + } + } + } + return -1 +} + +/** + * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. + */ +public inline fun Array.indexOfFirst(predicate: (T) -> Boolean): Int { + for (index in indices) { + if (predicate(this[index])) { + return index + } + } + return -1 +} + +/** + * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. + */ +public inline fun Array.indexOfLast(predicate: (T) -> Boolean): Int { + for (index in indices.reversed()) { + if (predicate(this[index])) { + return index + } + } + return -1 +} + +/** + * Returns a list containing all elements not matching the given [predicate]. + */ +public inline fun Array.filterNot(predicate: (T) -> Boolean): List { + return filterNotTo(ArrayList(), predicate) +} + +/** + * Appends all elements not matching the given [predicate] to the given [destination]. + */ +public inline fun > Array.filterNotTo(destination: C, predicate: (T) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} + +/** + * Returns a list containing all elements that are not `null`. + */ +public fun Array.filterNotNull(): List { + return filterNotNullTo(ArrayList()) +} + +/** + * Appends all elements that are not `null` to the given [destination]. + */ +public fun , T : Any> Array.filterNotNullTo(destination: C): C { + for (element in this) if (element != null) destination.add(element) + return destination +} + +/** + * Returns the first element matching the given [predicate], or `null` if no such element was found. + */ +public inline fun Array.find(predicate: (T) -> Boolean): T? { + return firstOrNull(predicate) +} + +/** + * Returns the last element matching the given [predicate], or `null` if no such element was found. + */ +public inline fun Array.findLast(predicate: (T) -> Boolean): T? { + return lastOrNull(predicate) +} + +/** + * Returns the first element, or `null` if the array is empty. + */ +public fun Array.firstOrNull(): T? { + return if (isEmpty()) null else this[0] +} + +/** + * Returns the first element matching the given [predicate], or `null` if element was not found. + */ +public inline fun Array.firstOrNull(predicate: (T) -> Boolean): T? { + for (element in this) if (predicate(element)) return element + return null +} + +/** + * Returns the last element, or `null` if the array is empty. + */ +public fun Array.lastOrNull(): T? { + return if (isEmpty()) null else this[size - 1] +} + +/** + * Returns the last element matching the given [predicate], or `null` if no such element was found. + */ +public inline fun Array.lastOrNull(predicate: (T) -> Boolean): T? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} + +/** + * Returns `true` if the array is empty. + */ +@kotlin.internal.InlineOnly +public inline fun Array.isEmpty(): Boolean { + return size == 0 +} + +/** + * Returns the range of valid indices for the array. + */ +public val Array.indices: IntRange + get() = IntRange(0, lastIndex) + +/** + * Returns the last valid index for the array. + */ +public val Array.lastIndex: Int + get() = size - 1 diff --git a/runtime/src/main/kotlin/kotlin/Exceptions.kt b/runtime/src/main/kotlin/kotlin/Exceptions.kt index 03a4ebd3ea1..0effb03329d 100644 --- a/runtime/src/main/kotlin/kotlin/Exceptions.kt +++ b/runtime/src/main/kotlin/kotlin/Exceptions.kt @@ -136,13 +136,4 @@ public class AssertionError : Error { constructor(message: String, cause: Throwable) : super(message, cause) { } -} - -// TODO: does it belong here? -fun TODO() { - throw UnsupportedOperationException() -} - -fun TODO(message: String) { - throw UnsupportedOperationException(message) } \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/collections/AbstractCollection.kt b/runtime/src/main/kotlin/kotlin/collections/AbstractCollection.kt index 1d9b66e466d..cb464dfde1f 100644 --- a/runtime/src/main/kotlin/kotlin/collections/AbstractCollection.kt +++ b/runtime/src/main/kotlin/kotlin/collections/AbstractCollection.kt @@ -4,7 +4,6 @@ public abstract class AbstractCollection protected constructor() : Collec abstract override val size: Int abstract override fun iterator(): Iterator - /* TODO: uncomment, once can support lambdas. override fun contains(element: @UnsafeVariance E): Boolean = any { it == element } override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean = @@ -12,8 +11,8 @@ public abstract class AbstractCollection protected constructor() : Collec override fun isEmpty(): Boolean = size == 0 + /* override fun toString(): String = joinToString(", ", "[", "]") { if (it === this) "(this Collection)" else it.toString() } */ - } diff --git a/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt b/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt new file mode 100644 index 00000000000..a841f7b174d --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt @@ -0,0 +1,135 @@ +/* + * Based on GWT AbstractList + * Copyright 2007 Google Inc. +*/ +package kotlin.collections + +public abstract class AbstractList protected constructor() : AbstractCollection(), List { + abstract override val size: Int + abstract override fun get(index: Int): E + + // TODO: fix once have inner classes. + @FixmeInner + override fun iterator(): Iterator = TODO() // IteratorImpl() + + override fun indexOf(element: @UnsafeVariance E): Int = indexOfFirst { it == element } + + override fun lastIndexOf(element: @UnsafeVariance E): Int = indexOfLast { it == element } + + // TODO: fix once have inner classes. + @FixmeInner + override fun listIterator(): ListIterator = TODO() // ListIteratorImpl(0) + + @FixmeInner + override fun listIterator(index: Int): ListIterator = TODO() // ListIteratorImpl(index) + + override fun subList(fromIndex: Int, toIndex: Int): List = SubList(this, fromIndex, toIndex) + + internal open class SubList( + private val list: AbstractList, private val fromIndex: Int, toIndex: Int) : AbstractList() { + private var _size: Int = 0 + + init { + checkRangeIndexes(fromIndex, toIndex, list.size) + this._size = toIndex - fromIndex + } + + override fun get(index: Int): E { + checkElementIndex(index, _size) + + return list[fromIndex + index] + } + + override val size: Int get() = _size + } + + override fun equals(other: Any?): Boolean { + if (other === this) return true + if (other !is List<*>) return false + + return orderedEquals(this, other) + } + + override fun hashCode(): Int = orderedHashCode(this) + + // TODO: enable, once have inner classes. +/* + private open inner class IteratorImpl : Iterator { + /** the index of the item that will be returned on the next call to [next]`()` */ + protected var index = 0 + + override fun hasNext(): Boolean = index < size + + override fun next(): E { + if (!hasNext()) throw NoSuchElementException() + return get(index++) + } + } + + /** + * Implementation of `MutableListIterator` for abstract lists. + */ + private open inner class ListIteratorImpl(index: Int) : IteratorImpl(), ListIterator { + + init { + checkPositionIndex(index, this@AbstractList.size) + this.index = index + } + + override fun hasPrevious(): Boolean = index > 0 + + override fun nextIndex(): Int = index + + override fun previous(): E { + if (!hasPrevious()) throw NoSuchElementException() + return get(--index) + } + + override fun previousIndex(): Int = index - 1 + } */ + + internal companion object { + internal fun checkElementIndex(index: Int, size: Int) { + if (index < 0 || index >= size) { + throw IndexOutOfBoundsException("index: $index, size: $size") + } + } + + internal fun checkPositionIndex(index: Int, size: Int) { + if (index < 0 || index > size) { + throw IndexOutOfBoundsException("index: $index, size: $size") + } + } + + internal fun checkRangeIndexes(start: Int, end: Int, size: Int) { + if (start < 0 || end > size) { + throw IndexOutOfBoundsException("fromIndex: $start, toIndex: $end, size: $size") + } + if (start > end) { + throw IllegalArgumentException("fromIndex: $start > toIndex: $end") + } + } + + internal fun orderedHashCode(c: Collection<*>): Int { + var hashCode = 1 + for (e in c) { + hashCode = 31 * hashCode + (if (e != null) e.hashCode() else 0) + hashCode = hashCode or 0 // make sure we don't overflow + } + return hashCode + } + + internal fun orderedEquals(c: Collection<*>, other: Collection<*>): Boolean { + if (c.size != other.size) return false + + val otherIterator = other.iterator() + for (elem in c) { + val elemOther = otherIterator.next() + if (elem != elemOther) { + return false + } + } + return true + } + } +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/collections/ArrayUtil.kt b/runtime/src/main/kotlin/kotlin/collections/ArrayUtil.kt index 6a0e8f25076..4ce36677c97 100644 --- a/runtime/src/main/kotlin/kotlin/collections/ArrayUtil.kt +++ b/runtime/src/main/kotlin/kotlin/collections/ArrayUtil.kt @@ -34,7 +34,7 @@ fun IntArray.copyOfUninitializedElements(newSize: Int): IntArray { * either throwing exception or returning some kind of implementation-specific default value. */ fun Array.resetAt(index: Int) { - (this as Array)[index] = null + (@Suppress("UNCHECKED_CAST")(this as Array))[index] = null } @SymbolName("Kotlin_Array_fillImpl") @@ -51,7 +51,7 @@ external private fun fillImpl(array: IntArray, fromIndex: Int, toIndex: Int, val * either throwing exception or returning some kind of implementation-specific default value. */ fun Array.resetRange(fromIndex: Int, toIndex: Int) { - fillImpl(this as Array, fromIndex, toIndex, null) + fillImpl(@Suppress("UNCHECKED_CAST") (this as Array), fromIndex, toIndex, null) } fun IntArray.fill(fromIndex: Int, toIndex: Int, value: Int) { @@ -71,7 +71,9 @@ external private fun copyImpl(array: IntArray, fromIndex: Int, * to another [destination] array starting at [destinationIndex]. */ fun Array.copyRangeTo(destination: Array, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) { - copyImpl(this as Array, fromIndex, destination as Array, destinationIndex, toIndex - fromIndex) + copyImpl(@Suppress("UNCHECKED_CAST") (this as Array), fromIndex, + @Suppress("UNCHECKED_CAST") (destination as Array), + destinationIndex, toIndex - fromIndex) } fun IntArray.copyRangeTo(destination: IntArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) { diff --git a/runtime/src/main/kotlin/kotlin/collections/Collections.kt b/runtime/src/main/kotlin/kotlin/collections/Collections.kt index caa2209a281..783add20e8c 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Collections.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Collections.kt @@ -39,6 +39,90 @@ internal object EmptyList : List/*, RandomAccess */ { private fun readResolve(): Any = EmptyList } +internal fun Array.asCollection(): Collection = ArrayAsCollection(this, isVarargs = false) + +private class ArrayAsCollection(val values: Array, val isVarargs: Boolean): Collection { + override val size: Int get() = values.size + override fun isEmpty(): Boolean = values.isEmpty() + override fun contains(element: T): Boolean = values.contains(element) + override fun containsAll(elements: Collection): Boolean = elements.all { contains(it) } + override fun iterator(): Iterator = values.iterator() + // override hidden toArray implementation to prevent copying of values array + public fun toArray(): Array = values.copyToArrayOfAny(isVarargs) +} + +/** Returns an empty read-only list. */ +public fun emptyList(): List = EmptyList + +/** Returns a new read-only list of given elements. */ +public fun listOf(vararg elements: T): List = if (elements.size > 0) elements.asList() else emptyList() + +/** Returns an empty read-only list. */ +@kotlin.internal.InlineOnly +public inline fun listOf(): List = emptyList() + +/** Returns a new [MutableList] with the given elements. */ +public fun mutableListOf(vararg elements: T): MutableList + = if (elements.size == 0) ArrayList() else ArrayList(ArrayAsCollection(elements, isVarargs = true)) + +// This part is from generated _Collections.kt. + +/** Returns a new [ArrayList] with the given elements. */ +public fun arrayListOf(vararg elements: T): ArrayList + = if (elements.size == 0) ArrayList() else ArrayList(ArrayAsCollection(elements, isVarargs = true)) + +/** Returns a new read-only list either of single given element, if it is not null, + * or empty list it the element is null.*/ +public fun listOfNotNull(element: T?): List = + if (element != null) listOf(element) else emptyList() + +/** Returns a new read-only list only of those given elements, that are not null. */ +public fun listOfNotNull(vararg elements: T?): List = elements.filterNotNull() + +/** + * Returns an [IntRange] of the valid indices for this collection. + */ +public val Collection<*>.indices: IntRange + get() = 0..size - 1 + +/** + * Returns the index of the last item in the list or -1 if the list is empty. + * + * @sample samples.collections.Collections.Lists.lastIndexOfList + */ +public val List.lastIndex: Int + get() = this.size - 1 + +/** Returns `true` if the collection is not empty. */ +@kotlin.internal.InlineOnly +public inline fun Collection.isNotEmpty(): Boolean = !isEmpty() + +/** Returns this Collection if it's not `null` and the empty list otherwise. */ +@kotlin.internal.InlineOnly +public inline fun Collection?.orEmpty(): Collection = this ?: emptyList() + +@kotlin.internal.InlineOnly +public inline fun List?.orEmpty(): List = this ?: emptyList() + +/** + * Checks if all elements in the specified collection are contained in this collection. + * + * Allows to overcome type-safety restriction of `containsAll` that requires to pass a collection of type `Collection`. + */ +@kotlin.internal.InlineOnly +public inline fun <@kotlin.internal.OnlyInputTypes T> Collection.containsAll( + elements: Collection): Boolean = this.containsAll(elements) + +// copies typed varargs array to array of objects +// TODO: generally wrong, wrt specialization. +@Fixme +private fun Array.copyToArrayOfAny(isVarargs: Boolean): Array = + if (isVarargs) + // if the array came from varargs and already is array of Any, copying isn't required. + @Suppress("UNCHECKED_CAST") (this as Array) + else + @Suppress("UNCHECKED_CAST") (this.copyOfUninitializedElements(this.size) as Array) + /** * Classes that inherit from this interface can be represented as a sequence of elements that can @@ -63,6 +147,61 @@ public interface MutableIterable : Iterable { override fun iterator(): MutableIterator } +/** + * Returns `true` if all elements match the given [predicate]. + */ +public inline fun Iterable.all(predicate: (T) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} + +/** + * Returns `true` if collection has at least one element. + */ +public fun Iterable.any(): Boolean { + for (element in this) return true + return false +} + +/** + * Returns `true` if at least one element matches the given [predicate]. + */ +public inline fun Iterable.any(predicate: (T) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} + +/** + * Returns a list containing all elements not matching the given [predicate]. + */ +public inline fun Iterable.filterNot(predicate: (T) -> Boolean): List { + return filterNotTo(ArrayList(), predicate) +} + +/** + * Returns a list containing all elements that are not `null`. + */ +public fun Iterable.filterNotNull(): List { + return filterNotNullTo(ArrayList()) +} + +/** + * Appends all elements that are not `null` to the given [destination]. + */ +public fun , T : Any> Iterable.filterNotNullTo(destination: C): C { + for (element in this) if (element != null) destination.add(element) + return destination +} + +/** + * Appends all elements not matching the given [predicate] to the given [destination]. + */ +public inline fun > Iterable.filterNotTo(destination: C, predicate: (T) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.add(element) + return destination +} + + fun Array.asList(): List { // TODO: consider making lighter list over an array. val result = ArrayList(this.size) @@ -71,6 +210,17 @@ fun Array.asList(): List { } return result } +/* TODO: use this one! +public fun Array.asList(): List { + return object : AbstractList() { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: T): Boolean = this@asList.contains(element) + override fun get(index: Int): T = this@asList[index] + override fun indexOf(element: T): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: T): Int = this@asList.lastIndexOf(element) + } +} */ fun Array.toSet(): Set { val result = HashSet(this.size) @@ -80,21 +230,63 @@ fun Array.toSet(): Set { return result } -public fun arrayListOf(vararg args: T): MutableList { - val result = ArrayList(args.size) - for (arg in args) { - result.add(arg) - } - return result -} - -public fun listOf(): List = EmptyList - -public fun listOf(vararg args: T): List = args.asList() - public fun > Iterable.toCollection(destination: C): C { for (item in this) { destination.add(item) } return destination } + +// From generated _Collections.kt. +/** + * Returns index of the first element matching the given [predicate], or -1 if the collection does not contain such element. + */ +public inline fun Iterable.indexOfFirst(predicate: (T) -> Boolean): Int { + var index = 0 + for (item in this) { + if (predicate(item)) + return index + index++ + } + return -1 +} + +/** + * Returns index of the first element matching the given [predicate], or -1 if the list does not contain such element. + */ +public inline fun List.indexOfFirst(predicate: (T) -> Boolean): Int { + var index = 0 + for (item in this) { + if (predicate(item)) + return index + index++ + } + return -1 +} + +/** + * Returns index of the last element matching the given [predicate], or -1 if the collection does not contain such element. + */ +public inline fun Iterable.indexOfLast(predicate: (T) -> Boolean): Int { + var lastIndex = -1 + var index = 0 + for (item in this) { + if (predicate(item)) + lastIndex = index + index++ + } + return lastIndex +} + +/** + * Returns index of the last element matching the given [predicate], or -1 if the list does not contain such element. + */ +public inline fun List.indexOfLast(predicate: (T) -> Boolean): Int { + val iterator = this.listIterator(size) + while (iterator.hasPrevious()) { + if (predicate(iterator.previous())) { + return iterator.nextIndex() + } + } + return -1 +} diff --git a/runtime/src/main/kotlin/kotlin/collections/HashSet.kt b/runtime/src/main/kotlin/kotlin/collections/HashSet.kt index da6b9f98e05..90b326ae970 100644 --- a/runtime/src/main/kotlin/kotlin/collections/HashSet.kt +++ b/runtime/src/main/kotlin/kotlin/collections/HashSet.kt @@ -64,7 +64,8 @@ class HashSet internal constructor( override fun equals(other: Any?): Boolean { return other === this || (other is Set<*>) && - contentEquals(other as Set) + contentEquals( + @Suppress("UNCHECKED_CAST") (other as Set)) } override fun hashCode(): Int { diff --git a/runtime/src/main/kotlin/kotlin/collections/Maps.kt b/runtime/src/main/kotlin/kotlin/collections/Maps.kt index 5328094a645..53a521efb7a 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Maps.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Maps.kt @@ -22,7 +22,7 @@ private object EmptyMap : Map { * Returns an empty read-only map of specified type. The returned map is serializable (JVM). * @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap */ -public fun emptyMap(): Map = @Suppress("UNCHECKED_CAST") (EmptyMap as Map) +public fun emptyMap(): Map = EmptyMap as Map /** * Returns a new read-only map with the specified contents, given as a list of pairs @@ -34,12 +34,14 @@ public fun emptyMap(): Map = @Suppress("UNCHECKED_CAST") (EmptyMap * * @sample samples.collections.Maps.Instantiation.mapFromPairs */ -public fun mapOf(vararg pairs: Pair): Map = if (pairs.size > 0) hashMapOf(*pairs) else emptyMap() +public fun mapOf(vararg pairs: Pair): Map = + if (pairs.size > 0) hashMapOf(*pairs) else emptyMap() /** * Returns an empty read-only map. The returned map is serializable (JVM). * @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap */ +@kotlin.internal.InlineOnly public inline fun mapOf(): Map = emptyMap() /** @@ -57,6 +59,7 @@ public inline fun mapOf(): Map = emptyMap() * @sample samples.collections.Maps.Instantiation.mutableMapFromPairs * @sample samples.collections.Maps.Instantiation.emptyMutableMap */ +@Fixme public fun mutableMapOf(vararg pairs: Pair): MutableMap = hashMapOf(*pairs) // = HashMap(mapCapacity(pairs.size)).apply { putAll(pairs) } @@ -100,25 +103,30 @@ internal fun mapCapacity(expectedSize: Int): Int { return Int.MAX_VALUE // any large value } +@Fixme private const val INT_MAX_POWER_OF_TWO: Int = 0x40000000 // Int.MAX_VALUE / 2 + 1 /** Returns `true` if this map is not empty. */ +@kotlin.internal.InlineOnly public inline fun Map.isNotEmpty(): Boolean = !isEmpty() /** * Returns the [Map] if its not `null`, or the empty [Map] otherwise. */ +@kotlin.internal.InlineOnly public inline fun Map?.orEmpty() : Map = this ?: emptyMap() /** * Checks if the map contains the given key. This method allows to use the `x in map` syntax for checking * whether an object is contained in the map. */ +@kotlin.internal.InlineOnly public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.contains(key: K) : Boolean = containsKey(key) /** * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map. */ +@kotlin.internal.InlineOnly public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.get(key: K): V? = @Suppress("UNCHECKED_CAST") (this as Map).get(key) @@ -127,6 +135,7 @@ public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map. * * Allows to overcome type-safety restriction of `containsKey` that requires to pass a key of type `K`. */ +@kotlin.internal.InlineOnly public inline fun <@kotlin.internal.OnlyInputTypes K> Map.containsKey(key: K): Boolean = @Suppress("UNCHECKED_CAST") (this as Map).containsKey(key) @@ -135,6 +144,7 @@ public inline fun <@kotlin.internal.OnlyInputTypes K> Map.containsKey( * * Allows to overcome type-safety restriction of `containsValue` that requires to pass a value of type `V`. */ +@kotlin.internal.InlineOnly public inline fun Map.containsValue(value: V): Boolean = this.containsValue(value) @@ -145,6 +155,7 @@ public inline fun Map.containsValue * Allows to overcome type-safety restriction of `remove` that requires to pass a key of type `K`. */ +@kotlin.internal.InlineOnly public inline fun <@kotlin.internal.OnlyInputTypes K, V> MutableMap.remove(key: K): V? = @Suppress("UNCHECKED_CAST") (this as MutableMap).remove(key) @@ -158,6 +169,7 @@ public inline fun <@kotlin.internal.OnlyInputTypes K, V> MutableMap.re * } * ``` */ +@kotlin.internal.InlineOnly public inline operator fun Map.Entry.component1(): K = key /** @@ -169,11 +181,13 @@ public inline operator fun Map.Entry.component1(): K = key * } * ``` */ +@kotlin.internal.InlineOnly public inline operator fun Map.Entry.component2(): V = value /** * Converts entry to [Pair] with key being first component and value being second. */ +@kotlin.internal.InlineOnly public inline fun Map.Entry.toPair(): Pair = Pair(key, value) /** @@ -184,7 +198,10 @@ public inline fun Map.Entry.toPair(): Pair = Pair(key, value) public inline fun Map.getOrElse(key: K, defaultValue: () -> V): V = get(key) ?: defaultValue() -//internal inline fun Map.getOrElseNullable(key: K, defaultValue: () -> V): V { +@Fixme +internal inline fun Map.getOrElseNullable(key: K, defaultValue: () -> V): V { + TODO() +} // val value = get(key) // if (value == null && !containsKey(key)) { // return defaultValue() @@ -217,21 +234,26 @@ public inline fun MutableMap.getOrPut(key: K, defaultValue: () -> V * * @sample samples.collections.Maps.Usage.forOverEntries */ +@kotlin.internal.InlineOnly public inline operator fun Map.iterator(): Iterator> = entries.iterator() /** * Returns a [MutableIterator] over the mutable entries in the [MutableMap]. * */ +@kotlin.internal.InlineOnly public inline operator fun MutableMap.iterator(): MutableIterator> = entries.iterator() /** * Populates the given [destination] map with entries having the keys of this map and the values obtained * by applying the [transform] function to each entry in this [Map]. */ -//public inline fun > Map.mapValuesTo(destination: M, transform: (Map.Entry) -> R): M { +@Fixme +@kotlin.internal.InlineOnly +public inline fun > Map.mapValuesTo(destination: M, transform: (Map.Entry) -> R): M { + TODO() // return entries.associateByTo(destination, { it.key }, transform) -//} +} /** * Populates the given [destination] map with entries having the keys obtained @@ -240,9 +262,11 @@ public inline operator fun MutableMap.iterator(): MutableIterator> Map.mapKeysTo(destination: M, transform: (Map.Entry) -> R): M { +@kotlin.internal.InlineOnly +public inline fun > Map.mapKeysTo(destination: M, transform: (Map.Entry) -> R): M { + TODO() // return entries.associateByTo(destination, transform, { it.value }) -//} +} /** * Puts all the given [pairs] into this [MutableMap] with the first component in the pair being the key and the second the value. @@ -463,21 +487,17 @@ public fun Map.toMutableMap(): MutableMap = HashMap(t /** * Populates and returns the [destination] mutable map with key-value pairs from the given map. */ -public fun > Map.toMap(destination: M): M { - for (key in keys) { - destination.put(key, get(key)!!) - } - return destination -} -// = destination.apply { putAll(this@toMap) } +public fun > Map.toMap(destination: M): M + = destination.apply { putAll(this@toMap) } +// TODO: fix me, once have correct type variance in HashMap. /** * Creates a new read-only map by replacing or adding an entry to this map from a given key-value [pair]. * * The returned map preserves the entry iteration order of the original map. * The [pair] is iterated in the end if it has a unique key. */ -//public operator fun Map.plus(pair: Pair): Map +// public operator fun Map.plus(pair: Pair): Map // = if (this.isEmpty()) mapOf(pair) else HashMap(this).apply { put(pair.first, pair.second) } /** @@ -516,10 +536,10 @@ public fun > Map.toMap(destination: M //public operator fun Map.plus(map: Map): Map // = HashMap(this).apply { putAll(map) } - /** * Appends or replaces the given [pair] in this mutable map. */ +@kotlin.internal.InlineOnly public inline operator fun MutableMap.plusAssign(pair: Pair) { put(pair.first, pair.second) } @@ -527,6 +547,7 @@ public inline operator fun MutableMap.plusAssign(pair: Pair MutableMap.plusAssign(pairs: Iterable>) { putAll(pairs) } @@ -534,6 +555,7 @@ public inline operator fun MutableMap.plusAssign(pairs: Itera /** * Appends or replaces all pairs from the given array of [pairs] in this mutable map. */ +@kotlin.internal.InlineOnly public inline operator fun MutableMap.plusAssign(pairs: Array>) { putAll(pairs) } @@ -541,6 +563,7 @@ public inline operator fun MutableMap.plusAssign(pairs: Array /** * Appends or replaces all pairs from the given sequence of [pairs] in this mutable map. */ +@kotlin.internal.InlineOnly public inline operator fun MutableMap.plusAssign(pairs: Sequence>) { putAll(pairs) } @@ -548,11 +571,11 @@ public inline operator fun MutableMap.plusAssign(pairs: Seque /** * Appends or replaces all entries from the given [map] in this mutable map. */ +@kotlin.internal.InlineOnly public inline operator fun MutableMap.plusAssign(map: Map) { putAll(map) } - // do not expose for now @kotlin.internal.InlineExposed internal fun Map.optimizeReadOnlyMap() = when (size) { 0 -> emptyMap() @@ -566,3 +589,128 @@ internal fun Map.optimizeReadOnlyMap() = when (size) { // creates a singleton copy of map //internal fun Map.toSingletonMap(): Map // = with (entries.iterator().next()) { java.util.Collections.singletonMap(key, value) } + +// This is from generated _Maps.kt. +/** + * Returns a [List] containing all key-value pairs. + */ +public fun Map.toList(): List> { + if (size == 0) + return emptyList() + val iterator = entries.iterator() + if (!iterator.hasNext()) + return emptyList() + val first = iterator.next() + if (!iterator.hasNext()) + return listOf(first.toPair()) + val result = ArrayList>(size) + result.add(first.toPair()) + do { + result.add(iterator.next().toPair()) + } while (iterator.hasNext()) + return result +} + +/** + * Returns a single list of all elements yielded from results of [transform] function being invoked on each entry of original map. + */ +public inline fun Map.flatMap(transform: (Map.Entry) -> Iterable): List { + return flatMapTo(ArrayList(), transform) +} + +/** + * Appends all elements yielded from results of [transform] function being invoked on each entry of original map, to the given [destination]. + */ +public inline fun > Map.flatMapTo(destination: C, transform: (Map.Entry) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} + +/** + * Returns a list containing the results of applying the given [transform] function + * to each entry in the original map. + */ +public inline fun Map.map(transform: (Map.Entry) -> R): List { + return mapTo(ArrayList(size), transform) +} + +/** + * Returns a list containing only the non-null results of applying the given [transform] function + * to each entry in the original map. + */ +public inline fun Map.mapNotNull(transform: (Map.Entry) -> R?): List { + return mapNotNullTo(ArrayList(), transform) +} + +/** + * Applies the given [transform] function to each entry in the original map + * and appends only the non-null results to the given [destination]. + */ +@FixmeLambda +public inline fun > Map.mapNotNullTo(destination: C, transform: (Map.Entry) -> R?): C { + TODO() + //forEach { element -> transform(element)?.let { destination.add(it) } } + //return destination +} + +/** + * Applies the given [transform] function to each entry of the original map + * and appends the results to the given [destination]. + */ +public inline fun > Map.mapTo(destination: C, transform: (Map.Entry) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} + +/** + * Returns `true` if all entries match the given [predicate]. + */ +public inline fun Map.all(predicate: (Map.Entry) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} + +/** + * Returns `true` if map has at least one entry. + */ +public fun Map.any(): Boolean { + for (element in this) return true + return false +} + +/** + * Returns `true` if at least one entry matches the given [predicate]. + */ +public inline fun Map.any(predicate: (Map.Entry) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} + +/** + * Returns the number of entries in this map. + */ +@kotlin.internal.InlineOnly +public inline fun Map.count(): Int { + return size +} + +/** + * Returns the number of entries matching the given [predicate]. + */ +public inline fun Map.count(predicate: (Map.Entry) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) count++ + return count +} + +/** + * Performs the given [action] on each entry. + */ +@kotlin.internal.HidesMembers +public inline fun Map.forEach(action: (Map.Entry) -> Unit): Unit { + for (element in this) action(element) +} diff --git a/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt b/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt new file mode 100644 index 00000000000..8fa739a3f2a --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt @@ -0,0 +1,303 @@ +package kotlin.collections + +/** + * Removes a single instance of the specified element from this + * collection, if it is present. + * + * Allows to overcome type-safety restriction of `remove` that requires to pass an element of type `E`. + * + * @return `true` if the element has been successfully removed; `false` if it was not present in the collection. + */ +@kotlin.internal.InlineOnly +public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.remove(element: T): Boolean + = @Suppress("UNCHECKED_CAST") (this as MutableCollection).remove(element) + +/** + * Removes all of this collection's elements that are also contained in the specified collection. + + * Allows to overcome type-safety restriction of `removeAll` that requires to pass a collection of type `Collection`. + * + * @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified. + */ +@kotlin.internal.InlineOnly +public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.removeAll(elements: Collection): Boolean + = @Suppress("UNCHECKED_CAST") (this as MutableCollection).removeAll(elements) + +/** + * Retains only the elements in this collection that are contained in the specified collection. + * + * Allows to overcome type-safety restriction of `retailAll` that requires to pass a collection of type `Collection`. + * + * @return `true` if any element was removed from the collection, `false` if the collection was not modified. + */ +@kotlin.internal.InlineOnly +public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.retainAll(elements: Collection): Boolean + = @Suppress("UNCHECKED_CAST") (this as MutableCollection).retainAll(elements) + +/** + * Removes the element at the specified [index] from this list. + * In Kotlin one should use the [MutableList.removeAt] function instead. + */ +@Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)"), level = DeprecationLevel.ERROR) +@kotlin.internal.InlineOnly +public inline fun MutableList.remove(index: Int): T = removeAt(index) + +/** + * Adds the specified [element] to this mutable collection. + */ +@kotlin.internal.InlineOnly +public inline operator fun MutableCollection.plusAssign(element: T) { + this.add(element) +} + +/** + * Adds all elements of the given [elements] collection to this mutable collection. + */ +@kotlin.internal.InlineOnly +public inline operator fun MutableCollection.plusAssign(elements: Iterable) { + this.addAll(elements) +} + +/** + * Adds all elements of the given [elements] array to this mutable collection. + */ +@kotlin.internal.InlineOnly +public inline operator fun MutableCollection.plusAssign(elements: Array) { + this.addAll(elements) +} + +/** + * Adds all elements of the given [elements] sequence to this mutable collection. + */ +@kotlin.internal.InlineOnly +public inline operator fun MutableCollection.plusAssign(elements: Sequence) { + this.addAll(elements) +} + +/** + * Removes a single instance of the specified [element] from this mutable collection. + */ +@kotlin.internal.InlineOnly +public inline operator fun MutableCollection.minusAssign(element: T) { + this.remove(element) +} + +/** + * Removes all elements contained in the given [elements] collection from this mutable collection. + */ +@kotlin.internal.InlineOnly +public inline operator fun MutableCollection.minusAssign(elements: Iterable) { + this.removeAll(elements) +} + +/** + * Removes all elements contained in the given [elements] array from this mutable collection. + */ +@kotlin.internal.InlineOnly +public inline operator fun MutableCollection.minusAssign(elements: Array) { + this.removeAll(elements) +} + +/** + * Removes all elements contained in the given [elements] sequence from this mutable collection. + */ +@kotlin.internal.InlineOnly +public inline operator fun MutableCollection.minusAssign(elements: Sequence) { + this.removeAll(elements) +} + +/** + * Adds all elements of the given [elements] collection to this [MutableCollection]. + */ +public fun MutableCollection.addAll(elements: Iterable): Boolean { + when (elements) { + is Collection -> return addAll(elements) + else -> { + var result: Boolean = false + for (item in elements) + if (add(item)) result = true + return result + } + } +} + +/** + * Adds all elements of the given [elements] sequence to this [MutableCollection]. + */ +public fun MutableCollection.addAll(elements: Sequence): Boolean { + var result: Boolean = false + for (item in elements) { + if (add(item)) result = true + } + return result +} + +/** + * Adds all elements of the given [elements] array to this [MutableCollection]. + */ +public fun MutableCollection.addAll(elements: Array): Boolean { + return addAll(elements.asList()) +} + +/** + * Removes all elements from this [MutableIterable] that match the given [predicate]. + */ +public fun MutableIterable.removeAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, true) + +/** + * Retains only elements of this [MutableIterable] that match the given [predicate]. + */ +public fun MutableIterable.retainAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, false) + +// TODO: due to boxing problems, cannot use Boolean type. +@FixmeBoxing +private fun MutableIterable.filterInPlace(predicate: (T) -> Boolean, predicateResultToRemove: Boolean): Boolean { + TODO() + /* + var result = false + with (iterator()) { + while (hasNext()) + if (predicate(next()).toString() == predicateResultToRemove) { + remove() + result = true + } + } + return result */ +} + +/** + * Removes all elements from this [MutableList] that match the given [predicate]. + */ +public fun MutableList.removeAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, true) + +/** + * Retains only elements of this [MutableList] that match the given [predicate]. + */ +public fun MutableList.retainAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, false) + +@Fixme +private fun MutableList.filterInPlace(predicate: (T) -> Boolean, predicateResultToRemove: Boolean): Boolean { + TODO() +} +/* TODO: fix downTo, RandomAccess + if (this !is RandomAccess) + return (this as MutableIterable).filterInPlace(predicate, predicateResultToRemove) + + var writeIndex: Int = 0 + for (readIndex in 0..lastIndex) { + val element = this[readIndex] + if (predicate(element) == predicateResultToRemove) + continue + + if (writeIndex != readIndex) + this[writeIndex] = element + + writeIndex++ + } + if (writeIndex < size) { + for (removeIndex in lastIndex downTo writeIndex) + removeAt(removeIndex) + + return true + } + else { + return false + } +} */ + +/** + * Removes all elements from this [MutableCollection] that are also contained in the given [elements] collection. + */ +@Fixme +public fun MutableCollection.removeAll(elements: Iterable): Boolean { + // TODO: add convertToSetForSetOperationWith + // return removeAll(elements.convertToSetForSetOperationWith(this)) + var removed = false + for (e in elements) { + removed = removed or remove(e) + } + return removed +} + +/** + * Removes all elements from this [MutableCollection] that are also contained in the given [elements] sequence. + */ +@Fixme +public fun MutableCollection.removeAll(elements: Sequence): Boolean { + // TODO: add toHashSet() + //val set = elements.toHashSet() + // return set.isNotEmpty() && removeAll(set) + var removed = false + for (e in elements) { + removed = removed or remove(e) + } + return removed +} + +/** + * Removes all elements from this [MutableCollection] that are also contained in the given [elements] array. + */ +@Fixme +public fun MutableCollection.removeAll(elements: Array): Boolean { + // TODO: add toHashSet() + // return elements.isNotEmpty() && removeAll(elements.toHashSet()) + var removed = false + for (e in elements) { + removed = removed or remove(e) + } + return removed +} + +/** + * Retains only elements of this [MutableCollection] that are contained in the given [elements] collection. + */ +@Fixme +public fun MutableCollection.retainAll(elements: Iterable): Boolean { + TODO() + //return retainAll(elements.convertToSetForSetOperationWith(this)) +} + +/** + * Retains only elements of this [MutableCollection] that are contained in the given [elements] array. + */ +public fun MutableCollection.retainAll(elements: Array): Boolean { + if (elements.isNotEmpty()) + return retainAll(elements.toHashSet()) + else + return retainNothing() +} + +/** + * Retains only elements of this [MutableCollection] that are contained in the given [elements] sequence. + */ +public fun MutableCollection.retainAll(elements: Sequence): Boolean { + val set = elements.toHashSet() + if (set.isNotEmpty()) + return retainAll(set) + else + return retainNothing() +} + +private fun MutableCollection<*>.retainNothing(): Boolean { + val result = isNotEmpty() + clear() + return result +} */ + +/** + * Sorts elements in the list in-place according to their natural sort order. + */ +@Fixme +public fun > MutableList.sort(): Unit { + TODO() + //if (size > 1) java.util.Collections.sort(this) +} + +/** + * Sorts elements in the list in-place according to the order specified with [comparator]. + */ +@Fixme +public fun MutableList.sortWith(comparator: Comparator): Unit { + TODO() + //if (size > 1) java.util.Collections.sort(this, comparator) +} diff --git a/runtime/src/main/kotlin/kotlin/collections/Sets.kt b/runtime/src/main/kotlin/kotlin/collections/Sets.kt index fe24b17bf03..c9262500d1d 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Sets.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Sets.kt @@ -25,7 +25,8 @@ public fun emptySet(): Set = EmptySet */ public fun setOf(vararg elements: T): Set = if (elements.size > 0) elements.toSet() else emptySet() -/** Returns an empty read-only set. The returned set is serializable (JVM). */ +/** Returns an empty read-only set. */ +@kotlin.internal.InlineOnly public inline fun setOf(): Set = emptySet() /** @@ -44,6 +45,7 @@ public fun hashSetOf(vararg elements: T): HashSet = elements.toCollection //public fun linkedSetOf(vararg elements: T): LinkedHashSet = elements.toCollection(LinkedHashSet(mapCapacity(elements.size))) /** Returns this Set if it's not `null` and the empty set otherwise. */ +@kotlin.internal.InlineOnly public inline fun Set?.orEmpty(): Set = this ?: emptySet() /** diff --git a/runtime/src/main/kotlin/kotlin/internal/Annotations.kt b/runtime/src/main/kotlin/kotlin/internal/Annotations.kt index 6ad51b9a607..1c80ba3ed9c 100644 --- a/runtime/src/main/kotlin/kotlin/internal/Annotations.kt +++ b/runtime/src/main/kotlin/kotlin/internal/Annotations.kt @@ -1,8 +1,54 @@ package kotlin.internal +/** + * Specifies that the corresponding type should be ignored during type inference. + */ +@Target(AnnotationTarget.TYPE) +@Retention(AnnotationRetention.BINARY) +internal annotation class NoInfer +/** + * Specifies that the constraint built for the type during type inference should be an equality one. + */ +@Target(AnnotationTarget.TYPE) +@Retention(AnnotationRetention.BINARY) +internal annotation class Exact + +/** + * Specifies that a corresponding member has the lowest priority in overload resolution. + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.BINARY) +internal annotation class LowPriorityInOverloadResolution + +/** + * Specifies that the corresponding member has the highest priority in overload resolution. Effectively this means that + * an extension annotated with this annotation will win in overload resolution over a member with the same signature. + */ +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.BINARY) +internal annotation class HidesMembers + +/** + * The value of this type parameter should be mentioned in input types (argument types, receiver type or expected type). + */ @Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER) public annotation class OnlyInputTypes + @Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER) -public annotation class OnlyOutputTypes \ No newline at end of file +public annotation class OnlyOutputTypes + +/** + * Specifies that this function should not be called directly without inlining + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +internal annotation class InlineOnly + +/** + * Specifies that this part of internal API is effectively public exposed by using in public inline function + */ +@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.BINARY) +internal annotation class InlineExposed diff --git a/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt b/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt index ffa97c09267..768cb33ef48 100644 --- a/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt +++ b/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt @@ -324,3 +324,12 @@ public fun Long.coerceIn(range: ClosedRange): Long { if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.") return if (this < range.start) range.start else if (this > range.endInclusive) range.endInclusive else this } + + +// This part is from generated _Ranges.kt. +/** + * Returns a progression that goes over the same range in the opposite direction with the same step. + */ +public fun IntProgression.reversed(): IntProgression { + return IntProgression.fromClosedRange(last, first, -step) +} diff --git a/runtime/src/main/kotlin/kotlin/util/Standard.kt b/runtime/src/main/kotlin/kotlin/util/Standard.kt new file mode 100644 index 00000000000..9fe0eb82ad5 --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/util/Standard.kt @@ -0,0 +1,64 @@ +package kotlin + +/** + * An exception is thrown to indicate that a method body remains to be implemented. + */ +public class NotImplementedError(message: String) : Error(message) + +/** + * Always throws [NotImplementedError] stating that operation is not implemented. + */ + +@kotlin.internal.InlineOnly +public inline fun TODO(): Nothing = throw NotImplementedError("An operation is not implemented.") + +/** + * Always throws [NotImplementedError] stating that operation is not implemented. + * + * @param reason a string explaining why the implementation is missing. + */ +@kotlin.internal.InlineOnly +public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason") + + +/** + * Calls the specified function [block] and returns its result. + */ +@kotlin.internal.InlineOnly +public inline fun run(block: () -> R): R = block() + +/** + * Calls the specified function [block] with `this` value as its receiver and returns its result. + */ +@kotlin.internal.InlineOnly +public inline fun T.run(block: T.() -> R): R = block() + +/** + * Calls the specified function [block] with the given [receiver] as its receiver and returns its result. + */ +@kotlin.internal.InlineOnly +public inline fun with(receiver: T, block: T.() -> R): R = receiver.block() + +/** + * Calls the specified function [block] with `this` value as its receiver and returns `this` value. + */ +@kotlin.internal.InlineOnly +public inline fun T.apply(block: T.() -> Unit): T { block(); return this } + +/** + * Calls the specified function [block] with `this` value as its argument and returns its result. + */ +@kotlin.internal.InlineOnly +public inline fun T.let(block: (T) -> R): R = block(this) + +/** + * Executes the given function [action] specified number of [times]. + * + * A zero-based index of current iteration is passed as a parameter to [action]. + */ +@kotlin.internal.InlineOnly +public inline fun repeat(times: Int, action: (Int) -> Unit) { + for (index in 0..times - 1) { + action(index) + } +} \ No newline at end of file