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);
|
Type type = asmType(outType);
|
||||||
assert type.getSort() == Type.ARRAY;
|
assert type.getSort() == Type.ARRAY;
|
||||||
Type elementType = correctElementType(type);
|
Type elementType = correctElementType(type);
|
||||||
int size = valueArgument.getArguments().size();
|
List<ValueArgument> arguments = valueArgument.getArguments();
|
||||||
|
int size = arguments.size();
|
||||||
|
|
||||||
v.iconst(valueArgument.getArguments().size());
|
boolean hasSpread = false;
|
||||||
v.newarray(elementType);
|
|
||||||
for(int i = 0; i != size; ++i) {
|
for(int i = 0; i != size; ++i) {
|
||||||
v.dup();
|
if(arguments.get(i).getSpreadElement() != null) {
|
||||||
v.iconst(i);
|
hasSpread = true;
|
||||||
gen(valueArgument.getArguments().get(i).getArgumentExpression(), elementType);
|
break;
|
||||||
StackValue.arrayElement(elementType, false).store(v);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 TYPE_NOTHING = Type.getObjectType("jet/Nothing");
|
||||||
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
|
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_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_STRING_TYPE = Type.getObjectType("java/lang/String");
|
||||||
public static final Type JL_CHAR_SEQUENCE_TYPE = Type.getObjectType("java/lang/CharSequence");
|
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");
|
private static final Type JL_COMPARABLE_TYPE = Type.getObjectType("java/lang/Comparable");
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
@@ -94,4 +96,23 @@ public class VarArgTest extends CodegenTestCase {
|
|||||||
public void testKt797() {
|
public void testKt797() {
|
||||||
blackBoxFile("regressions/kt796_797.jet");
|
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 jet.Function0;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
@@ -82,4 +84,36 @@ public class Intrinsics {
|
|||||||
return sanitizeStackTrace(this);
|
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