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;
|
package org.jetbrains.k2js.translate.intrinsic;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
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.jet.lexer.JetToken;
|
||||||
import org.jetbrains.k2js.translate.intrinsic.array.*;
|
import org.jetbrains.k2js.translate.intrinsic.array.*;
|
||||||
import org.jetbrains.k2js.translate.intrinsic.primitive.*;
|
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 org.jetbrains.k2js.translate.utils.DescriptorUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
||||||
@@ -53,9 +57,31 @@ public final class Intrinsics {
|
|||||||
declareArrayIntrinsics();
|
declareArrayIntrinsics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void declareTuplesIntrinsics() {
|
||||||
|
for (int tupleSize = 0; tupleSize < JetStandardClasses.TUPLE_COUNT; ++tupleSize) {
|
||||||
|
declareTupleIntrinsics(tupleSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: provide generic mechanism or refactor
|
//TODO: provide generic mechanism or refactor
|
||||||
private void declareArrayIntrinsics() {
|
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");
|
FunctionDescriptor setFunction = getFunctionByName(arrayMemberScope, "set");
|
||||||
functionIntrinsics.put(setFunction, ArraySetIntrinsic.INSTANCE);
|
functionIntrinsics.put(setFunction, ArraySetIntrinsic.INSTANCE);
|
||||||
FunctionDescriptor getFunction = getFunctionByName(arrayMemberScope, "get");
|
FunctionDescriptor getFunction = getFunctionByName(arrayMemberScope, "get");
|
||||||
@@ -64,18 +90,20 @@ public final class Intrinsics {
|
|||||||
functionIntrinsics.put(sizeProperty.getGetter(), ArraySizeIntrinsic.INSTANCE);
|
functionIntrinsics.put(sizeProperty.getGetter(), ArraySizeIntrinsic.INSTANCE);
|
||||||
PropertyDescriptor indicesProperty = getPropertyByName(arrayMemberScope, "indices");
|
PropertyDescriptor indicesProperty = getPropertyByName(arrayMemberScope, "indices");
|
||||||
functionIntrinsics.put(indicesProperty.getGetter(), ArrayIndicesIntrinsic.INSTANCE);
|
functionIntrinsics.put(indicesProperty.getGetter(), ArrayIndicesIntrinsic.INSTANCE);
|
||||||
FunctionDescriptor nullArrayConstructor = getFunctionByName(library.getLibraryScope(), "Array");
|
|
||||||
functionIntrinsics.put(nullArrayConstructor, ArrayNullConstructorIntrinsic.INSTANCE);
|
|
||||||
FunctionDescriptor iteratorFunction = getFunctionByName(arrayMemberScope, "iterator");
|
FunctionDescriptor iteratorFunction = getFunctionByName(arrayMemberScope, "iterator");
|
||||||
functionIntrinsics.put(iteratorFunction, ArrayIteratorIntrinsic.INSTANCE);
|
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);
|
functionIntrinsics.put(arrayConstructor, ArrayFunctionConstructorIntrinsic.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareTuplesIntrinsics() {
|
private List<JetType> getLibraryArrayTypes() {
|
||||||
for (int tupleSize = 0; tupleSize < JetStandardClasses.TUPLE_COUNT; ++tupleSize) {
|
List<JetType> arrayTypes = Lists.newArrayList();
|
||||||
declareTupleIntrinsics(tupleSize);
|
for (PrimitiveType type : PrimitiveType.values()) {
|
||||||
|
arrayTypes.add(library.getPrimitiveArrayJetType(type));
|
||||||
}
|
}
|
||||||
|
arrayTypes.add(library.getArray().getDefaultType());
|
||||||
|
return arrayTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareTupleIntrinsics(int tupleSize) {
|
private void declareTupleIntrinsics(int tupleSize) {
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package org.jetbrains.k2js.translate.reference;
|
package org.jetbrains.k2js.translate.reference;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
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.util.AstUtil;
|
import com.google.dart.compiler.util.AstUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -89,6 +86,7 @@ public final class CallTranslator extends AbstractTranslator {
|
|||||||
return new CallTranslator(receiver, callee, arguments, resolvedCall, null, context);
|
return new CallTranslator(receiver, callee, arguments, resolvedCall, null, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: inspect dead code
|
||||||
@Nullable
|
@Nullable
|
||||||
private JsExpression translateCalleeIfExpressionAsFunction(@NotNull JetCallExpression callExpression) {
|
private JsExpression translateCalleeIfExpressionAsFunction(@NotNull JetCallExpression callExpression) {
|
||||||
//TODO: util
|
//TODO: util
|
||||||
@@ -102,28 +100,43 @@ public final class CallTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static List<JsExpression> translateArgumentsForCallExpression(@NotNull JetCallExpression callExpression,
|
private List<JsExpression> translateArgumentsForCallExpression(@NotNull JetCallExpression callExpression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
List<JsExpression> result = new ArrayList<JsExpression>();
|
List<JsExpression> result = new ArrayList<JsExpression>();
|
||||||
ResolvedCall<?> resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression);
|
ResolvedCall<?> resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression);
|
||||||
Map<ValueParameterDescriptor, ResolvedValueArgument> formalToActualArguments = resolvedCall.getValueArguments();
|
Map<ValueParameterDescriptor, ResolvedValueArgument> formalToActualArguments = resolvedCall.getValueArguments();
|
||||||
for (ValueParameterDescriptor parameterDescriptor : resolvedCall.getResultingDescriptor().getValueParameters()) {
|
for (ValueParameterDescriptor parameterDescriptor : resolvedCall.getResultingDescriptor().getValueParameters()) {
|
||||||
JetExpression argument = getActualArgument(formalToActualArguments, parameterDescriptor, context);
|
ResolvedValueArgument actualArgument = formalToActualArguments.get(parameterDescriptor);
|
||||||
result.add(Translation.translateAsExpression(argument, context));
|
result.add(translateSingleArgument(actualArgument, parameterDescriptor));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: refactor
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JetExpression getActualArgument(
|
private JsExpression translateSingleArgument(@NotNull ResolvedValueArgument actualArgument,
|
||||||
@NotNull Map<ValueParameterDescriptor, ResolvedValueArgument> formalToActualArguments,
|
@NotNull ValueParameterDescriptor parameterDescriptor) {
|
||||||
@NotNull ValueParameterDescriptor parameterDescriptor, @NotNull TranslationContext context) {
|
List<JetExpression> argumentExpressions = actualArgument.getArgumentExpressions();
|
||||||
ResolvedValueArgument actualArgument = formalToActualArguments.get(parameterDescriptor);
|
if (actualArgument instanceof VarargValueArgument) {
|
||||||
if (actualArgument instanceof DefaultValueArgument) {
|
return translateVarargArgument(argumentExpressions);
|
||||||
return getDefaultArgument(context.bindingContext(), parameterDescriptor);
|
|
||||||
} else {
|
|
||||||
return getExpressionArgument(actualArgument);
|
|
||||||
}
|
}
|
||||||
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
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.JetToken;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
*/
|
*/
|
||||||
@@ -94,12 +91,4 @@ public final class PsiUtils {
|
|||||||
assert loopParameter != null;
|
assert loopParameter != null;
|
||||||
return loopParameter;
|
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");
|
testFooBoxIsTrue("expressionAsFunction.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void vararg() throws Exception {
|
||||||
|
testFooBoxIsTrue("vararg.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void kt921() throws Exception {
|
public void kt921() throws Exception {
|
||||||
try {
|
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