Type infrastructure simplified
This commit is contained in:
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -23,29 +24,48 @@ public class TypeResolver {
|
||||
public Type resolveType(@NotNull final JetScope scope, @NotNull final JetTypeReference typeReference) {
|
||||
final List<Attribute> attributes = AttributeResolver.INSTANCE.resolveAttributes(typeReference.getAttributes());
|
||||
|
||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||
return resolveTypeElement(scope, attributes, typeElement, false);
|
||||
}
|
||||
|
||||
private Type resolveTypeElement(final JetScope scope, final List<Attribute> attributes, JetTypeElement typeElement, final boolean nullable) {
|
||||
final Type[] result = new Type[1];
|
||||
typeReference.getTypeElement().accept(new JetVisitor() {
|
||||
typeElement.accept(new JetVisitor() {
|
||||
@Override
|
||||
public void visitUserType(JetUserType type) {
|
||||
ClassDescriptor classDescriptor = resolveClass(scope, type);
|
||||
if (classDescriptor != null) {
|
||||
result[0] = new ClassType(
|
||||
attributes,
|
||||
classDescriptor,
|
||||
resolveTypeProjections(scope, type.getTypeArguments())
|
||||
result[0] = new TypeImpl(
|
||||
attributes,
|
||||
classDescriptor.getTypeConstructor(),
|
||||
nullable,
|
||||
resolveTypeProjections(scope, type.getTypeArguments()),
|
||||
JetStandardClasses.STUB
|
||||
);
|
||||
} else if (type.getTypeArguments().isEmpty()) {
|
||||
}
|
||||
else if (type.getTypeArguments().isEmpty()) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameterDescriptor(type.getReferencedName());
|
||||
if (typeParameterDescriptor != null) {
|
||||
result[0] = new TypeVariable(attributes, typeParameterDescriptor);
|
||||
result[0] = new TypeImpl(
|
||||
attributes,
|
||||
typeParameterDescriptor.getTypeConstructor(),
|
||||
nullable || hasNullableBound(typeParameterDescriptor),
|
||||
Collections.<TypeProjection>emptyList(),
|
||||
JetStandardClasses.STUB
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNullableType(JetNullableType nullableType) {
|
||||
result[0] = resolveTypeElement(scope, attributes, nullableType.getInnerType(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTupleType(JetTupleType type) {
|
||||
// TODO labels
|
||||
result[0] = TupleType.getTupleType(resolveTypes(scope, type.getComponentTypeRefs()));
|
||||
result[0] = JetStandardClasses.getTupleType(resolveTypes(scope, type.getComponentTypeRefs()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,11 +74,20 @@ public class TypeResolver {
|
||||
}
|
||||
});
|
||||
if (result[0] == null) {
|
||||
return new ErrorType(typeReference);
|
||||
return ErrorType.createErrorType(typeElement.getText());
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
|
||||
private boolean hasNullableBound(TypeParameterDescriptor typeParameterDescriptor) {
|
||||
for (Type bound : typeParameterDescriptor.getUpperBounds()) {
|
||||
if (bound.isNullable()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Type> resolveTypes(JetScope scope, List<JetTypeReference> argumentElements) {
|
||||
final List<Type> arguments = new ArrayList<Type>();
|
||||
for (JetTypeReference argumentElement : argumentElements) {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ClassType extends TypeImpl {
|
||||
@NotNull
|
||||
private final ClassDescriptor classDescriptor;
|
||||
|
||||
public ClassType(@NotNull List<Attribute> attributes, @NotNull ClassDescriptor classDescriptor, @NotNull List<TypeProjection> arguments) {
|
||||
super(attributes, classDescriptor.getTypeConstructor(), arguments);
|
||||
assert classDescriptor.getTypeConstructor().getParameters().size() == arguments.size() : classDescriptor.getTypeConstructor().getParameters().size() + " != " + arguments.size();
|
||||
|
||||
this.classDescriptor = classDescriptor;
|
||||
}
|
||||
|
||||
public ClassType(ClassDescriptor classDescriptor) {
|
||||
this(Collections.<Attribute>emptyList(), classDescriptor, Collections.<TypeProjection>emptyList());
|
||||
assert classDescriptor.getTypeConstructor().getParameters().size() == 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassDescriptor getClassDescriptor() {
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitClassType(this, data);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,26 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ErrorType extends VisitableTypeImpl implements Type {
|
||||
private final String debugLabel;
|
||||
public class ErrorType {
|
||||
private static final TypeMemberDomain ERROR_DOMAIN = new TypeMemberDomain() {
|
||||
@Override
|
||||
public ClassDescriptor getClassDescriptor(@NotNull Type type) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
};
|
||||
private static final TypeConstructor ERROR = new TypeConstructor(Collections.<Attribute>emptyList(), "ERROR", Collections.<TypeParameterDescriptor>emptyList(), Collections.<Type>emptyList());
|
||||
|
||||
public ErrorType(JetTypeReference typeReference) {
|
||||
super(Collections.<Attribute>emptyList());
|
||||
this.debugLabel = typeReference.getText();
|
||||
assert debugLabel != null;
|
||||
public static Type createErrorType(String debugMessage) {
|
||||
return new TypeImpl(ERROR, ERROR_DOMAIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeConstructor getConstructor() {
|
||||
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeProjection> getArguments() {
|
||||
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitErrorType(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "!!!" + debugLabel + "!!!";
|
||||
public static boolean isError(Type type) {
|
||||
return type.getConstructor() == ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,34 @@ package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetStandardClasses {
|
||||
private static final TypeConstructor NOTHING = new TypeConstructor(
|
||||
Collections.<Attribute>emptyList(),
|
||||
"Nothing",
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
new AbstractCollection<Type>() {
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return o instanceof Type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Type> iterator() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
|
||||
private static final ClassDescriptor ANY = new ClassDescriptor(
|
||||
Collections.<Attribute>emptyList(),
|
||||
"Any",
|
||||
@@ -17,7 +37,7 @@ public class JetStandardClasses {
|
||||
Collections.<Type>emptySet()
|
||||
);
|
||||
|
||||
private static final ClassType ANY_TYPE = new ClassType(ANY);
|
||||
private static final Type ANY_TYPE = new TypeImpl(ANY.getTypeConstructor(), TypeMemberDomain.EMPTY);
|
||||
|
||||
private static final ClassDescriptor BYTE = new ClassDescriptor("Byte");
|
||||
private static final ClassDescriptor CHAR = new ClassDescriptor("Char");
|
||||
@@ -48,13 +68,33 @@ public class JetStandardClasses {
|
||||
}
|
||||
}
|
||||
|
||||
public static final TypeMemberDomain STUB = new TypeMemberDomain() {
|
||||
@Override
|
||||
public ClassDescriptor getClassDescriptor(@NotNull Type type) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
};
|
||||
|
||||
private static final Type BYTE_TYPE = new TypeImpl(getByte().getTypeConstructor(), STUB);
|
||||
private static final Type CHAR_TYPE = new TypeImpl(getChar().getTypeConstructor(), STUB);
|
||||
private static final Type SHORT_TYPE = new TypeImpl(getShort().getTypeConstructor(), STUB);
|
||||
private static final Type INT_TYPE = new TypeImpl(getInt().getTypeConstructor(), STUB);
|
||||
private static final Type LONG_TYPE = new TypeImpl(getLong().getTypeConstructor(), STUB);
|
||||
private static final Type FLOAT_TYPE = new TypeImpl(getFloat().getTypeConstructor(), STUB);
|
||||
private static final Type DOUBLE_TYPE = new TypeImpl(getDouble().getTypeConstructor(), STUB);
|
||||
private static final Type BOOLEAN_TYPE = new TypeImpl(getBoolean().getTypeConstructor(), STUB);
|
||||
private static final Type STRING_TYPE = new TypeImpl(getString().getTypeConstructor(), STUB);
|
||||
private static final Type UNIT_TYPE = new TypeImpl(getTuple(0).getTypeConstructor(), STUB);
|
||||
private static final Type NOTHING_TYPE = new TypeImpl(NOTHING, STUB);
|
||||
private static final Type NULLABLE_NOTHING_TYPE = new TypeImpl(Collections.<Attribute>emptyList(), NOTHING, true, Collections.<TypeProjection>emptyList(), TypeMemberDomain.EMPTY);
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getAny() {
|
||||
return ANY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassType getAnyType() {
|
||||
public static Type getAnyType() {
|
||||
return ANY_TYPE;
|
||||
}
|
||||
|
||||
@@ -108,9 +148,92 @@ public class JetStandardClasses {
|
||||
return TUPLE[size];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getLabeledTuple(int size) {
|
||||
public static Type getIntType() {
|
||||
return INT_TYPE;
|
||||
}
|
||||
|
||||
public static Type getLongType() {
|
||||
return LONG_TYPE;
|
||||
}
|
||||
|
||||
public static Type getDoubleType() {
|
||||
return DOUBLE_TYPE;
|
||||
}
|
||||
|
||||
public static Type getFloatType() {
|
||||
return FLOAT_TYPE;
|
||||
}
|
||||
|
||||
public static Type getCharType() {
|
||||
return CHAR_TYPE;
|
||||
}
|
||||
|
||||
public static Type getBooleanType() {
|
||||
return BOOLEAN_TYPE;
|
||||
}
|
||||
|
||||
public static Type getStringType() {
|
||||
return STRING_TYPE;
|
||||
}
|
||||
|
||||
public static Type getByteType() {
|
||||
return BYTE_TYPE;
|
||||
}
|
||||
|
||||
public static Type getShortType() {
|
||||
return SHORT_TYPE;
|
||||
}
|
||||
|
||||
public static Type getUnitType() {
|
||||
return UNIT_TYPE;
|
||||
}
|
||||
|
||||
public static Type getNothingType() {
|
||||
return NOTHING_TYPE;
|
||||
}
|
||||
|
||||
public static Type getNullableNothingType() {
|
||||
return NULLABLE_NOTHING_TYPE;
|
||||
}
|
||||
|
||||
public static Type getTupleType(List<Attribute> attributes, List<Type> arguments) {
|
||||
if (attributes.isEmpty() && arguments.isEmpty()) {
|
||||
return getUnitType();
|
||||
}
|
||||
return new TypeImpl(attributes, getTuple(arguments.size()).getTypeConstructor(), false, toProjections(arguments), STUB);
|
||||
}
|
||||
|
||||
public static Type getTupleType(List<Type> arguments) {
|
||||
return getTupleType(Collections.<Attribute>emptyList(), arguments);
|
||||
}
|
||||
|
||||
public static Type getTupleType(Type... arguments) {
|
||||
return getTupleType(Collections.<Attribute>emptyList(), Arrays.asList(arguments));
|
||||
}
|
||||
|
||||
public static Type getLabeledTupleType(List<Attribute> attributes, List<ParameterDescriptor> arguments) {
|
||||
// TODO
|
||||
return getTuple(size);
|
||||
return getTupleType(attributes, toTypes(arguments));
|
||||
}
|
||||
|
||||
public static Type getLabeledTupleType(List<ParameterDescriptor> arguments) {
|
||||
// TODO
|
||||
return getLabeledTupleType(Collections.<Attribute>emptyList(), arguments);
|
||||
}
|
||||
|
||||
private static List<TypeProjection> toProjections(List<Type> arguments) {
|
||||
List<TypeProjection> result = new ArrayList<TypeProjection>();
|
||||
for (Type argument : arguments) {
|
||||
result.add(new TypeProjection(ProjectionKind.OUT_ONLY, argument));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<Type> toTypes(List<ParameterDescriptor> labeledEntries) {
|
||||
List<Type> result = new ArrayList<Type>();
|
||||
for (ParameterDescriptor entry : labeledEntries) {
|
||||
result.add(entry.getType());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetStandardTypes {
|
||||
private static final ClassType ANY_TYPE = new ClassType(JetStandardClasses.getAny());
|
||||
private static final ClassType BYTE = new ClassType(JetStandardClasses.getByte());
|
||||
private static final ClassType CHAR = new ClassType(JetStandardClasses.getChar());
|
||||
private static final ClassType SHORT = new ClassType(JetStandardClasses.getShort());
|
||||
private static final ClassType INT = new ClassType(JetStandardClasses.getInt());
|
||||
private static final ClassType LONG = new ClassType(JetStandardClasses.getLong());
|
||||
private static final ClassType FLOAT = new ClassType(JetStandardClasses.getFloat());
|
||||
private static final ClassType DOUBLE = new ClassType(JetStandardClasses.getDouble());
|
||||
private static final ClassType BOOLEAN = new ClassType(JetStandardClasses.getBoolean());
|
||||
private static final ClassType STRING = new ClassType(JetStandardClasses.getString());
|
||||
private static final TupleType UNIT = TupleType.UNIT;
|
||||
|
||||
public static ClassType getInt() {
|
||||
return INT;
|
||||
}
|
||||
|
||||
public static ClassType getLong() {
|
||||
return LONG;
|
||||
}
|
||||
|
||||
public static ClassType getDouble() {
|
||||
return DOUBLE;
|
||||
}
|
||||
|
||||
public static ClassType getFloat() {
|
||||
return FLOAT;
|
||||
}
|
||||
|
||||
public static ClassType getChar() {
|
||||
return CHAR;
|
||||
}
|
||||
|
||||
public static ClassType getBoolean() {
|
||||
return BOOLEAN;
|
||||
}
|
||||
|
||||
public static ClassType getString() {
|
||||
return STRING;
|
||||
}
|
||||
|
||||
public static ClassType getByte() {
|
||||
return BYTE;
|
||||
}
|
||||
|
||||
public static ClassType getShort() {
|
||||
return SHORT;
|
||||
}
|
||||
|
||||
public static TupleType getUnit() {
|
||||
return UNIT;
|
||||
}
|
||||
|
||||
public static Type getAny() {
|
||||
return ANY_TYPE;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import java.util.Map;
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetTypeChecker {
|
||||
public static final JetTypeChecker INSTANCE = new JetTypeChecker();
|
||||
|
||||
public Type getType(JetExpression expression) {
|
||||
final Type[] result = new Type[1];
|
||||
expression.accept(new JetVisitor() {
|
||||
@@ -22,24 +24,26 @@ public class JetTypeChecker {
|
||||
public void visitConstantExpression(JetConstantExpression expression) {
|
||||
IElementType elementType = expression.getNode().getElementType();
|
||||
if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getInt();
|
||||
result[0] = JetStandardClasses.getIntType();
|
||||
} else if (elementType == JetNodeTypes.LONG_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getLong();
|
||||
result[0] = JetStandardClasses.getLongType();
|
||||
} else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
|
||||
String text = expression.getText();
|
||||
assert text.length() > 0;
|
||||
char lastChar = text.charAt(text.length() - 1);
|
||||
if (lastChar == 'f' || lastChar == 'F') {
|
||||
result[0] = JetStandardTypes.getFloat();
|
||||
result[0] = JetStandardClasses.getFloatType();
|
||||
} else {
|
||||
result[0] = JetStandardTypes.getDouble();
|
||||
result[0] = JetStandardClasses.getDoubleType();
|
||||
}
|
||||
} else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getBoolean();
|
||||
result[0] = JetStandardClasses.getBooleanType();
|
||||
} else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getChar();
|
||||
result[0] = JetStandardClasses.getCharType();
|
||||
} else if (elementType == JetNodeTypes.STRING_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getString();
|
||||
result[0] = JetStandardClasses.getStringType();
|
||||
} else if (elementType == JetNodeTypes.NULL) {
|
||||
result[0] = JetStandardClasses.getNullableNothingType();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported constant: " + expression);
|
||||
}
|
||||
@@ -52,7 +56,7 @@ public class JetTypeChecker {
|
||||
for (JetExpression entry : entries) {
|
||||
types.add(getType(entry));
|
||||
}
|
||||
result[0] = TupleType.getTupleType(types);
|
||||
result[0] = JetStandardClasses.getTupleType(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,8 +72,10 @@ public class JetTypeChecker {
|
||||
}
|
||||
|
||||
public boolean isSubtypeOf(Type subtype, Type supertype) {
|
||||
@Nullable
|
||||
Type closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
||||
if (!supertype.isNullable() && subtype.isNullable()) {
|
||||
return false;
|
||||
}
|
||||
@Nullable Type closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
||||
if (closestSupertype == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -95,30 +101,24 @@ public class JetTypeChecker {
|
||||
}
|
||||
|
||||
private Type substituteForParameters(Type context, Type subject) {
|
||||
Map<TypeParameterDescriptor, TypeProjection> parameterValues = new HashMap<TypeParameterDescriptor, TypeProjection>();
|
||||
Map<TypeConstructor, TypeProjection> parameterValues = new HashMap<TypeConstructor, TypeProjection>();
|
||||
|
||||
List<TypeParameterDescriptor> parameters = context.getConstructor().getParameters();
|
||||
List<TypeProjection> contextArguments = context.getArguments();
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
TypeProjection value = contextArguments.get(i);
|
||||
parameterValues.put(parameter, value);
|
||||
parameterValues.put(parameter.getTypeConstructor(), value);
|
||||
}
|
||||
|
||||
return substitute(parameterValues, subject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type substitute(Map<TypeParameterDescriptor, TypeProjection> parameterValues, Type subject) {
|
||||
if (subject instanceof TypeVariable) {
|
||||
TypeVariable typeVariable = (TypeVariable) subject;
|
||||
TypeProjection value = parameterValues.get(typeVariable.getTypeParameterDescriptor());
|
||||
if (value == null) {
|
||||
return typeVariable;
|
||||
}
|
||||
Type type = value.getType();
|
||||
assert type != null;
|
||||
return type;
|
||||
private Type substitute(Map<TypeConstructor, TypeProjection> parameterValues, Type subject) {
|
||||
TypeProjection value = parameterValues.get(subject.getConstructor());
|
||||
if (value != null) {
|
||||
return value.getType();
|
||||
}
|
||||
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
|
||||
for (TypeProjection argument : subject.getArguments()) {
|
||||
@@ -128,13 +128,7 @@ public class JetTypeChecker {
|
||||
}
|
||||
|
||||
private Type specializeType(Type type, List<TypeProjection> newArguments) {
|
||||
return type.accept(new TypeVisitor<Type, List<TypeProjection>>() {
|
||||
@Override
|
||||
public Type visitClassType(ClassType classType, List<TypeProjection> newArguments) {
|
||||
return new ClassType(classType.getAttributes(), classType.getClassDescriptor(), newArguments);
|
||||
}
|
||||
|
||||
}, newArguments);
|
||||
return new TypeImpl(type.getAttributes(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberDomain());
|
||||
}
|
||||
|
||||
private boolean checkSubtypeForTheSameConstructor(Type subtype, Type supertype) {
|
||||
@@ -212,7 +206,7 @@ public class JetTypeChecker {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean equalTypes(Type type1, Type type2) {
|
||||
public boolean equalTypes(Type type1, Type type2) {
|
||||
if (!type1.getConstructor().equals(type2.getConstructor())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class NothingType extends TypeImpl {
|
||||
|
||||
public static final TypeConstructor NOTHING = new TypeConstructor(
|
||||
Collections.<Attribute>emptyList(),
|
||||
"Nothing",
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
new AbstractCollection<Type>() {
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return o instanceof Type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Type> iterator() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: attributes seem wrong here
|
||||
public NothingType(List<Attribute> attributes) {
|
||||
super(attributes, NOTHING, Collections.<TypeProjection>emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitNothingType(this, data);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class NullableType extends VisitableTypeImpl {
|
||||
public NullableType(List<Attribute> attributes) {
|
||||
super(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeConstructor getConstructor() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeProjection> getArguments() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitNullableType(this, data);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ThisType extends TypeImpl {
|
||||
public ThisType(List<Attribute> attributes, ClassDescriptor thisClass) {
|
||||
super(attributes, thisClass.getTypeConstructor(), toArguments(thisClass.getTypeConstructor().getParameters()));
|
||||
}
|
||||
|
||||
private static List<TypeProjection> toArguments(List<TypeParameterDescriptor> parameters) {
|
||||
List<TypeProjection> result = new ArrayList<TypeProjection>();
|
||||
for (TypeParameterDescriptor parameter : parameters) {
|
||||
result.add(new TypeProjection(new TypeVariable(Collections.<Attribute>emptyList(), parameter)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitThisType(this, data);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TupleType extends TypeImpl {
|
||||
|
||||
public static final TupleType UNIT = new TupleType(Collections.<Attribute>emptyList(), Collections.<Type>emptyList());
|
||||
|
||||
public static TupleType getTupleType(List<Attribute> attributes, List<Type> arguments) {
|
||||
if (attributes.isEmpty() && arguments.isEmpty()) {
|
||||
return UNIT;
|
||||
}
|
||||
return new TupleType(attributes, arguments);
|
||||
}
|
||||
|
||||
|
||||
public static TupleType getTupleType(List<Type> arguments) {
|
||||
return getTupleType(Collections.<Attribute>emptyList(), arguments);
|
||||
}
|
||||
|
||||
public static TupleType getLabeledTupleType(List<Attribute> attributes, List<ParameterDescriptor> arguments) {
|
||||
return getTupleType(attributes, toTypes(arguments));
|
||||
}
|
||||
|
||||
|
||||
public static TupleType getLabeledTupleType(List<ParameterDescriptor> arguments) {
|
||||
return getLabeledTupleType(Collections.<Attribute>emptyList(), arguments);
|
||||
}
|
||||
|
||||
|
||||
private TupleType(List<Attribute> attributes, List<Type> arguments) {
|
||||
super(attributes, JetStandardClasses.getTuple(arguments.size()).getTypeConstructor(), toProjections(arguments));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new UnsupportedOperationException("Not implemented"); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitTupleType(this, data);
|
||||
}
|
||||
|
||||
private static List<TypeProjection> toProjections(List<Type> arguments) {
|
||||
List<TypeProjection> result = new ArrayList<TypeProjection>();
|
||||
for (Type argument : arguments) {
|
||||
result.add(new TypeProjection(ProjectionKind.OUT_ONLY, argument));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<Type> toTypes(List<ParameterDescriptor> labeledEntries) {
|
||||
List<Type> result = new ArrayList<Type>();
|
||||
for (ParameterDescriptor entry : labeledEntries) {
|
||||
result.add(entry.getType());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface Type extends Annotated {
|
||||
TypeConstructor getConstructor();
|
||||
List<TypeProjection> getArguments();
|
||||
@NotNull TypeConstructor getConstructor();
|
||||
@NotNull List<TypeProjection> getArguments();
|
||||
boolean isNullable();
|
||||
|
||||
Collection<MemberDescriptor> getMembers();
|
||||
@NotNull TypeMemberDomain getMemberDomain();
|
||||
|
||||
<R, D> R accept(TypeVisitor<R, D> visitor, D data);
|
||||
<R> R acceptNoData(TypeVisitor<R, ?> visitor);
|
||||
void acceptVoid(TypeVisitor<?, ?> visitor);
|
||||
@NotNull Type getNullableVersion();
|
||||
}
|
||||
|
||||
@@ -1,20 +1,38 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public abstract class TypeImpl extends VisitableTypeImpl {
|
||||
public final class TypeImpl extends AnnotatedImpl implements Type {
|
||||
|
||||
private final TypeConstructor constructor;
|
||||
private final List<TypeProjection> arguments;
|
||||
private final boolean nullable;
|
||||
private final TypeMemberDomain memberDomain;
|
||||
|
||||
public TypeImpl(List<Attribute> attributes, TypeConstructor constructor, List<TypeProjection> arguments) {
|
||||
public TypeImpl(List<Attribute> attributes, TypeConstructor constructor, boolean nullable, List<TypeProjection> arguments, TypeMemberDomain memberDomain) {
|
||||
super(attributes);
|
||||
this.constructor = constructor;
|
||||
this.nullable = nullable;
|
||||
this.arguments = arguments;
|
||||
this.memberDomain = memberDomain;
|
||||
}
|
||||
|
||||
public TypeImpl(TypeConstructor constructor, TypeMemberDomain memberDomain) {
|
||||
this(Collections.<Attribute>emptyList(), constructor, false, Collections.<TypeProjection>emptyList(), memberDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getNullableVersion() {
|
||||
if (isNullable()) {
|
||||
return this;
|
||||
}
|
||||
// TODO: cache these?
|
||||
return new TypeImpl(getAttributes(), constructor, true, arguments, memberDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -27,9 +45,19 @@ public abstract class TypeImpl extends VisitableTypeImpl {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeMemberDomain getMemberDomain() {
|
||||
return memberDomain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return constructor + (arguments.isEmpty() ? "" : "<" + argumentsToString() + ">");
|
||||
return constructor + (arguments.isEmpty() ? "" : "<" + argumentsToString() + ">") + (isNullable() ? "?" : "");
|
||||
}
|
||||
|
||||
private StringBuilder argumentsToString() {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface TypeMemberDomain {
|
||||
TypeMemberDomain EMPTY = new TypeMemberDomain() {
|
||||
@Override
|
||||
public ClassDescriptor getClassDescriptor(@NotNull Type type) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable ClassDescriptor getClassDescriptor(@NotNull Type type);
|
||||
// ...
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class TypeParameterDescriptor extends NamedAnnotatedImpl {
|
||||
// TODO: Should we actually pass the attributes on to the type constructor?
|
||||
this.typeConstructor = new TypeConstructor(
|
||||
attributes,
|
||||
name,
|
||||
"&" + name,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
upperBounds);
|
||||
}
|
||||
@@ -35,4 +35,9 @@ public class TypeParameterDescriptor extends NamedAnnotatedImpl {
|
||||
public TypeConstructor getTypeConstructor() {
|
||||
return typeConstructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return typeConstructor.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeVariable extends TypeImpl {
|
||||
|
||||
private final TypeParameterDescriptor typeParameterDescriptor;
|
||||
|
||||
public TypeVariable(@NotNull List<Attribute> attributes, @NotNull TypeParameterDescriptor typeParameter) {
|
||||
super(attributes, typeParameter.getTypeConstructor(), Collections.<TypeProjection>emptyList());
|
||||
this.typeParameterDescriptor = typeParameter;
|
||||
}
|
||||
|
||||
public TypeParameterDescriptor getTypeParameterDescriptor() {
|
||||
return typeParameterDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitTypeVariable(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "&" + super.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeVisitor<R, D> {
|
||||
public R visitNothingType(NothingType nothingType, D data) {
|
||||
return visitType(nothingType, data);
|
||||
}
|
||||
|
||||
public R visitTupleType(TupleType tupleType, D data) {
|
||||
return visitType(tupleType, data);
|
||||
}
|
||||
|
||||
public R visitTypeVariable(TypeVariable typeVariable, D data) {
|
||||
return visitType(typeVariable, data);
|
||||
}
|
||||
|
||||
public R visitClassType(ClassType classType, D data) {
|
||||
return visitType(classType, data);
|
||||
}
|
||||
|
||||
public R visitThisType(ThisType thisType, D data) {
|
||||
return visitType(thisType, data);
|
||||
}
|
||||
|
||||
public R visitErrorType(ErrorType errorType, D data) {
|
||||
return visitType(errorType, data);
|
||||
}
|
||||
|
||||
public R visitNullableType(NullableType nullableType, D data) {
|
||||
return visitType(nullableType, data);
|
||||
}
|
||||
|
||||
public R visitType(Type type, D data) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public abstract class VisitableTypeImpl extends AnnotatedImpl implements Type {
|
||||
public VisitableTypeImpl(List<Attribute> attributes) {
|
||||
super(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R acceptNoData(TypeVisitor<R, ?> visitor) {
|
||||
return accept(visitor, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVoid(TypeVisitor<?, ?> visitor) {
|
||||
accept(visitor, null);
|
||||
}
|
||||
}
|
||||
@@ -29,33 +29,41 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
}
|
||||
|
||||
public void testConstants() throws Exception {
|
||||
assertType("1", JetStandardTypes.getInt());
|
||||
assertType("0x1", JetStandardTypes.getInt());
|
||||
assertType("0X1", JetStandardTypes.getInt());
|
||||
assertType("0b1", JetStandardTypes.getInt());
|
||||
assertType("0B1", JetStandardTypes.getInt());
|
||||
assertType("1", JetStandardClasses.getIntType());
|
||||
assertType("0x1", JetStandardClasses.getIntType());
|
||||
assertType("0X1", JetStandardClasses.getIntType());
|
||||
assertType("0b1", JetStandardClasses.getIntType());
|
||||
assertType("0B1", JetStandardClasses.getIntType());
|
||||
|
||||
assertType("1l", JetStandardTypes.getLong());
|
||||
assertType("1L", JetStandardTypes.getLong());
|
||||
assertType("1l", JetStandardClasses.getLongType());
|
||||
assertType("1L", JetStandardClasses.getLongType());
|
||||
|
||||
assertType("1.0", JetStandardTypes.getDouble());
|
||||
assertType("1.0d", JetStandardTypes.getDouble());
|
||||
assertType("1.0D", JetStandardTypes.getDouble());
|
||||
assertType("0x1.fffffffffffffp1023", JetStandardTypes.getDouble());
|
||||
assertType("1.0", JetStandardClasses.getDoubleType());
|
||||
assertType("1.0d", JetStandardClasses.getDoubleType());
|
||||
assertType("1.0D", JetStandardClasses.getDoubleType());
|
||||
assertType("0x1.fffffffffffffp1023", JetStandardClasses.getDoubleType());
|
||||
|
||||
assertType("1.0f", JetStandardTypes.getFloat());
|
||||
assertType("1.0F", JetStandardTypes.getFloat());
|
||||
assertType("0x1.fffffffffffffp1023f", JetStandardTypes.getFloat());
|
||||
assertType("1.0f", JetStandardClasses.getFloatType());
|
||||
assertType("1.0F", JetStandardClasses.getFloatType());
|
||||
assertType("0x1.fffffffffffffp1023f", JetStandardClasses.getFloatType());
|
||||
|
||||
assertType("true", JetStandardTypes.getBoolean());
|
||||
assertType("false", JetStandardTypes.getBoolean());
|
||||
assertType("true", JetStandardClasses.getBooleanType());
|
||||
assertType("false", JetStandardClasses.getBooleanType());
|
||||
|
||||
assertType("'d'", JetStandardTypes.getChar());
|
||||
assertType("'d'", JetStandardClasses.getCharType());
|
||||
|
||||
assertType("\"d\"", JetStandardTypes.getString());
|
||||
assertType("\"\"\"d\"\"\"", JetStandardTypes.getString());
|
||||
assertType("\"d\"", JetStandardClasses.getStringType());
|
||||
assertType("\"\"\"d\"\"\"", JetStandardClasses.getStringType());
|
||||
|
||||
assertType("()", JetStandardTypes.getUnit());
|
||||
assertType("()", JetStandardClasses.getUnitType());
|
||||
|
||||
assertType("null", JetStandardClasses.getNullableNothingType());
|
||||
}
|
||||
|
||||
public void testTupleConstants() throws Exception {
|
||||
assertType("()", JetStandardClasses.getUnitType());
|
||||
|
||||
assertType("(1, 'a')", JetStandardClasses.getTupleType(JetStandardClasses.getIntType(), JetStandardClasses.getCharType()));
|
||||
}
|
||||
|
||||
public void testBasicSubtyping() throws Exception {
|
||||
@@ -170,7 +178,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
}
|
||||
|
||||
public void testImplicitConversions() throws Exception {
|
||||
assertConvertibleTo("1", JetStandardTypes.getByte());
|
||||
assertConvertibleTo("1", JetStandardClasses.getByteType());
|
||||
}
|
||||
|
||||
private static void assertSubtype(String type1, String type2) {
|
||||
@@ -184,7 +192,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
private static void assertSubtypingRelation(String type1, String type2, boolean expected) {
|
||||
Type typeNode1 = TypeResolver.INSTANCE.resolveType(ClassDefinitions.BASIC_SCOPE, JetChangeUtil.createType(getProject(), type1));
|
||||
Type typeNode2 = TypeResolver.INSTANCE.resolveType(ClassDefinitions.BASIC_SCOPE, JetChangeUtil.createType(getProject(), type2));
|
||||
boolean result = new JetTypeChecker().isSubtypeOf(
|
||||
boolean result = JetTypeChecker.INSTANCE.isSubtypeOf(
|
||||
typeNode1,
|
||||
typeNode2);
|
||||
String modifier = expected ? "not " : "";
|
||||
@@ -195,21 +203,21 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression);
|
||||
assertTrue(
|
||||
expression + " must be convertible to " + type,
|
||||
new JetTypeChecker().isConvertibleTo(jetExpression, type));
|
||||
JetTypeChecker.INSTANCE.isConvertibleTo(jetExpression, type));
|
||||
}
|
||||
|
||||
private static void assertNotConvertibleTo(String expression, Type type) {
|
||||
JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression);
|
||||
assertFalse(
|
||||
expression + " must not be convertible to " + type,
|
||||
new JetTypeChecker().isConvertibleTo(jetExpression, type));
|
||||
JetTypeChecker.INSTANCE.isConvertibleTo(jetExpression, type));
|
||||
}
|
||||
|
||||
private static void assertType(String expression, Type expectedType) {
|
||||
Project project = getProject();
|
||||
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
|
||||
Type type = new JetTypeChecker().getType(jetExpression);
|
||||
assertEquals(type, expectedType);
|
||||
Type type = JetTypeChecker.INSTANCE.getType(jetExpression);
|
||||
assertTrue(type + "!=" + expectedType, JetTypeChecker.INSTANCE.equalTypes(type, expectedType));
|
||||
}
|
||||
|
||||
private static class ClassDefinitions {
|
||||
|
||||
Reference in New Issue
Block a user