提交 f076ff02 编写于 作者: A Alex Tkachman

KT-729 Need to support arrays as varargs

上级 7b7987ba
......@@ -1529,15 +1529,55 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Type type = asmType(outType);
assert type.getSort() == Type.ARRAY;
Type elementType = correctElementType(type);
int size = valueArgument.getArguments().size();
List<ValueArgument> arguments = valueArgument.getArguments();
int size = arguments.size();
v.iconst(valueArgument.getArguments().size());
v.newarray(elementType);
boolean hasSpread = false;
for(int i = 0; i != size; ++i) {
v.dup();
v.iconst(i);
gen(valueArgument.getArguments().get(i).getArgumentExpression(), elementType);
StackValue.arrayElement(elementType, false).store(v);
if(arguments.get(i).getSpreadElement() != null) {
hasSpread = true;
break;
}
}
if(hasSpread) {
if(size == 1) {
gen(arguments.get(0).getArgumentExpression(), type);
}
else {
String owner = "jet/runtime/Intrinsics$SpreadBuilder";
v.anew(Type.getObjectType(owner));
v.dup();
v.invokespecial(owner, "<init>", "()V");
for(int i = 0; i != size; ++i) {
v.dup();
ValueArgument argument = arguments.get(i);
if(argument.getSpreadElement() != null) {
gen(argument.getArgumentExpression(),JetTypeMapper.TYPE_OBJECT);
v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V");
}
else {
gen(argument.getArgumentExpression(), elementType);
v.invokevirtual(owner, "add", "(Ljava/lang/Object;)Z");
v.pop();
}
}
v.dup();
v.invokevirtual(owner, "size", "()I");
v.newarray(elementType);
v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;");
v.checkcast(type);
}
}
else {
v.iconst(arguments.size());
v.newarray(elementType);
for(int i = 0; i != size; ++i) {
v.dup();
v.iconst(i);
gen(arguments.get(i).getArgumentExpression(), elementType);
StackValue.arrayElement(elementType, false).store(v);
}
}
}
......
......@@ -54,6 +54,7 @@ public class JetTypeMapper {
public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing");
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder");
public static final Type JL_ARRAY_LIST = Type.getObjectType("java/util/ArrayList");
public static final Type JL_STRING_TYPE = Type.getObjectType("java/lang/String");
public static final Type JL_CHAR_SEQUENCE_TYPE = Type.getObjectType("java/lang/CharSequence");
private static final Type JL_COMPARABLE_TYPE = Type.getObjectType("java/lang/Comparable");
......
......@@ -16,8 +16,10 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* @author alex.tkachman
......@@ -94,4 +96,23 @@ public class VarArgTest extends CodegenTestCase {
public void testKt797() {
blackBoxFile("regressions/kt796_797.jet");
}
public void testArrayAsVararg () throws InvocationTargetException, IllegalAccessException {
loadText("private fun asList(vararg elems: String) = elems; fun test(ts: Array<String>) = asList(*ts); ");
//System.out.println(generateToText());
final Method main = generateFunction("test");
String[] args = {"mama", "papa"};
assertTrue(args == main.invoke(null, new Object[]{ args } ));
}
public void testArrayAsVararg2 () throws InvocationTargetException, IllegalAccessException {
loadText("private fun asList(vararg elems: String) = elems; fun test(ts1: Array<String>, ts2: String) = asList(*ts1, ts2); ");
System.out.println(generateToText());
final Method main = generateFunction("test");
Object invoke = main.invoke(null, new Object[] {new String[] {"mama"}, "papa" });
assertInstanceOf(invoke, String[].class);
assertEquals(2, Array.getLength(invoke));
assertEquals("mama", Array.get(invoke, 0));
assertEquals("papa", Array.get(invoke, 1));
}
}
......@@ -19,6 +19,8 @@ package jet.runtime;
import jet.Function0;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author alex.tkachman
......@@ -82,4 +84,36 @@ public class Intrinsics {
return sanitizeStackTrace(this);
}
}
public static class SpreadBuilder extends ArrayList {
public void addSpread(Object array) {
if(array != null) {
if(array instanceof Object[]) {
Object[] arr = (Object[]) array;
if(arr.length > 0) {
ensureCapacity(size() + arr.length);
for (int i = 0; i < arr.length; i++) {
add(arr[i]);
}
}
}
else if(array instanceof Collection) {
addAll((Collection) array);
}
else if(array instanceof Iterable) {
for(Iterator iterator = ((Iterable) array).iterator(); iterator.hasNext(); ) {
add(iterator.next());
}
}
else if(array instanceof Iterator) {
for(Iterator iterator = ((Iterator) array); iterator.hasNext(); ) {
add(iterator.next());
}
}
else {
throw new UnsupportedOperationException("Don't know how to spread " + array.getClass());
}
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册