Type infrastructure simplified

This commit is contained in:
Andrey Breslav
2011-01-27 16:06:11 +03:00
parent ae854b1e38
commit 820563a283
18 changed files with 303 additions and 500 deletions
@@ -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 {