Vararg parameters in functions supported

This commit is contained in:
Pavel Talanov
2012-01-31 21:26:36 +04:00
parent 52344103d6
commit 562c0c7fe7
6 changed files with 769 additions and 334 deletions
+683 -300
View File
File diff suppressed because it is too large Load Diff
@@ -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<JetType> 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<JetType> getLibraryArrayTypes() {
List<JetType> 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) {
@@ -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<JsExpression> translateArgumentsForCallExpression(@NotNull JetCallExpression callExpression,
@NotNull TranslationContext context) {
private List<JsExpression> translateArgumentsForCallExpression(@NotNull JetCallExpression callExpression,
@NotNull TranslationContext context) {
List<JsExpression> result = new ArrayList<JsExpression>();
ResolvedCall<?> resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression);
Map<ValueParameterDescriptor, ResolvedValueArgument> 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<ValueParameterDescriptor, ResolvedValueArgument> 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<JetExpression> 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<JetExpression> arguments) {
JsArrayLiteral varargArgument = new JsArrayLiteral();
for (JetExpression argument : arguments) {
varargArgument.getExpressions().add(Translation.translateAsExpression(argument, context));
}
return varargArgument;
}
}
@@ -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<JetExpression> argumentExpressions = actualArgument.getArgumentExpressions();
assert !argumentExpressions.isEmpty() : "Actual arguments must be supplied.";
assert argumentExpressions.size() == 1 : "Varargs not supported.";
return argumentExpressions.get(0);
}
}
@@ -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 {
@@ -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)