From 5584b435dcf73b9bafad2969eb8ec033e0e257ae Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 25 Dec 2018 06:55:48 +0300 Subject: [PATCH] Provide implementation templates for Native platform --- .../kotlin-stdlib-gen/src/templates/Arrays.kt | 125 +++++++++++++++++- .../src/templates/Comparables.kt | 80 ++++++++--- 2 files changed, 184 insertions(+), 21 deletions(-) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index bcb9555c96a..264208665ee 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -92,6 +92,24 @@ object ArrayOps : TemplateGroupBase() { body { "return contentEqualsInternal(other)" } } } + on(Platform.Native) { + body { + """ + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true + """ + } + } } val f_contentDeepEquals = fn("contentDeepEquals(other: SELF)") { @@ -131,6 +149,9 @@ object ArrayOps : TemplateGroupBase() { body { "return contentDeepEqualsImpl(other)" } } } + on(Platform.Native) { + body { "return contentDeepEqualsImpl(other)" } + } } val f_contentToString = fn("contentToString()") { @@ -161,6 +182,9 @@ object ArrayOps : TemplateGroupBase() { body { "return arrayToString(this as Array<*>)" } } } + on(Platform.Native) { + body { """return joinToString(", ", "[", "]")""" } + } } val f_contentDeepToString = fn("contentDeepToString()") { @@ -199,6 +223,9 @@ object ArrayOps : TemplateGroupBase() { body { "return contentDeepToStringImpl()" } } } + on(Platform.Native) { + body { "return contentDeepToStringImpl()" } + } } val f_contentHashCode = fn("contentHashCode()") { @@ -226,6 +253,16 @@ object ArrayOps : TemplateGroupBase() { body { "return contentHashCodeInternal()" } } } + on(Platform.Native) { + body { + """ + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result + """ + } + } } val f_contentDeepHashCode = fn("contentDeepHashCode()") { @@ -262,6 +299,9 @@ object ArrayOps : TemplateGroupBase() { body { "return contentDeepHashCodeInternal()" } } } + on(Platform.Native) { + body { "return contentDeepHashCodeImpl()" } + } } val f_toPrimitiveArray = fn("toPrimitiveArray()") { @@ -382,6 +422,10 @@ object ArrayOps : TemplateGroupBase() { inlineOnly() body { "return plus(element)" } } + on(Platform.Native) { + inlineOnly() + body { "return plus(element)" } + } on(Platform.JS) { family = ArraysOfObjects inline(suppressWarning = true) @@ -433,6 +477,16 @@ object ArrayOps : TemplateGroupBase() { "return plus(${primitive.name.toLowerCase()}ArrayOf(element))" } } + on(Platform.Native) { + body { + """ + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result + """ + } + } on(Platform.Common) { specialFor(InvariantArraysOfObjects) { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 @@ -473,6 +527,16 @@ object ArrayOps : TemplateGroupBase() { body { "return fillFromCollection(this.copyOf(size + elements.size), this.size, elements)" } } } + on(Platform.Native) { + body { + """ + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result + """ + } + } on(Platform.Common) { specialFor(InvariantArraysOfObjects) { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 @@ -514,6 +578,17 @@ object ArrayOps : TemplateGroupBase() { body { """return primitiveArrayConcat(this, elements)""" } } } + on(Platform.Native) { + body { + """ + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result + """ + } + } on(Platform.Common) { specialFor(InvariantArraysOfObjects) { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 @@ -581,6 +656,15 @@ object ArrayOps : TemplateGroupBase() { """ } } + on(Platform.Native) { + suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") + body { + """ + this.copyRangeTo(destination, startIndex, endIndex, destinationOffset) + return destination + """ + } + } } } @@ -654,6 +738,15 @@ object ArrayOps : TemplateGroupBase() { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 } } + on(Platform.Native) { + inlineOnly() + body { + """ + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) + """ + } + } } } @@ -699,7 +792,10 @@ object ArrayOps : TemplateGroupBase() { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 } } - + on(Platform.Native) { + inlineOnly() + body { "return this.copyOfUninitializedElements(size)" } + } } } @@ -739,7 +835,10 @@ object ArrayOps : TemplateGroupBase() { } body { newSizeCheck + "\n" + body } } - + on(Platform.Native) { + inlineOnly() + body { "return this.copyOfUninitializedElements(newSize)" } + } } specialFor(InvariantArraysOfObjects) { sample("samples.collections.Arrays.CopyOfOperations.resizingCopyOf") @@ -757,6 +856,10 @@ object ArrayOps : TemplateGroupBase() { on(Platform.Common) { suppress("NO_ACTUAL_FOR_EXPECT") // TODO: KT-21937 } + on(Platform.Native) { + inlineOnly() + body { "return this.copyOfNulls(newSize)" } + } } specialFor(ArraysOfPrimitives, InvariantArraysOfObjects) { on(Platform.JVM) { @@ -814,6 +917,14 @@ object ArrayOps : TemplateGroupBase() { } } } + on(Platform.Native) { + specialFor(ArraysOfObjects) { + body { """if (size > 1) kotlin.util.sortArrayComparable(this)""" } + } + specialFor(ArraysOfPrimitives) { + body { """if (size > 1) kotlin.util.sortArray(this)""" } + } + } } val f_sortWith = fn("sortWith(comparator: Comparator)") { @@ -834,6 +945,9 @@ object ArrayOps : TemplateGroupBase() { """ } } + on(Platform.Native) { + body { """if (size > 1) kotlin.util.sortArrayWith(this, 0, size, comparator)""" } + } } val f_sort_comparison = fn("sort(noinline comparison: (a: T, b: T) -> Int)") { @@ -902,8 +1016,7 @@ object ArrayOps : TemplateGroupBase() { body { """return ArrayList(this.unsafeCast>())""" } } - specialFor(ArraysOfPrimitives) { - val objectLiteralImpl = """ + val objectLiteralImpl = """ return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -913,6 +1026,7 @@ object ArrayOps : TemplateGroupBase() { override fun lastIndexOf(element: T): Int = this@asList.lastIndexOf(element) } """ + specialFor(ArraysOfPrimitives) { on(Platform.JVM) { body { objectLiteralImpl } } @@ -926,6 +1040,9 @@ object ArrayOps : TemplateGroupBase() { } } } + on(Platform.Native) { + body { objectLiteralImpl } + } } val f_toTypedArray = fn("toTypedArray()") { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt index 2c06f09e418..1419c022428 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt @@ -145,6 +145,7 @@ object ComparableOps : TemplateGroupBase() { If values are equal, returns the first one. """ } + val defaultImpl = "if (a <= b) a else b" // TODO: Add a note about NaN propagation for floats. specialFor(Primitives) { inlineOnly() @@ -156,26 +157,45 @@ object ComparableOps : TemplateGroupBase() { suppress("DEPRECATION_ERROR") convertBack = "unsafeCast<$primitive>()" } - body { - "return Math.min(a, b)" + body { "return $defaultImpl" } + on(Platform.JVM) { + body { "return Math.min(a, b)" } + } + on(Platform.JS) { + body { "return Math.min(a, b)" } + if (primitive == PrimitiveType.Long) { + inline(suppressWarning = true) + body { "return $defaultImpl" } + } } if (primitive in shortIntPrimitives) { body { "return Math.min(a.toInt(), b.toInt()).$convertBack" } + on(Platform.Native) { + body { "return minOf(a.toInt(), b.toInt()).$convertBack" } + } } - on(Platform.JS) { - if (primitive == PrimitiveType.Long) { - inline(suppressWarning = true) - body { "return if (a <= b) a else b" } + if (primitive?.isIntegral() == false) { + on(Platform.Native) { + body { + """ + // TODO: Check +/-0.0 + return when { + a.isNaN() -> a + b.isNaN() -> b + else -> $defaultImpl + } + """ + } } } } on(Platform.JS) { /* just to make expect, KT-22520 */ } body(Generic) { - "return if (a <= b) a else b" + "return $defaultImpl" } } - val f_minOf = fn("minOf(a: T, b: T, c: T)") { + val f_minOf_3 = fn("minOf(a: T, b: T, c: T)") { include(Generic) include(Primitives, numericPrimitives) } builder { @@ -197,7 +217,10 @@ object ComparableOps : TemplateGroupBase() { on(Platform.JS) { /* just to make expect, KT-22520 */ } specialFor(Primitives) { if (primitive in shortIntPrimitives) { - body { "return Math.min(a.toInt(), Math.min(b.toInt(), c.toInt())).to$primitive()" } + body { "return minOf(a.toInt(), minOf(b.toInt(), c.toInt())).to$primitive()" } + on(Platform.JVM) { + body { "return Math.min(a.toInt(), Math.min(b.toInt(), c.toInt())).to$primitive()" } + } on(Platform.JS) { suppress("DEPRECATION_ERROR") body { "return Math.min(a.toInt(), b.toInt(), c.toInt()).unsafeCast<$primitive>()" } @@ -262,6 +285,7 @@ object ComparableOps : TemplateGroupBase() { If values are equal, returns the first one. """ } + val defaultImpl = "if (a >= b) a else b" // TODO: Add a note about NaN propagation for floats. specialFor(Primitives) { inlineOnly() @@ -273,22 +297,41 @@ object ComparableOps : TemplateGroupBase() { suppress("DEPRECATION_ERROR") convertBack = "unsafeCast<$primitive>()" } - body { - "return Math.max(a, b)" + body { "return $defaultImpl" } + on(Platform.JVM) { + body { "return Math.max(a, b)" } + } + on(Platform.JS) { + body { "return Math.max(a, b)" } + if (primitive == PrimitiveType.Long) { + inline(suppressWarning = true) + body { "return $defaultImpl" } + } } if (primitive in shortIntPrimitives) { body { "return Math.max(a.toInt(), b.toInt()).$convertBack" } + on(Platform.Native) { + body { "return maxOf(a.toInt(), b.toInt()).$convertBack" } + } } - on(Platform.JS) { - if (primitive == PrimitiveType.Long) { - inline(suppressWarning = true) - body { "return if (a >= b) a else b" } + if (primitive?.isIntegral() == false) { + on(Platform.Native) { + body { + """ + // TODO: Check +/-0.0 + return when { + a.isNaN() -> a + b.isNaN() -> b + else -> $defaultImpl + } + """ + } } } } on(Platform.JS) { /* just to make expect, KT-22520 */ } body(Generic) { - "return if (a >= b) a else b" + "return $defaultImpl" } } @@ -314,7 +357,10 @@ object ComparableOps : TemplateGroupBase() { on(Platform.JS) { /* just to make expect, KT-22520 */ } specialFor(Primitives) { if (primitive in shortIntPrimitives) { - body { "return Math.max(a.toInt(), Math.max(b.toInt(), c.toInt())).to$primitive()" } + body { "return maxOf(a.toInt(), maxOf(b.toInt(), c.toInt())).to$primitive()" } + on(Platform.JVM) { + body { "return Math.max(a.toInt(), Math.max(b.toInt(), c.toInt())).to$primitive()" } + } on(Platform.JS) { suppress("DEPRECATION_ERROR") body { "return Math.max(a.toInt(), b.toInt(), c.toInt()).unsafeCast<$primitive>()" }