From 562c0c7fe7a76771f3a664b9f647a96324a552a3 Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Tue, 31 Jan 2012 21:26:36 +0400 Subject: [PATCH] Vararg parameters in functions supported --- .idea/workspace.xml | 983 ++++++++++++------ .../k2js/translate/intrinsic/Intrinsics.java | 42 +- .../translate/reference/CallTranslator.java | 45 +- .../k2js/translate/utils/PsiUtils.java | 11 - .../org/jetbrains/k2js/test/FunctionTest.java | 5 + .../expression/function/cases/vararg.kt | 17 + 6 files changed, 769 insertions(+), 334 deletions(-) create mode 100644 translator/testFiles/expression/function/cases/vararg.kt diff --git a/.idea/workspace.xml b/.idea/workspace.xml index ae69769127e..fcb3a30f1f9 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -13,20 +13,12 @@ - - - - + - - - - - - - - + + + @@ -71,7 +63,7 @@ - + - + + + + + - + - + - + + + + + + MODULES + mdl-translator + + mdl-frontend + mdl-js + mdl-backend + mdl-translator + mdl-frontend.java + mdl-cli + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -184,24 +296,6 @@ - - - - - - - - - - - - - - - - - - @@ -214,7 +308,16 @@ - + + + + + + + + + + @@ -251,97 +354,100 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -372,11 +478,6 @@ @@ -826,6 +932,86 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1391,6 +1705,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1764,98 +2146,13 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1863,23 +2160,109 @@ - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java index fcee3e53773..428985f3838 100644 --- a/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java @@ -1,11 +1,14 @@ package org.jetbrains.k2js.translate.intrinsic; +import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardLibrary; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.PrimitiveType; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.k2js.translate.intrinsic.array.*; import org.jetbrains.k2js.translate.intrinsic.primitive.*; @@ -15,6 +18,7 @@ import org.jetbrains.k2js.translate.operation.OperatorTable; import org.jetbrains.k2js.translate.utils.DescriptorUtils; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*; @@ -53,9 +57,31 @@ public final class Intrinsics { declareArrayIntrinsics(); } + private void declareTuplesIntrinsics() { + for (int tupleSize = 0; tupleSize < JetStandardClasses.TUPLE_COUNT; ++tupleSize) { + declareTupleIntrinsics(tupleSize); + } + } + //TODO: provide generic mechanism or refactor private void declareArrayIntrinsics() { - JetScope arrayMemberScope = library.getArray().getDefaultType().getMemberScope(); + + List arrayTypes = getLibraryArrayTypes(); + + for (JetType arrayType : arrayTypes) { + declareIntrinsicsForArrayType(arrayType); + } + declareNullConstructorIntrinsic(); + } + + private void declareNullConstructorIntrinsic() { + FunctionDescriptor nullArrayConstructor = getFunctionByName(library.getLibraryScope(), "Array"); + functionIntrinsics.put(nullArrayConstructor, ArrayNullConstructorIntrinsic.INSTANCE); + } + + //TODO: some dangerous operation unchecked here + private void declareIntrinsicsForArrayType(@NotNull JetType arrayType) { + JetScope arrayMemberScope = arrayType.getMemberScope(); FunctionDescriptor setFunction = getFunctionByName(arrayMemberScope, "set"); functionIntrinsics.put(setFunction, ArraySetIntrinsic.INSTANCE); FunctionDescriptor getFunction = getFunctionByName(arrayMemberScope, "get"); @@ -64,18 +90,20 @@ public final class Intrinsics { functionIntrinsics.put(sizeProperty.getGetter(), ArraySizeIntrinsic.INSTANCE); PropertyDescriptor indicesProperty = getPropertyByName(arrayMemberScope, "indices"); functionIntrinsics.put(indicesProperty.getGetter(), ArrayIndicesIntrinsic.INSTANCE); - FunctionDescriptor nullArrayConstructor = getFunctionByName(library.getLibraryScope(), "Array"); - functionIntrinsics.put(nullArrayConstructor, ArrayNullConstructorIntrinsic.INSTANCE); FunctionDescriptor iteratorFunction = getFunctionByName(arrayMemberScope, "iterator"); functionIntrinsics.put(iteratorFunction, ArrayIteratorIntrinsic.INSTANCE); - ConstructorDescriptor arrayConstructor = library.getArray().getConstructors().iterator().next(); + ConstructorDescriptor arrayConstructor = + ((ClassDescriptor) arrayMemberScope.getContainingDeclaration()).getConstructors().iterator().next(); functionIntrinsics.put(arrayConstructor, ArrayFunctionConstructorIntrinsic.INSTANCE); } - private void declareTuplesIntrinsics() { - for (int tupleSize = 0; tupleSize < JetStandardClasses.TUPLE_COUNT; ++tupleSize) { - declareTupleIntrinsics(tupleSize); + private List getLibraryArrayTypes() { + List arrayTypes = Lists.newArrayList(); + for (PrimitiveType type : PrimitiveType.values()) { + arrayTypes.add(library.getPrimitiveArrayJetType(type)); } + arrayTypes.add(library.getArray().getDefaultType()); + return arrayTypes; } private void declareTupleIntrinsics(int tupleSize) { diff --git a/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java index 009d92fcb9a..6b67b25ee5e 100644 --- a/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java @@ -1,9 +1,6 @@ package org.jetbrains.k2js.translate.reference; -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsInvocation; -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import com.google.dart.compiler.backend.js.ast.JsNew; +import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -89,6 +86,7 @@ public final class CallTranslator extends AbstractTranslator { return new CallTranslator(receiver, callee, arguments, resolvedCall, null, context); } + //TODO: inspect dead code @Nullable private JsExpression translateCalleeIfExpressionAsFunction(@NotNull JetCallExpression callExpression) { //TODO: util @@ -102,28 +100,43 @@ public final class CallTranslator extends AbstractTranslator { } @NotNull - private static List translateArgumentsForCallExpression(@NotNull JetCallExpression callExpression, - @NotNull TranslationContext context) { + private List translateArgumentsForCallExpression(@NotNull JetCallExpression callExpression, + @NotNull TranslationContext context) { List result = new ArrayList(); ResolvedCall resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression); Map formalToActualArguments = resolvedCall.getValueArguments(); for (ValueParameterDescriptor parameterDescriptor : resolvedCall.getResultingDescriptor().getValueParameters()) { - JetExpression argument = getActualArgument(formalToActualArguments, parameterDescriptor, context); - result.add(Translation.translateAsExpression(argument, context)); + ResolvedValueArgument actualArgument = formalToActualArguments.get(parameterDescriptor); + result.add(translateSingleArgument(actualArgument, parameterDescriptor)); } return result; } + + //TODO: refactor @NotNull - private static JetExpression getActualArgument( - @NotNull Map formalToActualArguments, - @NotNull ValueParameterDescriptor parameterDescriptor, @NotNull TranslationContext context) { - ResolvedValueArgument actualArgument = formalToActualArguments.get(parameterDescriptor); - if (actualArgument instanceof DefaultValueArgument) { - return getDefaultArgument(context.bindingContext(), parameterDescriptor); - } else { - return getExpressionArgument(actualArgument); + private JsExpression translateSingleArgument(@NotNull ResolvedValueArgument actualArgument, + @NotNull ValueParameterDescriptor parameterDescriptor) { + List argumentExpressions = actualArgument.getArgumentExpressions(); + if (actualArgument instanceof VarargValueArgument) { + return translateVarargArgument(argumentExpressions); } + if (actualArgument instanceof DefaultValueArgument) { + JetExpression defaultArgument = getDefaultArgument(context.bindingContext(), parameterDescriptor); + return Translation.translateAsExpression(defaultArgument, context); + } + assert actualArgument instanceof ExpressionValueArgument; + assert argumentExpressions.size() == 1; + return Translation.translateAsExpression(argumentExpressions.get(0), context); + } + + @NotNull + private JsExpression translateVarargArgument(@NotNull List arguments) { + JsArrayLiteral varargArgument = new JsArrayLiteral(); + for (JetExpression argument : arguments) { + varargArgument.getExpressions().add(Translation.translateAsExpression(argument, context)); + } + return varargArgument; } } diff --git a/translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java b/translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java index f23a6846164..ba459b4ceda 100644 --- a/translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java +++ b/translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java @@ -4,12 +4,9 @@ import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; -import java.util.List; - /** * @author Pavel Talanov */ @@ -94,12 +91,4 @@ public final class PsiUtils { assert loopParameter != null; return loopParameter; } - - @NotNull - public static JetExpression getExpressionArgument(@NotNull ResolvedValueArgument actualArgument) { - List argumentExpressions = actualArgument.getArgumentExpressions(); - assert !argumentExpressions.isEmpty() : "Actual arguments must be supplied."; - assert argumentExpressions.size() == 1 : "Varargs not supported."; - return argumentExpressions.get(0); - } } diff --git a/translator/test/org/jetbrains/k2js/test/FunctionTest.java b/translator/test/org/jetbrains/k2js/test/FunctionTest.java index c1d6245dfe0..e03f4cd3dcb 100644 --- a/translator/test/org/jetbrains/k2js/test/FunctionTest.java +++ b/translator/test/org/jetbrains/k2js/test/FunctionTest.java @@ -84,6 +84,11 @@ public class FunctionTest extends AbstractExpressionTest { testFooBoxIsTrue("expressionAsFunction.kt"); } + @Test + public void vararg() throws Exception { + testFooBoxIsTrue("vararg.kt"); + } + @Test public void kt921() throws Exception { try { diff --git a/translator/testFiles/expression/function/cases/vararg.kt b/translator/testFiles/expression/function/cases/vararg.kt new file mode 100644 index 00000000000..d3ab09ec173 --- /dev/null +++ b/translator/testFiles/expression/function/cases/vararg.kt @@ -0,0 +1,17 @@ +package foo + +fun testSize(expectedSize : Int, vararg i : Int) : Boolean { + return (i.size == expectedSize) +} + +fun testSum(expectedSum : Int, vararg i : Int) : Boolean { + var sum = 0 + for (j in i) { + sum += j + } + + return (expectedSum == sum) +} + +fun box() = testSize(0) && testSum(0) && testSize(3, 1, 1, 1) && testSum(3, 1, 1, 1) && testSize(6, 1, 1, 1, 2, 3, 4) && + testSum(30, 10, 20, 0) \ No newline at end of file