diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 205d116fda9..562dcd33014 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -1,13 +1,12 @@ package org.jetbrains.jet.codegen; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.psi.JetClass; -import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeProjection; +import org.objectweb.asm.Type; /** * @author abreslav @@ -54,4 +53,8 @@ public class CodegenUtil { } return (ClassDescriptor) outerDescriptor; } + + public static Type arrayElementType(Type type) { + return Type.getType(type.getDescriptor().substring(1)); + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e93acaccf81..096e1b3aa51 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -378,8 +378,8 @@ public class ExpressionCodegen extends JetVisitor { gen(expression.getLoopRange(), loopRangeType); // array v.load(myIndexVar, Type.INT_TYPE); - v.aload(loopRangeType.getElementType()); - StackValue.onStack(loopRangeType.getElementType()).put(asmParamType, v); + v.aload(CodegenUtil.arrayElementType(loopRangeType)); + StackValue.onStack(CodegenUtil.arrayElementType(loopRangeType)).put(asmParamType, v); v.store(lookupLocal(parameterDescriptor), asmParamType); } @@ -1683,12 +1683,23 @@ public class ExpressionCodegen extends JetVisitor { } private void generateNewArray(JetCallExpression expression, Type type) { + JetType arrayType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); + List args = expression.getValueArguments(); if (args.size() != 1) { throw new CompilationException("array constructor requires one value argument"); } gen(args.get(0).getArgumentExpression(), Type.INT_TYPE); - v.newarray(type.getElementType()); + + JetType elementType = typeMapper.getGenericsElementType(arrayType); + if(elementType != null) { + generateTypeInfo(elementType); + v.invokestatic("jet/typeinfo/TypeInfo", "newArray", "(ILjet/typeinfo/TypeInfo;)[Ljava/lang/Object;"); + v.checkcast(type); + } + else { + v.newarray(CodegenUtil.arrayElementType(type)); + } } @Override @@ -1698,7 +1709,7 @@ public class ExpressionCodegen extends JetVisitor { gen(array, arrayType); generateArrayIndex(expression); if (arrayType.getSort() == Type.ARRAY) { - final Type elementType = arrayType.getElementType(); + final Type elementType = CodegenUtil.arrayElementType(arrayType); return StackValue.arrayElement(elementType); } else { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 91ad14a4f3f..92f504660c3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -670,4 +670,20 @@ public class JetTypeMapper { public String isKnownTypeInfo(JetType jetType) { return knowTypes.get(jetType); } + + public boolean isGenericsArray(JetType type) { + DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); + if(declarationDescriptor instanceof TypeParameterDescriptor) + return true; + + if(standardLibrary.getArray().equals(declarationDescriptor)) + return isGenericsArray(type.getArguments().get(0).getType()); + + return false; + } + + public JetType getGenericsElementType(JetType arrayType) { + JetType type = arrayType.getArguments().get(0).getType(); + return isGenericsArray(type) ? type : null; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 005cb7c422f..4974917fb30 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -152,7 +152,7 @@ public class NamespaceCodegen { v.aconst(jvmType); v.iconst(jetType.isNullable() ? 1 : 0); List arguments = jetType.getArguments(); - if (arguments.size() > 0) { + if (arguments.size() > 0 && !(jvmType.getSort() == Type.ARRAY && jvmType.getElementType().getSort() != Type.OBJECT)) { v.iconst(arguments.size()); v.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 29dbf0c7914..94b0504eeba 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -186,7 +186,7 @@ public abstract class StackValue { else v.iconst(0); } - else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT)) { + else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT) || type.getSort() == Type.ARRAY) { v.checkcast(type); } else if (type.getSort() == Type.OBJECT) { @@ -431,6 +431,7 @@ public abstract class StackValue { @Override public void put(Type type, InstructionAdapter v) { v.aload(type); // assumes array and index are on the stack + coerce(type, v); } @Override diff --git a/idea/testData/codegen/regressions/kt326.jet b/idea/testData/codegen/regressions/kt326.jet new file mode 100644 index 00000000000..cfd171f11e0 --- /dev/null +++ b/idea/testData/codegen/regressions/kt326.jet @@ -0,0 +1,25 @@ +namespace test + +class List() { + val a : Array = Array(1) +} + +fun box() : String { + val a = List() + a.a[0] = "1" + println(a.a[0]) + + val b = List() + b.a[0] = 10 + println(b.a[0]) + + val c = List>() + c.a[0] = Array(4) + println(c.a[0].size) + + return "OK" +} + +fun println(s : Any?) { + System.out?.println(s); +} diff --git a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java new file mode 100644 index 00000000000..372ba4214d1 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java @@ -0,0 +1,49 @@ +package org.jetbrains.jet.codegen; + +import java.lang.reflect.Method; + +public class ArrayGenTest extends CodegenTestCase { + public void testKt238 () throws Exception { + blackBoxFile("regressions/kt238.jet"); + } + + public void testKt326 () throws Exception { + blackBoxFile("regressions/kt326.jet"); + } + + public void testCreateMultiInt () throws Exception { + loadText("fun foo() = Array> (5)"); + Method foo = generateFunction(); + Object invoke = foo.invoke(null); + System.out.println(invoke.getClass()); + assertTrue(invoke instanceof int[][]); + } + + public void testCreateMultiString () throws Exception { + loadText("fun foo() = Array> (5)"); + Method foo = generateFunction(); + Object invoke = foo.invoke(null); + System.out.println(invoke.getClass()); + assertTrue(invoke instanceof String[][]); + } + + public void testCreateMultiGenerics () throws Exception { + /* + loadText("class L() { val a = Array(5) } fun foo() = L.a"); + System.out.println(generateToText()); + Method foo = generateFunction(); + Object invoke = foo.invoke(null); + System.out.println(invoke.getClass()); + assertTrue(invoke instanceof Integer[]); + */ + } + + public void testIntGenerics () throws Exception { + loadText("class L(var a : T) {} fun foo() = L(5).a"); + System.out.println(generateToText()); + Method foo = generateFunction(); + Object invoke = foo.invoke(null); + System.out.println(invoke.getClass()); + assertTrue(invoke instanceof Integer); + } +} diff --git a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTestCase.java b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTestCase.java deleted file mode 100644 index 36153e29568..00000000000 --- a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTestCase.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.jetbrains.jet.codegen; - -public class ArrayGenTestCase extends CodegenTestCase { - public void testKt238 () throws Exception { - blackBoxFile("regressions/kt238.jet"); - } -} diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index e4a971e90fe..4a49915511f 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -3,6 +3,7 @@ package jet.typeinfo; import jet.JetObject; import jet.Tuple0; +import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.TypeVariable; import java.util.*; @@ -37,6 +38,10 @@ public abstract class TypeInfo implements JetObject { public static final TypeInfo NULLABLE_DOUBLE_TYPE_INFO = getTypeInfo(Double.class, true); public static final TypeInfo NULLABLE_STRING_TYPE_INFO = getTypeInfo(String.class, true); public static final TypeInfo NULLABLE_TUPLE0_TYPE_INFO = getTypeInfo(Tuple0.class, true); + + public static Object [] newArray(int length, TypeInfo typeInfo) { + return (Object[]) Array.newInstance(((TypeInfoImpl) typeInfo).signature.klazz, length); + } public static TypeInfoProjection invariantProjection(final TypeInfo typeInfo) { return (TypeInfoProjection) typeInfo;