Supported creating varargs of reified type parameter

This commit is contained in:
Denis Zharkov
2014-11-04 11:38:28 +04:00
committed by Andrey Breslav
parent 29b4ba9b3d
commit a8ca39754c
6 changed files with 114 additions and 17 deletions
@@ -373,10 +373,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@NotNull
public Type expressionType(JetExpression expression) {
JetType type = bindingContext.get(EXPRESSION_TYPE, expression);
JetType type = expressionJetType(expression);
return type == null ? Type.VOID_TYPE : asmType(type);
}
@Nullable
public JetType expressionJetType(JetExpression expression) {
return bindingContext.get(EXPRESSION_TYPE, expression);
}
@Override
public StackValue visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, StackValue receiver) {
return genQualified(receiver, expression.getExpression());
@@ -2525,14 +2530,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
v.dup();
v.invokevirtual(owner, "size", "()I", false);
v.newarray(elementType);
newArrayInstruction(outType);
v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", false);
v.checkcast(type);
}
}
else {
v.iconst(arguments.size());
v.newarray(elementType);
newArrayInstruction(outType);
for (int i = 0; i != size; ++i) {
v.dup();
v.iconst(i);
@@ -3460,19 +3465,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
throw new CompilationException("primitive array constructor requires one argument", null, expression);
}
if (isArray) {
gen(args.get(0), Type.INT_TYPE);
putReifierMarkerIfTypeIsReifiedParameter(
arrayType.getArguments().get(0).getType(),
ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME
);
v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType())));
}
else {
Type type = typeMapper.mapType(arrayType);
gen(args.get(0), Type.INT_TYPE);
v.newarray(correctElementType(type));
}
gen(args.get(0), Type.INT_TYPE);
newArrayInstruction(arrayType);
if (args.size() == 2) {
int sizeIndex = myFrameMap.enterTemp(Type.INT_TYPE);
@@ -3512,6 +3506,21 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
public void newArrayInstruction(@NotNull JetType arrayType) {
if (KotlinBuiltIns.getInstance().isArray(arrayType)) {
JetType elementJetType = arrayType.getArguments().get(0).getType();
putReifierMarkerIfTypeIsReifiedParameter(
elementJetType,
ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME
);
v.newarray(boxType(asmType(elementJetType)));
}
else {
Type type = typeMapper.mapType(arrayType);
v.newarray(correctElementType(type));
}
}
@Override
public StackValue visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, StackValue receiver) {
JetExpression array = expression.getArrayExpression();
@@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.ExpressionCodegen;
@@ -45,7 +46,11 @@ public class CopyToArray extends IntrinsicMethod {
v.dup();
v.invokeinterface("java/util/Collection", "size", "()I");
v.newarray(returnType.getElementType());
assert element instanceof JetExpression;
JetType arrayType = codegen.expressionJetType((JetExpression) element);
assert arrayType != null;
codegen.newArrayInstruction(arrayType);
v.invokeinterface("java/util/Collection", "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;");
return getType(Object[].class);
@@ -0,0 +1,15 @@
import kotlin.test.assertEquals
inline fun <reified T> copy(c: Collection<T>): Array<T> {
return c.copyToArray()
}
fun box(): String {
val a: Array<String> = copy(listOf("a", "b", "c"))
assertEquals("abc", a.join(""))
val b: Array<Int> = copy(listOf(1,2,3))
assertEquals("123", b.map { it.toString() }.join(""))
return "OK"
}
@@ -0,0 +1,24 @@
import kotlin.test.assertEquals
fun <T> foo(vararg a: T) = a.size
inline fun <reified T> bar(a: Array<T>, block: () -> T): Array<T> {
assertEquals(4, foo(*a, block(), block()))
return array(*a, block(), block())
}
inline fun <reified T> empty() = array<T>()
fun box(): String {
var i = 0
val a: Array<String> = bar(array("1", "2")) { i++; i.toString() }
assertEquals("1234", a.join(""))
i = 0
val b: Array<Int> = bar(array(0, 1)) { i++ }
assertEquals("0123", b.map { it.toString() }.join(""))
return "OK"
}
@@ -0,0 +1,26 @@
import kotlin.test.assertEquals
fun <T> foo(vararg a: T) = a.size
inline fun <reified T> bar(block: () -> T): Array<T> {
assertEquals(2, foo(block(), block()))
return array(block(), block(), block())
}
inline fun <reified T> empty() = array<T>()
fun box(): String {
var i = 0
val a: Array<String> = bar() { i++; i.toString() }
assertEquals("345", a.join(""))
i = 0
val b: Array<Int> = bar() { i++ }
assertEquals("234", b.map { it.toString() }.join(""))
val c: Array<String> = empty()
assertEquals(0, c.size)
return "OK"
}
@@ -2471,6 +2471,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("copyToArray.kt")
public void testCopyToArray() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/copyToArray.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("defaultJavaClass.kt")
public void testDefaultJavaClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/defaultJavaClass.kt");
@@ -2542,6 +2548,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/sameIndexRecursive.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("spreads.kt")
public void testSpreads() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/spreads.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("varargs.kt")
public void testVarargs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/varargs.kt");
doTestWithStdlib(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxWithStdlib/storeStackBeforeInline")