diff --git a/.idea/libraries/annotations.xml b/.idea/libraries/annotations.xml
new file mode 100644
index 00000000000..5183e286398
--- /dev/null
+++ b/.idea/libraries/annotations.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/idea/idea.iml b/idea/idea.iml
index 9c112d636ff..d07235464f2 100644
--- a/idea/idea.iml
+++ b/idea/idea.iml
@@ -21,7 +21,6 @@
-
diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java
index 97f0cd3dda7..dc8f9961c02 100644
--- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java
+++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java
@@ -56,10 +56,8 @@ public class ClassCodegen {
public static void newTypeInfo(InstructionAdapter v, boolean isNullable, Type asmType) {
- v.anew(JetTypeMapper.TYPE_TYPEINFO);
- v.dup();
v.aconst(asmType);
v.iconst(isNullable?1:0);
- v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;Z)V");
+ v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
}
}
diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
index fff6e384af8..521ae9e361a 100644
--- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
+++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
@@ -18,6 +18,7 @@ import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
+import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
@@ -1949,29 +1950,39 @@ public class ExpressionCodegen extends JetVisitor {
return;
}
- v.anew(JetTypeMapper.TYPE_TYPEINFO);
- v.dup();
v.aconst(jvmType);
v.iconst(jetType.isNullable()?1:0);
List arguments = jetType.getArguments();
if (arguments.size() > 0) {
v.iconst(arguments.size());
- v.newarray(JetTypeMapper.TYPE_TYPEINFO);
+ v.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
for (int i = 0, argumentsSize = arguments.size(); i < argumentsSize; i++) {
TypeProjection argument = arguments.get(i);
v.dup();
v.iconst(i);
generateTypeInfo(argument.getType());
+ genTypeInfoToProjection(v, argument.getProjectionKind());
v.astore(JetTypeMapper.TYPE_OBJECT);
}
- v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfo;)V");
+ v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
}
else {
- v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;Z)V");
+ v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
}
}
+ public static void genTypeInfoToProjection(InstructionAdapter v, Variance variance) {
+ if(variance == Variance.INVARIANT)
+ v.invokestatic("jet/typeinfo/TypeInfo", "invariantProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;");
+ else if(variance == Variance.IN_VARIANCE)
+ v.invokestatic("jet/typeinfo/TypeInfo", "inProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;");
+ else if(variance == Variance.OUT_VARIANCE)
+ v.invokestatic("jet/typeinfo/TypeInfo", "outProjection", "(Ljet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfoProjection;");
+ else
+ throw new UnsupportedOperationException(variance.toString());
+ }
+
private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor) {
final StackValue value = typeParameterExpressions.get(typeParameterDescriptor);
if (value != null) {
@@ -1982,7 +1993,7 @@ public class ExpressionCodegen extends JetVisitor {
if (containingDeclaration == contextType() && contextType() instanceof ClassDescriptor) {
loadTypeInfo(typeMapper, (ClassDescriptor) contextType(), v);
v.iconst(typeParameterDescriptor.getIndex());
- v.invokevirtual("jet/typeinfo/TypeInfo", "getTypeParameter", "(I)Ljet/typeinfo/TypeInfo;");
+ v.invokevirtual("jet/typeinfo/TypeInfo", "getArgumentType", "(I)Ljet/typeinfo/TypeInfo;");
return;
}
throw new UnsupportedOperationException("don't know what this type parameter resolves to");
diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
index 6d019b6a771..8f1be52b429 100644
--- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
+++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.types.JetType;
+import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
@@ -389,21 +390,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
- iv.anew(JetTypeMapper.TYPE_TYPEINFO);
- iv.dup();
iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.INTERFACE));
iv.iconst(0);
iv.iconst(typeParamCount);
- iv.newarray(JetTypeMapper.TYPE_TYPEINFO);
+ iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
for (int i = 0; i < typeParamCount; i++) {
iv.dup();
iv.iconst(i);
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
+ ExpressionCodegen.genTypeInfoToProjection(iv, Variance.INVARIANT);
iv.astore(JetTypeMapper.TYPE_OBJECT);
}
- iv.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfo;)V");
+ iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java
index 40522b08121..d48c8eec52e 100644
--- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java
+++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java
@@ -4,6 +4,7 @@ import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import jet.JetObject;
import jet.typeinfo.TypeInfo;
+import jet.typeinfo.TypeInfoProjection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
@@ -23,6 +24,7 @@ import java.util.*;
public class JetTypeMapper {
public static final Type TYPE_OBJECT = Type.getObjectType("java/lang/Object");
public static final Type TYPE_TYPEINFO = Type.getType(TypeInfo.class);
+ public static final Type TYPE_TYPEINFOPROJECTION = Type.getType(TypeInfoProjection.class);
public static final Type TYPE_JET_OBJECT = Type.getType(JetObject.class);
public static final Type TYPE_CLASS = Type.getType(Class.class);
public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing");
diff --git a/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java b/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java
index e398c7d605a..fb7d05ede1e 100644
--- a/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java
+++ b/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java
@@ -3,6 +3,7 @@ package org.jetbrains.jet.plugin.structureView;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.navigation.ItemPresentation;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.NavigatablePsiElement;
@@ -68,6 +69,7 @@ public class JetStructureViewElement implements StructureViewTreeElement {
? PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED)
: null;
}
+
};
}
diff --git a/idea/testData/codegen/patternMatching/is.jet b/idea/testData/codegen/patternMatching/is.jet
new file mode 100644
index 00000000000..a5b5f33195f
--- /dev/null
+++ b/idea/testData/codegen/patternMatching/is.jet
@@ -0,0 +1,11 @@
+fun typeName(a: Any?) : String {
+ return when(a) {
+ is java.util.ArrayList => "array list"
+ else => "no idea"
+ }
+}
+
+fun box() : String {
+ if(typeName(java.util.ArrayList ()) != "array list") return "array list failed"
+ return "OK"
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java
index 13aaf4b19e2..c82f9a4847d 100644
--- a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java
+++ b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java
@@ -47,6 +47,12 @@ public class PatternMatchingTest extends CodegenTestCase {
assertEquals("something", foo.invoke(null, 19));
}
+ public void testIs() throws Exception {
+ loadFile();
+ blackBox();
+ System.out.println(generateToText());
+ }
+
public void testRange() throws Exception {
loadFile();
System.out.println(generateToText());
diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java
index 55f848c7b2c..f93bf29bad6 100644
--- a/stdlib/src/jet/typeinfo/TypeInfo.java
+++ b/stdlib/src/jet/typeinfo/TypeInfo.java
@@ -1,6 +1,7 @@
package jet.typeinfo;
import jet.JetObject;
+import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.util.Arrays;
@@ -8,60 +9,101 @@ import java.util.Arrays;
/**
* @author abreslav
* @author yole
+ * @author alex.tkachman
*/
-public class TypeInfo implements JetObject {
+public abstract class TypeInfo implements JetObject {
+ public static final TypeInfo BYTE_TYPE_INFO = getTypeInfo(Byte.class, false);
+ public static final TypeInfo SHORT_TYPE_INFO = getTypeInfo(Short.class, false);
+ public static final TypeInfo INT_TYPE_INFO = getTypeInfo(Integer.class, false);
+ public static final TypeInfo LONG_TYPE_INFO = getTypeInfo(Long.class, false);
+ public static final TypeInfo CHAR_TYPE_INFO = getTypeInfo(Character.class, false);
+ public static final TypeInfo BOOL_TYPE_INFO = getTypeInfo(Boolean.class, false);
+ public static final TypeInfo FLOAT_TYPE_INFO = getTypeInfo(Float.class, false);
+ public static final TypeInfo DOUBLE_TYPE_INFO = getTypeInfo(Double.class, false);
+
private TypeInfo> typeInfo;
private final Class theClass;
private final boolean nullable;
- private final TypeInfo[] typeParameters;
+ private final TypeInfoProjection[] projections;
- public TypeInfo(Class theClass, boolean nullable) {
+ private TypeInfo(Class theClass, boolean nullable) {
this.theClass = theClass;
this.nullable = nullable;
- this.typeParameters = null;
+ this.projections = null;
}
- public TypeInfo(Class theClass, boolean nullable, TypeInfo[] typeParameters) {
+ private TypeInfo(Class theClass, boolean nullable, TypeInfoProjection[] projections) {
this.theClass = theClass;
this.nullable = nullable;
- this.typeParameters = typeParameters;
+ this.projections = projections;
}
- public Object getClassObject() {
+ public static TypeInfoProjection invariantProjection(final TypeInfo typeInfo) {
+ return (TypeInfoImpl) typeInfo;
+ }
+
+ public static TypeInfoProjection inProjection(TypeInfo typeInfo) {
+ return new TypeInfoProjection.TypeInfoProjectionImpl(typeInfo) {
+ @NotNull
+ @Override
+ public TypeInfoVariance getVariance() {
+ return TypeInfoVariance.IN_VARIANCE;
+ }
+ };
+ }
+
+ public static TypeInfoProjection outProjection(TypeInfo typeInfo) {
+ return new TypeInfoProjection.TypeInfoProjectionImpl(typeInfo) {
+ @NotNull
+ @Override
+ public TypeInfoVariance getVariance() {
+ return TypeInfoVariance.OUT_VARIANCE;
+ }
+ };
+ }
+
+ public static TypeInfo getTypeInfo(Class klazz, boolean nullable) {
+ return new TypeInfoImpl(klazz, nullable);
+ }
+
+ public static TypeInfo getTypeInfo(Class klazz, boolean nullable, TypeInfoProjection[] projections) {
+ return new TypeInfoImpl(klazz, nullable, projections);
+ }
+
+ public final Object getClassObject() {
try {
final Class implClass = theClass.getClassLoader().loadClass(theClass.getCanonicalName() + "$$Impl");
final Field classobj = implClass.getField("$classobj");
return classobj.get(null);
- }
- catch(Exception e) {
+ } catch (Exception e) {
return null;
}
}
- public boolean isInstance(Object obj) {
+ public final boolean isInstance(Object obj) {
+ if (obj == null) return nullable;
+
if (obj instanceof JetObject) {
return ((JetObject) obj).getTypeInfo().isSubtypeOf(this);
}
- if(obj == null)
- return nullable;
return theClass.isAssignableFrom(obj.getClass()); // TODO
}
- public boolean isSubtypeOf(TypeInfo> superType) {
- if (!superType.theClass.isAssignableFrom(theClass)) {
- return false;
- }
+ public final boolean isSubtypeOf(TypeInfo> superType) {
if (nullable && !superType.nullable) {
return false;
}
- if (typeParameters != null) {
- if (superType.typeParameters == null || superType.typeParameters.length != typeParameters.length) {
+ if (!superType.theClass.isAssignableFrom(theClass)) {
+ return false;
+ }
+ if (projections != null) {
+ if (superType.projections == null || superType.projections.length != projections.length) {
throw new IllegalArgumentException("inconsistent type infos for the same class");
}
- for (int i = 0; i < typeParameters.length; i++) {
+ for (int i = 0; i < projections.length; i++) {
// TODO handle variance here
- if (!typeParameters [i].equals(superType.typeParameters [i])) {
+ if (!projections[i].equals(superType.projections[i])) {
return false;
}
}
@@ -69,12 +111,16 @@ public class TypeInfo implements JetObject {
return true;
}
- public TypeInfo getTypeParameter(int index) {
- return typeParameters[index];
+ public final TypeInfoProjection getProjection(int index) {
+ return projections[index];
+ }
+
+ public final TypeInfo getArgumentType(int index) {
+ return projections[index].getType();
}
@Override
- public TypeInfo> getTypeInfo() {
+ public final TypeInfo> getTypeInfo() {
if (typeInfo == null) {
// TODO: Implementation must be lazy, otherwise the result would be of an infinite size
throw new UnsupportedOperationException(); // TODO
@@ -83,7 +129,7 @@ public class TypeInfo implements JetObject {
}
@Override
- public boolean equals(Object o) {
+ public final boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -91,37 +137,50 @@ public class TypeInfo implements JetObject {
if (!theClass.equals(typeInfo.theClass)) return false;
if (nullable != typeInfo.nullable) return false;
- if (!Arrays.equals(typeParameters, typeInfo.typeParameters)) return false;
+ if (!Arrays.equals(projections, typeInfo.projections)) return false;
return true;
}
@Override
- public int hashCode() {
- return 31 * theClass.hashCode() + (typeParameters != null ? Arrays.hashCode(typeParameters) : 0);
+ public final int hashCode() {
+ return 31 * theClass.hashCode() + (projections != null ? Arrays.hashCode(projections) : 0);
}
@Override
- public String toString() {
+ public final String toString() {
StringBuilder sb = new StringBuilder().append(theClass.getName());
- if(typeParameters != null && typeParameters.length != 0) {
+ if (projections != null && projections.length != 0) {
sb.append("<");
- for(int i = 0; i != typeParameters.length-1; ++i) {
- sb.append(typeParameters[i].toString()).append(",");
+ for (int i = 0; i != projections.length - 1; ++i) {
+ sb.append(projections[i].toString()).append(",");
}
- sb.append(typeParameters[typeParameters.length - 1].toString()).append(">");
+ sb.append(projections[projections.length - 1].toString()).append(">");
}
- if(nullable)
+ if (nullable)
sb.append("?");
return sb.toString();
}
- public static final TypeInfo BYTE_TYPE_INFO = new TypeInfo(Byte.class, false);
- public static final TypeInfo SHORT_TYPE_INFO = new TypeInfo(Short.class, false);
- public static final TypeInfo INT_TYPE_INFO = new TypeInfo(Integer.class, false);
- public static final TypeInfo LONG_TYPE_INFO = new TypeInfo(Long.class, false);
- public static final TypeInfo CHAR_TYPE_INFO = new TypeInfo(Character.class, false);
- public static final TypeInfo BOOL_TYPE_INFO = new TypeInfo(Boolean.class, false);
- public static final TypeInfo FLOAT_TYPE_INFO = new TypeInfo(Float.class, false);
- public static final TypeInfo DOUBLE_TYPE_INFO = new TypeInfo(Double.class, false);
+ private static class TypeInfoImpl extends TypeInfo implements TypeInfoProjection {
+ TypeInfoImpl(Class klazz, boolean nullable) {
+ super(klazz, nullable);
+ }
+
+ TypeInfoImpl(Class klazz, boolean nullable, TypeInfoProjection[] projections) {
+ super(klazz, nullable, projections);
+ }
+
+ @NotNull
+ @Override
+ public TypeInfoVariance getVariance() {
+ return TypeInfoVariance.INVARIANT;
+ }
+
+ @NotNull
+ @Override
+ public TypeInfo getType() {
+ return this;
+ }
+ }
}
diff --git a/stdlib/src/jet/typeinfo/TypeInfoProjection.java b/stdlib/src/jet/typeinfo/TypeInfoProjection.java
new file mode 100644
index 00000000000..381383c05f4
--- /dev/null
+++ b/stdlib/src/jet/typeinfo/TypeInfoProjection.java
@@ -0,0 +1,50 @@
+package jet.typeinfo;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author alex.tkachman
+ */
+public interface TypeInfoProjection {
+ @NotNull
+ TypeInfoVariance getVariance();
+
+ @NotNull
+ TypeInfo getType();
+
+ abstract class TypeInfoProjectionImpl implements TypeInfoProjection {
+ @NotNull private final TypeInfo type;
+
+ TypeInfoProjectionImpl(@NotNull TypeInfo typeInfo) {
+ this.type = typeInfo;
+ }
+
+ @Override
+ @NotNull
+ public final TypeInfo getType() {
+ return type;
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ TypeInfoProjectionImpl that = (TypeInfoProjectionImpl) o;
+ // no need to compare variance as we compared classes already
+ return type.equals(that.type);
+ }
+
+ @Override
+ public final int hashCode() {
+ int result = type.hashCode();
+ result = 31 * result + (getVariance().hashCode());
+ return result;
+ }
+
+ @Override
+ public final String toString() {
+ return (getVariance() == TypeInfoVariance.INVARIANT ? "" : getVariance().toString() + " ") + type;
+ }
+ }
+}
diff --git a/stdlib/src/jet/typeinfo/TypeInfoVariance.java b/stdlib/src/jet/typeinfo/TypeInfoVariance.java
new file mode 100644
index 00000000000..410d45e3c49
--- /dev/null
+++ b/stdlib/src/jet/typeinfo/TypeInfoVariance.java
@@ -0,0 +1,21 @@
+package jet.typeinfo;
+
+/**
+ * @author alex.tkachman
+ */
+public enum TypeInfoVariance {
+ INVARIANT("") ,
+ IN_VARIANCE("in"),
+ OUT_VARIANCE("out");
+
+ private final String label;
+
+ TypeInfoVariance(String label) {
+ this.label = label;
+ }
+
+ @Override
+ public String toString() {
+ return label;
+ }
+}
diff --git a/stdlib/stdlib.iml b/stdlib/stdlib.iml
index d5c07432750..0e9d8224de4 100644
--- a/stdlib/stdlib.iml
+++ b/stdlib/stdlib.iml
@@ -7,6 +7,7 @@
+