First typechecker test passed

This commit is contained in:
Andrey Breslav
2011-01-25 17:28:55 +03:00
parent fb48cacf29
commit ef977e02e4
13 changed files with 191 additions and 35 deletions
@@ -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);
}
});