JS: concat vararg arguments using Kotlin.concat and Kotlin.concatPrimitive functions in order to be binary compatible with (Kotlin PrimitiveArray -> JS TypedArrays) mapping.

This commit is contained in:
Anton Bannykh
2017-02-13 15:27:48 +03:00
parent a903c4ab0e
commit 4c808e8691
7 changed files with 197 additions and 100 deletions
+21
View File
@@ -94,3 +94,24 @@ public class BoxedChar(val c: Char) : Comparable<Char> {
return js("this.c") return js("this.c")
} }
} }
/* For future binary compatibility with TypedArrays
* TODO: concat normal Array's and TypedArrays into an Array
*/
@PublishedApi
@JsName("arrayConcat")
internal fun <T> arrayConcat(a: T, b: T): T {
return a.asDynamic().concat.apply(js("[]"), js("arguments"));
}
/* For future binary compatibility with TypedArrays
* TODO: concat primitive arrays.
* For Byte-, Short-, Int-, Float-, and DoubleArray concat result into a TypedArray.
* For Boolean-, Char-, and LongArray return an Array with corresponding type property.
* Default to Array.prototype.concat for compatibility.
*/
@PublishedApi
@JsName("primitiveArrayConcat")
internal fun <T> primitiveArrayConcat(a: T, b: T): T {
return a.asDynamic().concat.apply(js("[]"), js("arguments"));
}
+26 -18
View File
@@ -9,6 +9,7 @@ package kotlin.collections
// //
import kotlin.js.* import kotlin.js.*
import primitiveArrayConcat
import kotlin.comparisons.* import kotlin.comparisons.*
/** /**
@@ -12944,8 +12945,15 @@ public inline fun BooleanArray.asList(): List<Boolean> {
/** /**
* Returns a [List] that wraps the original array. * Returns a [List] that wraps the original array.
*/ */
public inline fun CharArray.asList(): List<Char> { public fun CharArray.asList(): List<Char> {
return this.toTypedArray().asList() return object : AbstractList<Char>(), RandomAccess {
override val size: Int get() = this@asList.size
override fun isEmpty(): Boolean = this@asList.isEmpty()
override fun contains(element: Char): Boolean = this@asList.contains(element)
override fun get(index: Int): Char = this@asList[index]
override fun indexOf(element: Char): Int = this@asList.indexOf(element)
override fun lastIndexOf(element: Char): Int = this@asList.lastIndexOf(element)
}
} }
/** /**
@@ -13168,7 +13176,7 @@ public inline operator fun <T> Array<out T>.plus(element: T): Array<T> {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun ByteArray.plus(element: Byte): ByteArray { public inline operator fun ByteArray.plus(element: Byte): ByteArray {
return this.asDynamic().concat(arrayOf(element)) return plus(byteArrayOf(element))
} }
/** /**
@@ -13176,7 +13184,7 @@ public inline operator fun ByteArray.plus(element: Byte): ByteArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun ShortArray.plus(element: Short): ShortArray { public inline operator fun ShortArray.plus(element: Short): ShortArray {
return this.asDynamic().concat(arrayOf(element)) return plus(shortArrayOf(element))
} }
/** /**
@@ -13184,7 +13192,7 @@ public inline operator fun ShortArray.plus(element: Short): ShortArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun IntArray.plus(element: Int): IntArray { public inline operator fun IntArray.plus(element: Int): IntArray {
return this.asDynamic().concat(arrayOf(element)) return plus(intArrayOf(element))
} }
/** /**
@@ -13192,7 +13200,7 @@ public inline operator fun IntArray.plus(element: Int): IntArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun LongArray.plus(element: Long): LongArray { public inline operator fun LongArray.plus(element: Long): LongArray {
return this.asDynamic().concat(arrayOf(element)) return plus(longArrayOf(element))
} }
/** /**
@@ -13200,7 +13208,7 @@ public inline operator fun LongArray.plus(element: Long): LongArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun FloatArray.plus(element: Float): FloatArray { public inline operator fun FloatArray.plus(element: Float): FloatArray {
return this.asDynamic().concat(arrayOf(element)) return plus(floatArrayOf(element))
} }
/** /**
@@ -13208,7 +13216,7 @@ public inline operator fun FloatArray.plus(element: Float): FloatArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun DoubleArray.plus(element: Double): DoubleArray { public inline operator fun DoubleArray.plus(element: Double): DoubleArray {
return this.asDynamic().concat(arrayOf(element)) return plus(doubleArrayOf(element))
} }
/** /**
@@ -13216,7 +13224,7 @@ public inline operator fun DoubleArray.plus(element: Double): DoubleArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun BooleanArray.plus(element: Boolean): BooleanArray { public inline operator fun BooleanArray.plus(element: Boolean): BooleanArray {
return this.asDynamic().concat(arrayOf(element)) return plus(booleanArrayOf(element))
} }
/** /**
@@ -13224,7 +13232,7 @@ public inline operator fun BooleanArray.plus(element: Boolean): BooleanArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun CharArray.plus(element: Char): CharArray { public inline operator fun CharArray.plus(element: Char): CharArray {
return this.asDynamic().concat(arrayOf(element)) return plus(charArrayOf(element))
} }
/** /**
@@ -13303,7 +13311,7 @@ public inline operator fun <T> Array<out T>.plus(elements: Array<out T>): Array<
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun ByteArray.plus(elements: ByteArray): ByteArray { public inline operator fun ByteArray.plus(elements: ByteArray): ByteArray {
return this.asDynamic().concat(elements) return primitiveArrayConcat(this, elements)
} }
/** /**
@@ -13311,7 +13319,7 @@ public inline operator fun ByteArray.plus(elements: ByteArray): ByteArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun ShortArray.plus(elements: ShortArray): ShortArray { public inline operator fun ShortArray.plus(elements: ShortArray): ShortArray {
return this.asDynamic().concat(elements) return primitiveArrayConcat(this, elements)
} }
/** /**
@@ -13319,7 +13327,7 @@ public inline operator fun ShortArray.plus(elements: ShortArray): ShortArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun IntArray.plus(elements: IntArray): IntArray { public inline operator fun IntArray.plus(elements: IntArray): IntArray {
return this.asDynamic().concat(elements) return primitiveArrayConcat(this, elements)
} }
/** /**
@@ -13327,7 +13335,7 @@ public inline operator fun IntArray.plus(elements: IntArray): IntArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun LongArray.plus(elements: LongArray): LongArray { public inline operator fun LongArray.plus(elements: LongArray): LongArray {
return this.asDynamic().concat(elements) return primitiveArrayConcat(this, elements)
} }
/** /**
@@ -13335,7 +13343,7 @@ public inline operator fun LongArray.plus(elements: LongArray): LongArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun FloatArray.plus(elements: FloatArray): FloatArray { public inline operator fun FloatArray.plus(elements: FloatArray): FloatArray {
return this.asDynamic().concat(elements) return primitiveArrayConcat(this, elements)
} }
/** /**
@@ -13343,7 +13351,7 @@ public inline operator fun FloatArray.plus(elements: FloatArray): FloatArray {
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun DoubleArray.plus(elements: DoubleArray): DoubleArray { public inline operator fun DoubleArray.plus(elements: DoubleArray): DoubleArray {
return this.asDynamic().concat(elements) return primitiveArrayConcat(this, elements)
} }
/** /**
@@ -13351,7 +13359,7 @@ public inline operator fun DoubleArray.plus(elements: DoubleArray): DoubleArray
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun BooleanArray.plus(elements: BooleanArray): BooleanArray { public inline operator fun BooleanArray.plus(elements: BooleanArray): BooleanArray {
return this.asDynamic().concat(elements) return primitiveArrayConcat(this, elements)
} }
/** /**
@@ -13359,7 +13367,7 @@ public inline operator fun BooleanArray.plus(elements: BooleanArray): BooleanArr
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
public inline operator fun CharArray.plus(elements: CharArray): CharArray { public inline operator fun CharArray.plus(elements: CharArray): CharArray {
return this.asDynamic().concat(elements) return primitiveArrayConcat(this, elements)
} }
/** /**
@@ -17,11 +17,11 @@
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories; package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType; import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.patterns.DescriptorPredicate; import org.jetbrains.kotlin.js.patterns.DescriptorPredicate;
import org.jetbrains.kotlin.js.patterns.NamePredicate; import org.jetbrains.kotlin.js.patterns.NamePredicate;
import org.jetbrains.kotlin.js.translate.context.Namer; import org.jetbrains.kotlin.js.translate.context.Namer;
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.js.translate.reference package org.jetbrains.kotlin.js.translate.reference
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable
import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.context.TranslationContext
@@ -83,6 +83,7 @@ class CallArgumentTranslator private constructor(
var argsBeforeVararg: List<JsExpression>? = null var argsBeforeVararg: List<JsExpression>? = null
var concatArguments: MutableList<JsExpression>? = null var concatArguments: MutableList<JsExpression>? = null
val argsToJsExpr = translateUnresolvedArguments(context(), resolvedCall) val argsToJsExpr = translateUnresolvedArguments(context(), resolvedCall)
var isVarargTypePrimitive: Boolean? = null
for (parameterDescriptor in valueParameters) { for (parameterDescriptor in valueParameters) {
val actualArgument = valueArgumentsByIndex[parameterDescriptor.index] val actualArgument = valueArgumentsByIndex[parameterDescriptor.index]
@@ -95,6 +96,8 @@ class CallArgumentTranslator private constructor(
hasSpreadOperator = arguments.any { it.getSpreadElement() != null } hasSpreadOperator = arguments.any { it.getSpreadElement() != null }
} }
isVarargTypePrimitive = KotlinBuiltIns.isPrimitiveType(parameterDescriptor.original.varargElementType!!)
if (hasSpreadOperator) { if (hasSpreadOperator) {
if (isNativeFunctionCall) { if (isNativeFunctionCall) {
argsBeforeVararg = result argsBeforeVararg = result
@@ -102,7 +105,10 @@ class CallArgumentTranslator private constructor(
concatArguments = prepareConcatArguments(arguments, translateResolvedArgument(actualArgument, argsToJsExpr)) concatArguments = prepareConcatArguments(arguments, translateResolvedArgument(actualArgument, argsToJsExpr))
} }
else { else {
result.addAll(translateVarargArgument(actualArgument, argsToJsExpr, actualArgument.arguments.size > 1)) result.addAll(translateVarargArgument(actualArgument,
argsToJsExpr,
actualArgument.arguments.size > 1,
isVarargTypePrimitive))
} }
} }
else { else {
@@ -110,7 +116,7 @@ class CallArgumentTranslator private constructor(
result.addAll(translateResolvedArgument(actualArgument, argsToJsExpr)) result.addAll(translateResolvedArgument(actualArgument, argsToJsExpr))
} }
else { else {
result.addAll(translateVarargArgument(actualArgument, argsToJsExpr, true)) result.addAll(translateVarargArgument(actualArgument, argsToJsExpr, true, isVarargTypePrimitive))
} }
} }
} }
@@ -123,13 +129,15 @@ class CallArgumentTranslator private constructor(
assert(argsBeforeVararg != null) { "argsBeforeVararg should not be null" } assert(argsBeforeVararg != null) { "argsBeforeVararg should not be null" }
assert(concatArguments != null) { "concatArguments should not be null" } assert(concatArguments != null) { "concatArguments should not be null" }
concatArguments!!.addAll(result) if (!result.isEmpty()) {
concatArguments!!.add(JsArrayLiteral(result).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
if (!argsBeforeVararg!!.isEmpty()) {
concatArguments.add(0, JsArrayLiteral(argsBeforeVararg).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
} }
result = mutableListOf(concatArgumentsIfNeeded(concatArguments)) if (!argsBeforeVararg!!.isEmpty()) {
concatArguments!!.add(0, JsArrayLiteral(argsBeforeVararg).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
}
result = mutableListOf(concatArgumentsIfNeeded(concatArguments!!, isVarargTypePrimitive!!, true))
if (receiver != null) { if (receiver != null) {
cachedReceiver = context().getOrDeclareTemporaryConstVariable(receiver) cachedReceiver = context().getOrDeclareTemporaryConstVariable(receiver)
@@ -235,7 +243,8 @@ class CallArgumentTranslator private constructor(
private fun translateVarargArgument( private fun translateVarargArgument(
resolvedArgument: ResolvedValueArgument, resolvedArgument: ResolvedValueArgument,
translatedArgs: Map<ValueArgument, JsExpression>, translatedArgs: Map<ValueArgument, JsExpression>,
shouldWrapVarargInArray: Boolean shouldWrapVarargInArray: Boolean,
isVarargTypePrimitive: Boolean
): List<JsExpression> { ): List<JsExpression> {
val arguments = resolvedArgument.arguments val arguments = resolvedArgument.arguments
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
@@ -251,7 +260,7 @@ class CallArgumentTranslator private constructor(
return if (shouldWrapVarargInArray) { return if (shouldWrapVarargInArray) {
val concatArguments = prepareConcatArguments(arguments, list) val concatArguments = prepareConcatArguments(arguments, list)
val concatExpression = concatArgumentsIfNeeded(concatArguments) val concatExpression = concatArgumentsIfNeeded(concatArguments, isVarargTypePrimitive, false)
listOf(concatExpression) listOf(concatExpression)
} }
else { else {
@@ -259,12 +268,22 @@ class CallArgumentTranslator private constructor(
} }
} }
private fun concatArgumentsIfNeeded(concatArguments: List<JsExpression>): JsExpression { private fun concatArgumentsIfNeeded(
concatArguments: List<JsExpression>,
isVarargTypePrimitive: Boolean,
isMixed: Boolean
): JsExpression {
assert(concatArguments.isNotEmpty()) { "concatArguments.size should not be 0" } assert(concatArguments.isNotEmpty()) { "concatArguments.size should not be 0" }
if (concatArguments.size > 1) { if (concatArguments.size > 1) {
return JsInvocation(JsNameRef("concat", concatArguments[0]), concatArguments.subList(1, concatArguments.size)) if (isVarargTypePrimitive) {
val method = if (isMixed) "arrayConcat" else "primitiveArrayConcat"
return JsAstUtils.invokeKotlinFunction(method, concatArguments[0],
*concatArguments.subList(1, concatArguments.size).toTypedArray())
}
else {
return JsInvocation(JsNameRef("concat", concatArguments[0]), concatArguments.subList(1, concatArguments.size))
}
} }
else { else {
return concatArguments[0] return concatArguments[0]
+8
View File
@@ -56,6 +56,12 @@ external fun sumFunValuesOnParameters(x: Int, y: Int, vararg a: Int, f: (Int) ->
external fun <T> idArrayVarArg(vararg a: Array<T>): Array<T> = definedExternally external fun <T> idArrayVarArg(vararg a: Array<T>): Array<T> = definedExternally
@JsName("paramCount")
external fun oneMoreParamCount(before: IntArray, vararg middle: Int, after: IntArray): Int
@JsName("paramCount")
external fun <T> oneMoreGenericParamCount(before: Array<T>, vararg middle: T, after: Array<T>): Int
fun box(): String { fun box(): String {
if (paramCount() != 0) if (paramCount() != 0)
return "failed when call native function without args" return "failed when call native function without args"
@@ -138,5 +144,7 @@ fun box(): String {
assertEquals(3, idArrayVarArg(arrayOf(1, 2), *arrayOf(arrayOf(3, 4), arrayOf(5, 6))).size) assertEquals(3, idArrayVarArg(arrayOf(1, 2), *arrayOf(arrayOf(3, 4), arrayOf(5, 6))).size)
assertEquals(6, idArrayVarArg(arrayOf(1, 2), *arrayOf(arrayOf(3, 4), arrayOf(5, 6)), arrayOf(7), *arrayOf(arrayOf(8, 9), arrayOf(10, 11))).size) assertEquals(6, idArrayVarArg(arrayOf(1, 2), *arrayOf(arrayOf(3, 4), arrayOf(5, 6)), arrayOf(7), *arrayOf(arrayOf(8, 9), arrayOf(10, 11))).size)
assertEquals(6, oneMoreParamCount(intArrayOf(1, 2), 3, *intArrayOf(4, 5), 6, after = intArrayOf(7, 8)))
assertEquals(6, oneMoreGenericParamCount(arrayOf("1", "2"), "3", *arrayOf("4", "5"), "6", after = arrayOf("7", "8")))
return "OK" return "OK"
} }
@@ -101,6 +101,9 @@ private fun List<ConcreteFunction>.writeTo(file: File, sourceFile: SourceFile, p
writer.append("$COMMON_AUTOGENERATED_WARNING\n\n") writer.append("$COMMON_AUTOGENERATED_WARNING\n\n")
if (platform == Platform.JS) { if (platform == Platform.JS) {
writer.appendln("import kotlin.js.*") writer.appendln("import kotlin.js.*")
if (sourceFile == SourceFile.Arrays) {
writer.appendln("import primitiveArrayConcat")
}
} }
writer.append("import kotlin.comparisons.*\n\n") writer.append("import kotlin.comparisons.*\n\n")
@@ -175,32 +175,41 @@ object CommonArrays {
} }
} }
fun f_plusElementOperator() = f("plus(element: T)") { fun f_plusElementOperator() =
operator(true) (listOf(InvariantArraysOfObjects to null) + PrimitiveType.defaultPrimitives.map { ArraysOfPrimitives to it }).map {
val (family, primitive) = it
f("plus(element: T)") {
operator(true)
inline(Platform.JS, Inline.Yes) only(family)
annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""") if (family == InvariantArraysOfObjects) {
only(Platform.JS, ArraysOfObjects)
}
only(InvariantArraysOfObjects, ArraysOfPrimitives) inline(Platform.JS, Inline.Yes)
only(Platform.JS, ArraysOfObjects, ArraysOfPrimitives) annotations(Platform.JS, """@Suppress("NOTHING_TO_INLINE")""")
returns("SELF") returns("SELF")
returns(Platform.JS, ArraysOfObjects) { "Array<T>" } returns(Platform.JS, ArraysOfObjects) { "Array<T>" }
doc { "Returns an array containing all elements of the original array and then the given [element]." } doc { "Returns an array containing all elements of the original array and then the given [element]." }
body(Platform.JVM) { body(Platform.JVM) {
""" """
val index = size val index = size
val result = java.util.Arrays.copyOf(this, index + 1) val result = java.util.Arrays.copyOf(this, index + 1)
result[index] = element result[index] = element
return result return result
""" """
} }
body(Platform.JS) {
""" if (primitive == null) {
return this.asDynamic().concat(arrayOf(element)) body(Platform.JS) { "return this.asDynamic().concat(arrayOf(element))" }
""" }
} else {
} only(primitive)
body(Platform.JS, ArraysOfPrimitives) { "return plus(${primitive.name.toLowerCase()}ArrayOf(element))" }
}
}
}
fun f_plusCollection() = f("plus(elements: Collection<T>)") { fun f_plusCollection() = f("plus(elements: Collection<T>)") {
operator(true) operator(true)
@@ -258,6 +267,12 @@ object CommonArrays {
return this.asDynamic().concat(elements) return this.asDynamic().concat(elements)
""" """
} }
body(Platform.JS, ArraysOfPrimitives) {
"""
return primitiveArrayConcat(this, elements)
"""
}
} }
fun f_copyOfRange() = f("copyOfRange(fromIndex: Int, toIndex: Int)") { fun f_copyOfRange() = f("copyOfRange(fromIndex: Int, toIndex: Int)") {
@@ -318,7 +333,7 @@ object CommonArrays {
returns("SELF") returns("SELF")
defaultValue = when (primitive) { defaultValue = when (primitive) {
PrimitiveType.Boolean -> false.toString() PrimitiveType.Boolean -> false.toString()
PrimitiveType.Char -> "'\\u0000'" PrimitiveType.Char -> "0"
else -> "ZERO" else -> "ZERO"
} }
} else { } else {
@@ -399,69 +414,92 @@ object CommonArrays {
} }
fun f_asList() = f("asList()") { fun f_asList() = f("asList()") {
only(ArraysOfObjects, ArraysOfPrimitives) only(ArraysOfObjects)
doc { "Returns a [List] that wraps the original array." } doc { "Returns a [List] that wraps the original array." }
returns("List<T>") returns("List<T>")
body(Platform.JVM, ArraysOfObjects) { body(Platform.JVM) {
""" """
return ArraysUtilJVM.asList(this) return ArraysUtilJVM.asList(this)
""" """
} }
body(Platform.JS, ArraysOfObjects) { body(Platform.JS) {
""" """
return ArrayList<T>(this.unsafeCast<Array<Any?>>()) return ArrayList<T>(this.unsafeCast<Array<Any?>>())
""" """
} }
}
body(Platform.JVM, ArraysOfPrimitives) { fun f_asListPrimitives() =
""" PrimitiveType.defaultPrimitives.map { primitive ->
return object : AbstractList<T>(), RandomAccess { f("asList()") {
override val size: Int get() = this@asList.size only(ArraysOfPrimitives)
override fun isEmpty(): Boolean = this@asList.isEmpty() only(primitive)
override fun contains(element: T): Boolean = this@asList.contains(element) doc { "Returns a [List] that wraps the original array." }
override fun get(index: Int): T = this@asList[index] returns("List<T>")
override fun indexOf(element: T): Int = this@asList.indexOf(element)
override fun lastIndexOf(element: T): Int = this@asList.lastIndexOf(element) val objectLiteralImpl = """
return object : AbstractList<T>(), RandomAccess {
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)
}
"""
body(Platform.JVM) { objectLiteralImpl }
if (primitive == PrimitiveType.Char) {
body(Platform.JS) { objectLiteralImpl }
}
else {
inline(Platform.JS, Inline.Yes, ArraysOfPrimitives)
body(Platform.JS) { "return this.unsafeCast<Array<T>>().asList()" }
}
}
} }
"""
}
fun f_toTypedArray() =
PrimitiveType.defaultPrimitives.map { primitive ->
f("toTypedArray()") {
only(ArraysOfPrimitives)
only(primitive)
returns("Array<T>")
doc {
"""
Returns a *typed* object array containing all of the elements of this primitive array.
"""
}
body(Platform.JVM) {
"""
val result = arrayOfNulls<T>(size)
for (index in indices)
result[index] = this[index]
@Suppress("UNCHECKED_CAST")
return result as Array<T>
"""
}
inline(Platform.JS, Inline.Yes, ArraysOfPrimitives) if (primitive == PrimitiveType.Char) {
body(Platform.JS, ArraysOfPrimitives) {"""return this.unsafeCast<Array<T>>().asList()"""} body(Platform.JS) { "return Array<Char>(size, { i -> this[i] })" }
}
else {
body(Platform.JS) { "return copyOf().unsafeCast<Array<T>>()" }
}
}
}
}
fun f_toTypedArray() = f("toTypedArray()") {
only(ArraysOfPrimitives)
returns("Array<T>")
doc {
"""
Returns a *typed* object array containing all of the elements of this primitive array.
"""
}
body(Platform.JVM) {
"""
val result = arrayOfNulls<T>(size)
for (index in indices)
result[index] = this[index]
@Suppress("UNCHECKED_CAST")
return result as Array<T>
"""
}
body(Platform.JS) {
"""
return copyOf().unsafeCast<Array<T>>()
"""
}
}
// TODO: use reflection later to get all functions of matching type // TODO: use reflection later to get all functions of matching type
fun templates() = fun templates() =
listOf(f_plusElement(), f_plusElementOperator(), f_plusCollection(), f_plusArray()) + listOf(f_plusElement()) +
listOf(f_copyOf(), f_copyOfRange()) + f_plusElementOperator() +
listOf(f_plusCollection(), f_plusArray(), f_copyOf(), f_copyOfRange()) +
f_copyOfResized() + f_copyOfResized() +
f_sortPrimitives() + f_sortPrimitives() +
listOf(f_sort(), f_sortWith(), f_asList(), f_toTypedArray()) listOf(f_sort(), f_sortWith(), f_asList()) +
f_asListPrimitives() +
f_toTypedArray()
} }