KT-729 Need to support arrays as varargs
This commit is contained in:
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user