JS: support unsigned primitive vararg's
This commit is contained in:
committed by
Ilya Gorbunov
parent
944c5b6044
commit
934e11aa60
+1
-1
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
+5
@@ -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");
|
||||||
|
|||||||
+5
@@ -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");
|
||||||
|
|||||||
+26
@@ -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());
|
||||||
|
|||||||
+31
-5
@@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+73
-48
@@ -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"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user