JS: support unsigned primitive vararg's

This commit is contained in:
Anton Bannykh
2018-08-17 13:21:01 +03:00
committed by Ilya Gorbunov
parent 944c5b6044
commit 934e11aa60
9 changed files with 255 additions and 56 deletions
@@ -60,7 +60,7 @@ abstract class FunctionsFromAnyGenerator(protected val declaration: KtClassOrObj
generateEqualsMethod(function, properties) generateEqualsMethod(function, properties)
} }
private val primaryConstructorProperties: List<PropertyDescriptor> protected val primaryConstructorProperties: List<PropertyDescriptor>
get() = primaryConstructorParameters get() = primaryConstructorParameters
.filter { it.hasValOrVar() } .filter { it.hasValOrVar() }
.map { bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it)!! } .map { bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it)!! }
@@ -1,7 +1,6 @@
// WITH_UNSIGNED // WITH_UNSIGNED
// IGNORE_BACKEND: JVM_IR // IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS
fun box(): String { fun box(): String {
var sum = 0u var sum = 0u
@@ -1,6 +1,6 @@
// IGNORE_BACKEND: JVM_IR // IGNORE_BACKEND: JVM_IR
// WITH_UNSIGNED // WITH_UNSIGNED
// IGNORE_BACKEND: JS, JS_IR // IGNORE_BACKEND: JS_IR
fun uint(vararg us: UInt): UIntArray = us fun uint(vararg us: UInt): UIntArray = us
@@ -2495,6 +2495,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
runTest("js/js.translator/testData/box/expression/function/vararg.kt"); runTest("js/js.translator/testData/box/expression/function/vararg.kt");
} }
@TestMetadata("varargUInt.kt")
public void testVarargUInt() throws Exception {
runTest("js/js.translator/testData/box/expression/function/varargUInt.kt");
}
@TestMetadata("whenFunction.kt") @TestMetadata("whenFunction.kt")
public void testWhenFunction() throws Exception { public void testWhenFunction() throws Exception {
runTest("js/js.translator/testData/box/expression/function/whenFunction.kt"); runTest("js/js.translator/testData/box/expression/function/whenFunction.kt");
@@ -2495,6 +2495,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
runTest("js/js.translator/testData/box/expression/function/vararg.kt"); runTest("js/js.translator/testData/box/expression/function/vararg.kt");
} }
@TestMetadata("varargUInt.kt")
public void testVarargUInt() throws Exception {
runTest("js/js.translator/testData/box/expression/function/varargUInt.kt");
}
@TestMetadata("whenFunction.kt") @TestMetadata("whenFunction.kt")
public void testWhenFunction() throws Exception { public void testWhenFunction() throws Exception {
runTest("js/js.translator/testData/box/expression/function/whenFunction.kt"); runTest("js/js.translator/testData/box/expression/function/whenFunction.kt");
@@ -18,13 +18,18 @@ package org.jetbrains.kotlin.js.translate.declaration;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator; import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.js.backend.ast.*; import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.translate.context.Namer; import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.UtilsKt; import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.KtClassOrObject; import org.jetbrains.kotlin.psi.KtClassOrObject;
import org.jetbrains.kotlin.psi.KtParameter; import org.jetbrains.kotlin.psi.KtParameter;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
@@ -49,6 +54,15 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
this.isInline = isInline; this.isInline = isInline;
} }
@Override
public void generate() {
if (isInline) {
generateUnboxFunction();
}
super.generate();
}
@Override @Override
public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull ValueParameterDescriptor parameter) { public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull ValueParameterDescriptor parameter) {
if (isInline) return; if (isInline) return;
@@ -213,6 +227,18 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
functionObj.getBody().getStatements().add(returnStatement); functionObj.getBody().getStatements().add(returnStatement);
} }
private void generateUnboxFunction() {
PropertyDescriptor boxee = getPrimaryConstructorProperties().get(0);
JsFunction unboxFunction = context.createRootScopedFunction("unbox");
JsExpression prototypeRef = JsAstUtils.prototypeOf(context.getInnerReference(getClassDescriptor()));
JsExpression functionRef = new JsNameRef("unbox", prototypeRef);
unboxFunction.getBody().getStatements().add(new JsReturn(JsAstUtils.pureFqn(context.getNameForDescriptor(boxee), new JsThisRef())));
context.addDeclarationStatement(JsAstUtils.assignment(functionRef, unboxFunction).makeStmt());
}
private JsFunction generateJsMethod(@NotNull FunctionDescriptor functionDescriptor) { private JsFunction generateJsMethod(@NotNull FunctionDescriptor functionDescriptor) {
JsFunction functionObject = context.createRootScopedFunction(functionDescriptor); JsFunction functionObject = context.createRootScopedFunction(functionDescriptor);
functionObject.setSource(getDeclaration()); functionObject.setSource(getDeclaration());
@@ -40,6 +40,8 @@ import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntri
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.inline.InlineStrategy import org.jetbrains.kotlin.resolve.inline.InlineStrategy
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.types.KotlinType
import java.util.* import java.util.*
object ArrayFIF : CompositeFIF() { object ArrayFIF : CompositeFIF() {
@@ -64,14 +66,38 @@ object ArrayFIF : CompositeFIF() {
@JvmStatic @JvmStatic
fun typedArraysEnabled(config: JsConfig) = config.configuration.get(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, true) fun typedArraysEnabled(config: JsConfig) = config.configuration.get(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, true)
fun castOrCreatePrimitiveArray(ctx: TranslationContext, type: PrimitiveType?, arg: JsArrayLiteral): JsExpression { fun unsignedPrimitiveToSigned(type: KotlinType): PrimitiveType? {
if (type == null || !typedArraysEnabled(ctx.config)) return arg // short-circuit
if (!type.isInlineClassType() || type.isMarkedNullable) return null
return if (type in TYPED_ARRAY_MAP) { return when {
createTypedArray(type, arg) KotlinBuiltIns.isUByte(type) -> BYTE
KotlinBuiltIns.isUShort(type) -> SHORT
KotlinBuiltIns.isUInt(type) -> INT
KotlinBuiltIns.isULong(type) -> LONG
else -> null
}
}
fun castOrCreatePrimitiveArray(ctx: TranslationContext, type: KotlinType, arg: JsArrayLiteral): JsExpression {
if (type.isMarkedNullable) return arg
val unsignedPrimitiveType = unsignedPrimitiveToSigned(type)
if (unsignedPrimitiveType != null) {
val conversionFunction = "to${unsignedPrimitiveType.typeName}"
arg.expressions.replaceAll { JsInvocation(JsNameRef(conversionFunction, it)) }
}
val primitiveType = unsignedPrimitiveType ?: KotlinBuiltIns.getPrimitiveType(type)?.takeUnless { type.isMarkedNullable}
if (primitiveType == null || !typedArraysEnabled(ctx.config)) return arg
return if (primitiveType in TYPED_ARRAY_MAP) {
createTypedArray(primitiveType, arg)
} }
else { else {
JsAstUtils.invokeKotlinFunction(type.lowerCaseName + "ArrayOf", *arg.expressions.toTypedArray()) JsAstUtils.invokeKotlinFunction(primitiveType.lowerCaseName + "ArrayOf", *arg.expressions.toTypedArray())
} }
} }
@@ -5,12 +5,13 @@
package org.jetbrains.kotlin.js.translate.reference package org.jetbrains.kotlin.js.translate.reference
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.builtins.getFunctionalClassKind import org.jetbrains.kotlin.builtins.getFunctionalClassKind
import org.jetbrains.kotlin.descriptors.ClassDescriptor
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.incremental.components.NoLookupLocation
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
@@ -25,6 +26,8 @@ import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.js.translate.utils.getReferenceToJsClass import org.jetbrains.kotlin.js.translate.utils.getReferenceToJsClass
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.calls.components.isVararg
@@ -33,6 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
import java.util.* import java.util.*
class CallArgumentTranslator private constructor( class CallArgumentTranslator private constructor(
@@ -77,7 +81,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 varargPrimitiveType: PrimitiveType? = null var varargElementType: KotlinType? = null
for (parameterDescriptor in valueParameters) { for (parameterDescriptor in valueParameters) {
val actualArgument = valueArgumentsByIndex[parameterDescriptor.index] val actualArgument = valueArgumentsByIndex[parameterDescriptor.index]
@@ -90,8 +94,7 @@ class CallArgumentTranslator private constructor(
hasSpreadOperator = arguments.any { it.getSpreadElement() != null } hasSpreadOperator = arguments.any { it.getSpreadElement() != null }
} }
val varargElementType = parameterDescriptor.original.varargElementType!! varargElementType = parameterDescriptor.original.varargElementType!!
varargPrimitiveType = KotlinBuiltIns.getPrimitiveType(varargElementType).takeUnless { varargElementType.isMarkedNullable }
if (hasSpreadOperator) { if (hasSpreadOperator) {
if (isNativeFunctionCall) { if (isNativeFunctionCall) {
@@ -102,10 +105,10 @@ class CallArgumentTranslator private constructor(
null) null)
} }
else { else {
result.addAll(translateVarargArgument(actualArgument, translateVarargArgument(actualArgument,
argsToJsExpr, argsToJsExpr,
actualArgument.arguments.size > 1, actualArgument.arguments.size > 1,
varargPrimitiveType)) varargElementType)?.let { result.add(it) }
} }
} }
else { else {
@@ -113,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, varargPrimitiveType)) translateVarargArgument(actualArgument, argsToJsExpr, true, varargElementType)?.let { result.add(it) }
} }
} }
} }
@@ -134,7 +137,7 @@ class CallArgumentTranslator private constructor(
concatArguments!!.add(0, toArray(null, argsBeforeVararg)) concatArguments!!.add(0, toArray(null, argsBeforeVararg))
} }
result = mutableListOf(concatArgumentsIfNeeded(concatArguments!!, varargPrimitiveType, true)) result = mutableListOf(concatArgumentsIfNeeded(concatArguments!!, varargElementType, true))
if (receiver != null) { if (receiver != null) {
cachedReceiver = context().getOrDeclareTemporaryConstVariable(receiver) cachedReceiver = context().getOrDeclareTemporaryConstVariable(receiver)
@@ -207,44 +210,64 @@ class CallArgumentTranslator private constructor(
return result return result
} }
// Cache UTypeArray descriptor lookup
private val typeToUTypeArray = mutableMapOf<PrimitiveType, ClassDescriptor>()
private fun JsExpression.wrapInUArray(elementType: KotlinType): JsExpression {
return ArrayFIF.unsignedPrimitiveToSigned(elementType)?.let { primitiveType ->
val kotlinMemberScope = context.currentModule.getPackage(FqNameUnsafe("kotlin").toSafe()).memberScope
val classDescriptor = typeToUTypeArray.computeIfAbsent(primitiveType) {
val className = Name.identifier("U${primitiveType.typeName}Array")
kotlinMemberScope.getContributedClassifier(className, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
}
JsNew(ReferenceTranslator.translateAsTypeReference(classDescriptor, context), listOf(this))
} ?: this
}
private fun translateVarargArgument( private fun translateVarargArgument(
resolvedArgument: ResolvedValueArgument, resolvedArgument: ResolvedValueArgument,
translatedArgs: Map<ValueArgument, JsExpression>, translatedArgs: Map<ValueArgument, JsExpression>,
shouldWrapVarargInArray: Boolean, shouldWrapVarargInArray: Boolean,
varargPrimitiveType: PrimitiveType? varargElementType: KotlinType
): List<JsExpression> { ): JsExpression? {
val arguments = resolvedArgument.arguments val arguments = resolvedArgument.arguments
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
return if (shouldWrapVarargInArray) { return if (shouldWrapVarargInArray) {
return listOf(toArray(varargPrimitiveType, listOf())) return toArray(varargElementType, listOf()).wrapInUArray(varargElementType)
} } else {
else { null
listOf()
} }
} }
val list = translateResolvedArgument(resolvedArgument, translatedArgs) val list = translateResolvedArgument(resolvedArgument, translatedArgs)
return if (shouldWrapVarargInArray) { return if (shouldWrapVarargInArray) {
val concatArguments = prepareConcatArguments(arguments, list, varargPrimitiveType) val concatArguments = prepareConcatArguments(arguments, list, varargElementType)
val concatExpression = concatArgumentsIfNeeded(concatArguments, varargPrimitiveType, false) val concatExpression = concatArgumentsIfNeeded(concatArguments, varargElementType, false)
listOf(concatExpression) concatExpression
} } else {
else { val arg = ArrayFIF.unsignedPrimitiveToSigned(varargElementType)?.let {type ->
listOf(JsAstUtils.invokeMethod(list[0], "slice")) JsInvocation(JsNameRef("unbox", list[0]))
} } ?: list[0]
JsAstUtils.invokeMethod(arg, "slice")
}.wrapInUArray(varargElementType)
} }
private fun toArray(varargPrimitiveType: PrimitiveType?, elements: List<JsExpression>): JsExpression { private fun toArray(varargElementType: KotlinType?, elements: List<JsExpression>): JsExpression {
return ArrayFIF.castOrCreatePrimitiveArray(context(), val argument = JsArrayLiteral(elements).apply { sideEffects = SideEffectKind.PURE }
varargPrimitiveType,
JsArrayLiteral(elements).apply { sideEffects = SideEffectKind.PURE }) if (varargElementType == null) return argument
return ArrayFIF.castOrCreatePrimitiveArray(
context(),
varargElementType,
argument)
} }
private fun prepareConcatArguments( private fun prepareConcatArguments(
arguments: List<ValueArgument>, arguments: List<ValueArgument>,
list: List<JsExpression>, list: List<JsExpression>,
varargPrimitiveType: PrimitiveType? varargElementType: KotlinType?
): MutableList<JsExpression> { ): MutableList<JsExpression> {
assert(arguments.isNotEmpty()) { "arguments.size should not be 0" } assert(arguments.isNotEmpty()) { "arguments.size should not be 0" }
assert(arguments.size == list.size) { "arguments.size: " + arguments.size + " != list.size: " + list.size } assert(arguments.size == list.size) { "arguments.size: " + arguments.size + " != list.size: " + list.size }
@@ -259,17 +282,19 @@ class CallArgumentTranslator private constructor(
if (valueArgument.getSpreadElement() != null) { if (valueArgument.getSpreadElement() != null) {
if (lastArrayContent.size > 0) { if (lastArrayContent.size > 0) {
concatArguments.add(toArray(varargPrimitiveType, lastArrayContent)) concatArguments.add(toArray(varargElementType, lastArrayContent))
lastArrayContent = mutableListOf() lastArrayContent = mutableListOf()
} }
concatArguments.add(expressionArgument) val e = if (varargElementType != null && ArrayFIF.unsignedPrimitiveToSigned(varargElementType) != null) {
} JsInvocation(JsNameRef("unbox", expressionArgument))
else { } else expressionArgument
concatArguments.add(e)
} else {
lastArrayContent.add(expressionArgument) lastArrayContent.add(expressionArgument)
} }
} }
if (lastArrayContent.size > 0) { if (lastArrayContent.size > 0) {
concatArguments.add(toArray(varargPrimitiveType, lastArrayContent)) concatArguments.add(toArray(varargElementType, lastArrayContent))
} }
return concatArguments return concatArguments
@@ -306,23 +331,23 @@ class CallArgumentTranslator private constructor(
} }
private fun concatArgumentsIfNeeded( private fun concatArgumentsIfNeeded(
concatArguments: List<JsExpression>, concatArguments: List<JsExpression>,
varargPrimitiveType: PrimitiveType?, varargElementType: KotlinType?,
isMixed: Boolean isMixed: Boolean
): JsExpression { ): JsExpression {
assert(concatArguments.isNotEmpty()) { "concatArguments.size should not be 0" } assert(concatArguments.isNotEmpty()) { "concatArguments.size should not be 0" }
return if (concatArguments.size > 1) { return if (concatArguments.size > 1) {
if (varargPrimitiveType != null) { if (varargElementType != null && (varargElementType.isPrimitiveNumberType() || ArrayFIF.unsignedPrimitiveToSigned(varargElementType) != null)) {
val method = if (isMixed) "arrayConcat" else "primitiveArrayConcat" val method = if (isMixed) "arrayConcat" else "primitiveArrayConcat"
JsAstUtils.invokeKotlinFunction(method, concatArguments[0], JsAstUtils.invokeKotlinFunction(
*concatArguments.subList(1, concatArguments.size).toTypedArray()) method, concatArguments[0],
} *concatArguments.subList(1, concatArguments.size).toTypedArray()
else { )
} else {
JsInvocation(JsNameRef("concat", concatArguments[0]), concatArguments.subList(1, concatArguments.size)) JsInvocation(JsNameRef("concat", concatArguments[0]), concatArguments.subList(1, concatArguments.size))
} }
} } else {
else {
concatArguments[0] concatArguments[0]
} }
} }
@@ -0,0 +1,113 @@
// LANGUAGE_VERSION: 1.3
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1566
package foo
fun testSize(expectedSize: Int, vararg i: UInt): Boolean {
return (i.size == expectedSize)
}
fun testSum(expectedSum: UInt, vararg i: UInt): Boolean {
var sum = 0u
for (j in i) {
sum += j
}
return (expectedSum == sum)
}
fun testSpreadOperator(vararg args: UInt): Boolean {
var sum = 0u
for (a in args) sum += a
return testSize(args.size, *args) && testSum(sum, *args)
}
class Bar(val size: Int, val sum: UInt) {
fun test(vararg args: UInt) = testSize(size, *args) && testSum(sum, *args)
}
object obj {
fun test(size: Int, sum: UInt, vararg args: UInt) = testSize(size, *args) && testSum(sum, *args)
}
fun spreadInMethodCall(size: Int, sum: UInt, vararg args: UInt) = Bar(size, sum).test(*args)
fun spreadInObjectMethodCall(size: Int, sum: UInt, vararg args: UInt) = obj.test(size, sum, *args)
fun testVarargWithFunLit(vararg args: UInt, f: (a: UIntArray) -> Boolean): Boolean = f(args)
fun <T> idVarArgs(vararg a: T) = a
fun <T> idArrayVarArg(vararg a: Array<T>) = a
fun sumFunValuesOnParameters(x: UInt, y: UInt, vararg a: UInt, f: (UInt) -> UInt): UInt {
var result = f(x) + f(y)
for(u in a) {
result += f(u)
}
return result
}
fun box(): String {
if (!testSize(0))
return "wrong vararg size when call function without args"
if (!testSum(0u))
return "wrong vararg sum (arguments) when call function without args"
if (!testSize(6, 1u, 1u, 1u, 2u, 3u, 4u))
return "wrong vararg size when call function with some args (1)"
if (!testSum(30, 10u, 20u, 0u))
return "wrong vararg sum (arguments) when call function with some args (1)"
if (!testSpreadOperator(30u, 10u, 20u, 0u))
return "failed when call function using spread operator"
if (!Bar(3, 30u).test(10u, 20u, 0u))
return "failed when call method"
if (!spreadInMethodCall(2, 3u, 1u, 2u))
return "failed when call method using spread operator"
if (!obj.test(5, 15u, 1u, 2u, 3u, 4u, 5u))
return "failed when call method of object"
if (!spreadInObjectMethodCall(2, 3u, 1u, 2u))
return "failed when call method of object using spread operator"
if (!testVarargWithFunLit(1u, 2u, 3u) { args -> args.size == 3 })
return "failed when call function with vararg and fun literal"
val a = arrayOf(1u, 2u, 3u)
val b = arrayOf(4u, 5u)
assertEquals(5, arrayOf(*a, *b).size)
assertEquals(8, arrayOf(10u, *a, 20u, *b, 30u).size)
assertEquals(5, idVarArgs(*a, *b).size)
assertEquals(8, idVarArgs(10u, *a, 20u, *b, 30u).size)
assertEquals(9, arrayOf(1u, *a, *a, 1u, 2u).size)
assertEquals(9, idVarArgs(1u, *a, *a, 1u, 2u).size)
assertEquals(9, arrayOf(1u, *a, *arrayOf(1u, 2u, 3u), 1u, 2u).size)
assertEquals(9, idVarArgs(1u, *a, *arrayOf(1u, 2u, 3u), 1u, 2u).size)
assertEquals(90u, sumFunValuesOnParameters(1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u) { 2u*it })
assertEquals(90u, sumFunValuesOnParameters(1u, 2u, *uintArrayOf(3u, 4u, 5u, 6u, 7u, 8u, 9u)) { 2u*it })
assertEquals(90u, sumFunValuesOnParameters(1u, 2u, 3u, 4u, *uintArrayOf(5u, 6u, 7u, 8u, 9u)) { 2u*it })
assertEquals(90u, sumFunValuesOnParameters(1u, 2u, *uintArrayOf(3u, 4u, 5u, 6u, 7u), 8u, 9u) { 2u*it })
assertEquals(90u, sumFunValuesOnParameters(1u, 2u, *uintArrayOf(3u, 4u, 5u), *uintArrayOf(6u, 7u, 8u, 9u)) { 2u*it })
assertEquals(90u, sumFunValuesOnParameters(1u, 2u, *uintArrayOf(3u, 4u), 5u, 6u, *uintArrayOf(7u, 8u, 9u)) { 2u*it })
assertEquals(2, idArrayVarArg(arrayOf(1u), *arrayOf(arrayOf(2u, 3u, 4u))).size)
assertEquals(3, idArrayVarArg(arrayOf(1u, 2u), *arrayOf(arrayOf(3u, 4u), arrayOf(5u, 6u))).size)
assertEquals(6, idArrayVarArg(arrayOf(1u, 2u), *arrayOf(arrayOf(3u, 4u), arrayOf(5u, 6u)), arrayOf(7u), *arrayOf(arrayOf(8u, 9u), arrayOf(10u, 11u))).size)
val c = arrayOf(*a)
assertFalse(a === c, "Spread operator should copy its argument")
return "OK"
}