Vararg parameters in functions supported
This commit is contained in:
Generated
+683
-300
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)
|
||||
Reference in New Issue
Block a user