First typechecker test passed
This commit is contained in:
@@ -14,7 +14,7 @@ public class ClassDescriptor extends MemberDescriptorImpl implements MemberDomai
|
||||
|
||||
public ClassDescriptor(
|
||||
List<Annotation> annotations,
|
||||
String name, List<TypeParameterDescriptor> typeParameters, Collection<Type> superclasses) {
|
||||
String name, List<TypeParameterDescriptor> typeParameters, Collection<? extends Type> superclasses) {
|
||||
super(annotations, name);
|
||||
this.typeConstructor = new TypeConstructor(annotations, name, typeParameters, superclasses);
|
||||
}
|
||||
|
||||
@@ -30,4 +30,9 @@ public class ClassType extends TypeImpl {
|
||||
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,6 +1,10 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -24,48 +28,91 @@ public class JetStandardClasses {
|
||||
private static final ClassDescriptor DOUBLE = new ClassDescriptor("Double");
|
||||
private static final ClassDescriptor BOOLEAN = new ClassDescriptor("Boolean");
|
||||
private static final ClassDescriptor STRING = new ClassDescriptor("String");
|
||||
private static final ClassDescriptor UNIT = new ClassDescriptor("Unit");
|
||||
|
||||
public static final int TUPLE_COUNT = 22;
|
||||
private static final ClassDescriptor[] TUPLE = new ClassDescriptor[TUPLE_COUNT];
|
||||
static {
|
||||
for (int i = 0; i < TUPLE_COUNT; i++) {
|
||||
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
|
||||
for (int j = 0; j < i; j++) {
|
||||
parameters.add(new TypeParameterDescriptor(
|
||||
Collections.<Annotation>emptyList(),
|
||||
"T" + j,
|
||||
Variance.OUT_VARIANCE,
|
||||
Collections.<Type>emptySet()));
|
||||
}
|
||||
TUPLE[i] = new ClassDescriptor(
|
||||
Collections.<Annotation>emptyList(),
|
||||
"Tuple" + i,
|
||||
parameters,
|
||||
Collections.singleton(JetStandardClasses.getAnyType()));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getAny() {
|
||||
return ANY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassType getAnyType() {
|
||||
return ANY_TYPE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getByte() {
|
||||
return BYTE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getChar() {
|
||||
return CHAR;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getShort() {
|
||||
return SHORT;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getInt() {
|
||||
return INT;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getLong() {
|
||||
return LONG;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getFloat() {
|
||||
return FLOAT;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getDouble() {
|
||||
return DOUBLE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getBoolean() {
|
||||
return BOOLEAN;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getString() {
|
||||
return STRING;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getTuple(int size) {
|
||||
return TUPLE[size];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getLabeledTuple(int size) {
|
||||
// TODO
|
||||
return getTuple(size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -74,10 +76,6 @@ public class JetTypeChecker {
|
||||
return checkSubtypeForTheSameConstructor(closestSupertype, supertype);
|
||||
}
|
||||
|
||||
private boolean checkSubtypeForTheSameConstructor(Type closestSupertype, Type supertype) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
// This method returns the supertype of the first parameter that has the same constructor
|
||||
// as the second parameter, applying the substitution of type arguments to it
|
||||
@Nullable
|
||||
@@ -89,10 +87,44 @@ public class JetTypeChecker {
|
||||
for (Type immediateSupertype : constructor.getSupertypes()) {
|
||||
Type correspondingSupertype = findCorrespondingSupertype(immediateSupertype, supertype);
|
||||
if (correspondingSupertype != null) {
|
||||
return correspondingSupertype;
|
||||
return substituteForParameters(subtype, correspondingSupertype);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Type substituteForParameters(Type context, Type subject) {
|
||||
Map<TypeParameterDescriptor, TypeProjection> parameterValues = new HashMap<TypeParameterDescriptor, 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);
|
||||
}
|
||||
|
||||
return substitute(parameterValues, subject);
|
||||
}
|
||||
|
||||
private Type substitute(Map<TypeParameterDescriptor, TypeProjection> parameterValues, Type subject) {
|
||||
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
|
||||
for (TypeProjection argument : subject.getArguments()) {
|
||||
newArguments.add(new TypeProjection(argument.getProjection(), substitute(parameterValues, argument.getType())));
|
||||
}
|
||||
return specializeType(subject, newArguments);
|
||||
}
|
||||
|
||||
private Type specializeType(Type type, List<TypeProjection> newArguments) {
|
||||
// TODO
|
||||
return type;
|
||||
}
|
||||
|
||||
private boolean checkSubtypeForTheSameConstructor(Type subtype, Type supertype) {
|
||||
assert subtype.getConstructor().equals(supertype.getConstructor());
|
||||
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,4 +38,9 @@ public class NothingType extends TypeImpl {
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitNothingType(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,9 @@ public class ThisType extends TypeImpl {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,29 +10,8 @@ import java.util.List;
|
||||
*/
|
||||
public class TupleType extends TypeImpl {
|
||||
|
||||
public static final int TUPLE_COUNT = 22;
|
||||
private static final TypeConstructor[] TUPLE = new TypeConstructor[TUPLE_COUNT];
|
||||
|
||||
public static final TupleType UNIT = new TupleType(Collections.<Annotation>emptyList(), Collections.<Type>emptyList());
|
||||
|
||||
static {
|
||||
for (int i = 0; i < TUPLE_COUNT; i++) {
|
||||
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
|
||||
for (int j = 0; j < i; j++) {
|
||||
parameters.add(new TypeParameterDescriptor(
|
||||
Collections.<Annotation>emptyList(),
|
||||
"T" + j,
|
||||
Variance.OUT_VARIANCE,
|
||||
Collections.<Type>emptySet()));
|
||||
}
|
||||
TUPLE[i] = new TypeConstructor(
|
||||
Collections.<Annotation>emptyList(),
|
||||
"Tuple" + i,
|
||||
parameters,
|
||||
Collections.singleton(JetStandardTypes.getAny()));
|
||||
}
|
||||
}
|
||||
|
||||
public static TupleType getTupleType(List<Annotation> annotations, List<Type> arguments) {
|
||||
if (annotations.isEmpty() && arguments.isEmpty()) {
|
||||
return UNIT;
|
||||
@@ -56,7 +35,7 @@ public class TupleType extends TypeImpl {
|
||||
|
||||
|
||||
private TupleType(List<Annotation> annotations, List<Type> arguments) {
|
||||
super(annotations, TUPLE[arguments.size()], toProjections(arguments));
|
||||
super(annotations, JetStandardClasses.getTuple(arguments.size()).getTypeConstructor(), toProjections(arguments));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,6 +43,11 @@ public class TupleType extends TypeImpl {
|
||||
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) {
|
||||
|
||||
@@ -11,4 +11,8 @@ public interface Type extends Annotated {
|
||||
List<TypeProjection> getArguments();
|
||||
|
||||
Collection<MemberDescriptor> getMembers();
|
||||
|
||||
<R, D> R accept(TypeVisitor<R, D> visitor, D data);
|
||||
<R> R acceptNoData(TypeVisitor<R, ?> visitor);
|
||||
void acceptVoid(TypeVisitor<?, ?> visitor);
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ import java.util.List;
|
||||
*/
|
||||
public class TypeConstructor extends AnnotatedImpl {
|
||||
private final List<TypeParameterDescriptor> parameters;
|
||||
private final Collection<Type> supertypes;
|
||||
private final Collection<? extends Type> supertypes;
|
||||
private final String debugName;
|
||||
|
||||
public TypeConstructor(List<Annotation> annotations, String debugName, List<TypeParameterDescriptor> parameters, Collection<Type> supertypes) {
|
||||
public TypeConstructor(List<Annotation> annotations, String debugName, List<TypeParameterDescriptor> parameters, Collection<? extends Type> supertypes) {
|
||||
super(annotations);
|
||||
this.debugName = debugName;
|
||||
this.parameters = parameters;
|
||||
@@ -22,7 +22,7 @@ public class TypeConstructor extends AnnotatedImpl {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public Collection<Type> getSupertypes() {
|
||||
public Collection<? extends Type> getSupertypes() {
|
||||
return supertypes;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,4 +43,14 @@ public abstract class TypeImpl extends AnnotatedImpl implements Type {
|
||||
}
|
||||
return stringBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R acceptNoData(TypeVisitor<R, ?> visitor) {
|
||||
return accept(visitor, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVoid(TypeVisitor<?, ?> visitor) {
|
||||
accept(visitor, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,4 +19,9 @@ public class TypeVariable extends TypeImpl {
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new javax.help.UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitTypeVariable(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
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 visitType(Type type, D data) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,10 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
return JetStandardClasses.getFloat();
|
||||
} else if ("Double".equals(name)) {
|
||||
return JetStandardClasses.getDouble();
|
||||
} else if ("Unit".equals(name)) {
|
||||
return JetStandardClasses.getTuple(0);
|
||||
} else if ("Any".equals(name)) {
|
||||
return JetStandardClasses.getAny();
|
||||
}
|
||||
fail("Type not found: " + name);
|
||||
throw new IllegalStateException();
|
||||
@@ -92,6 +97,17 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
assertSubtype("Double", "Double");
|
||||
assertSubtype("Unit", "Unit");
|
||||
|
||||
assertSubtype("Boolean", "Any");
|
||||
assertSubtype("Byte", "Any");
|
||||
assertSubtype("Char", "Any");
|
||||
assertSubtype("Short", "Any");
|
||||
assertSubtype("Int", "Any");
|
||||
assertSubtype("Long", "Any");
|
||||
assertSubtype("Float", "Any");
|
||||
assertSubtype("Double", "Any");
|
||||
assertSubtype("Unit", "Any");
|
||||
assertSubtype("Any", "Any");
|
||||
|
||||
assertNotSubtype("Boolean", "Byte");
|
||||
assertNotSubtype("Byte", "Short");
|
||||
assertNotSubtype("Char", "Int");
|
||||
@@ -100,7 +116,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
assertNotSubtype("Long", "Double");
|
||||
assertNotSubtype("Float", "Double");
|
||||
assertNotSubtype("Double", "Int");
|
||||
assertNotSubtype("Unit", "Unit");
|
||||
assertNotSubtype("Unit", "Int");
|
||||
|
||||
assertSubtype("(Boolean)", "(Boolean)");
|
||||
assertSubtype("(Byte)", "(Byte)");
|
||||
@@ -128,14 +144,21 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
boolean result = new JetTypeChecker().isSubtypeOf(
|
||||
typeNode1,
|
||||
typeNode2);
|
||||
assertTrue(typeNode1 + " is not a subtype of " + typeNode2, result == expected);
|
||||
String modifier = expected ? "not " : "";
|
||||
assertTrue(typeNode1 + " is " + modifier + "a subtype of " + typeNode2, result == expected);
|
||||
}
|
||||
|
||||
private Type toType(JetTypeReference typeNode) {
|
||||
List<JetAttribute> attributes = typeNode.getAttributes();
|
||||
JetTypeElement typeElement = typeNode.getTypeElement();
|
||||
List<JetTypeReference> typeArguments = typeNode.getTypeArguments();
|
||||
List<JetTypeReference> argumentElements = typeNode.getTypeArguments();
|
||||
|
||||
final List<Type> arguments = new ArrayList<Type>();
|
||||
for (JetTypeReference argumentElement : argumentElements) {
|
||||
arguments.add(toType(argumentElement));
|
||||
}
|
||||
|
||||
// TODO annotations
|
||||
final Type[] result = new Type[1];
|
||||
typeElement.accept(new JetVisitor() {
|
||||
@Override
|
||||
@@ -143,9 +166,15 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
result[0] = new ClassType(TypeResolver.INSTANCE.resolveClass(BASIC_SCOPE, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTupleType(JetTupleType type) {
|
||||
// TODO labels
|
||||
result[0] = TupleType.getTupleType(arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetElement(JetElement elem) {
|
||||
throw new IllegalArgumentException();
|
||||
throw new IllegalArgumentException("Unsupported type: " + elem);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user