Working on the type checker
This commit is contained in:
+11
-1
@@ -10,9 +10,19 @@ Foo<Bar<X>, T, Object> // user type
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
type
|
type
|
||||||
: attributes (selfType | functionType | userType | tupleType)
|
: attributes typeDescriptor
|
||||||
|
|
||||||
|
typeDescriptor
|
||||||
|
: selfType
|
||||||
|
: functionType
|
||||||
|
: userType
|
||||||
|
: tupleType
|
||||||
|
: nullableType
|
||||||
;
|
;
|
||||||
|
|
||||||
|
nullableType
|
||||||
|
: typeDescriptor "?"
|
||||||
|
|
||||||
selfType
|
selfType
|
||||||
: "This"
|
: "This"
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.jetbrains.jet.lang.annotations;
|
package org.jetbrains.jet.lang.annotations;
|
||||||
|
|
||||||
import com.intellij.lang.annotation.AnnotationHolder;
|
import com.intellij.lang.annotation.AnnotationHolder;
|
||||||
import com.intellij.lang.annotation.AnnotationSession;
|
|
||||||
import com.intellij.lang.annotation.Annotator;
|
import com.intellij.lang.annotation.Annotator;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -21,7 +20,7 @@ public class JetPsiChecker implements Annotator {
|
|||||||
// holder.createErrorAnnotation(property.getNameIdentifier(), "Specify either type or value");
|
// holder.createErrorAnnotation(property.getNameIdentifier(), "Specify either type or value");
|
||||||
JetFile file = (JetFile) element;
|
JetFile file = (JetFile) element;
|
||||||
String path = file.getProject().getBaseDir().getPath();
|
String path = file.getProject().getBaseDir().getPath();
|
||||||
System.out.println("Path: " + path);
|
println("Path: " + path);
|
||||||
JetNamespace rootNamespace = file.getRootNamespace();
|
JetNamespace rootNamespace = file.getRootNamespace();
|
||||||
List<JetDeclaration> declarations = rootNamespace.getDeclarations();
|
List<JetDeclaration> declarations = rootNamespace.getDeclarations();
|
||||||
|
|
||||||
@@ -54,10 +53,10 @@ public class JetPsiChecker implements Annotator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void print(Object o) {
|
private void print(Object o) {
|
||||||
System.out.print(o);
|
// System.out.print(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void println(Object o) {
|
private void println(Object o) {
|
||||||
System.out.println(o);
|
// System.out.println(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,11 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
* ;
|
* ;
|
||||||
*/
|
*/
|
||||||
public void parseExpression() {
|
public void parseExpression() {
|
||||||
|
// TODO: better recovery for expressions
|
||||||
|
if (atSet(RPAR, RBRACE, RBRACKET, GT)) {
|
||||||
|
error("Expecting an expression");
|
||||||
|
return;
|
||||||
|
}
|
||||||
parseBinaryExpression(Precedence.ASSIGNMENT);
|
parseBinaryExpression(Precedence.ASSIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import com.intellij.lang.PsiBuilder;
|
|||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public interface SemanticWhitespaceAwarePsiBuilder extends PsiBuilder {
|
public interface SemanticWhitespaceAwarePsiBuilder extends PsiBuilder {
|
||||||
// TODO: comments go to wrong place when an empty element is created
|
// TODO: comments go to wrong place when an empty element is created, see IElementType.isLeftBound()
|
||||||
|
|
||||||
boolean newlineBeforeCurrentToken();
|
boolean newlineBeforeCurrentToken();
|
||||||
void disableNewlines();
|
void disableNewlines();
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ public class JetChangeUtil {
|
|||||||
return property.getInitializer();
|
return property.getInitializer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JetTypeReference createType(Project project, String type) {
|
||||||
|
JetProperty property = createProperty(project, "val x : " + type);
|
||||||
|
return property.getPropertyTypeRef();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JetFile createFile(Project project, String text) {
|
public static JetFile createFile(Project project, String text) {
|
||||||
return (JetFile) PsiFileFactory.getInstance(project).createFileFromText("dummy.jet", JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true);
|
return (JetFile) PsiFileFactory.getInstance(project).createFileFromText("dummy.jet", JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class JetElement extends ASTWrapperPsiElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accept(JetVisitor visitor) {
|
public void accept(@NotNull JetVisitor visitor) {
|
||||||
visitor.visitJetElement(this);
|
visitor.visitJetElement(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,20 @@ public class JetTypeReference extends JetElement {
|
|||||||
return findChildrenByType(JetNodeTypes.ATTRIBUTE_ANNOTATION);
|
return findChildrenByType(JetNodeTypes.ATTRIBUTE_ANNOTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JetTypeElement getTypeElement() {
|
||||||
|
return findChildByClass(JetTypeElement.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetTypeArgumentList getTypeArgumentList() {
|
||||||
|
return findChildByClass(JetTypeArgumentList.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JetTypeReference> getTypeArguments() {
|
||||||
|
// TODO: empty elements in PSI
|
||||||
|
JetTypeArgumentList typeArgumentList = getTypeArgumentList();
|
||||||
|
return typeArgumentList == null ? Collections.<JetTypeReference>emptyList() : typeArgumentList.getArguments();
|
||||||
|
}
|
||||||
|
|
||||||
public List<JetAttribute> getAttributes() {
|
public List<JetAttribute> getAttributes() {
|
||||||
List<JetAttribute> answer = null;
|
List<JetAttribute> answer = null;
|
||||||
for (JetAttributeAnnotation annotation : getAttributeAnnotations()) {
|
for (JetAttributeAnnotation annotation : getAttributeAnnotations()) {
|
||||||
|
|||||||
@@ -62,4 +62,9 @@ public class JetTypeChecker {
|
|||||||
public boolean isConvertibleTo(JetExpression expression, Type type) {
|
public boolean isConvertibleTo(JetExpression expression, Type type) {
|
||||||
return false; //To change body of created methods use File | Settings | File Templates.
|
return false; //To change body of created methods use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSubtypeOf(Type subtype, Type supertype) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.jetbrains.jet.lang.types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class NamespaceDescriptor {
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
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<Annotation> annotations, ClassDescriptor thisClass) {
|
||||||
|
super(annotations, 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.<Annotation>emptyList(), parameter)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<MemberDescriptor> getMembers() {
|
||||||
|
throw new UnsupportedOperationException(); // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,10 @@ public class TypeProjection {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TypeProjection(Type type) {
|
||||||
|
this(Variance.INVARIANT, type);
|
||||||
|
}
|
||||||
|
|
||||||
public Variance getProjection() {
|
public Variance getProjection() {
|
||||||
return projection;
|
return projection;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
type Comparison<in T> = {(T, T) : Int}
|
type Comparison<in T> = {(T, T) : Int}
|
||||||
|
|
||||||
fun naturalOrder<in T : IComparable<T>>(a : T, b : T) : Int = a.compareTo(b)
|
fun naturalOrder<in T : Comparable<T>>(a : T, b : T) : Int = a.compareTo(b)
|
||||||
|
|
||||||
fun castingNaturalOrder(a : Object, b : Object) : Int = (a as Comparable<Object>).compareTo(b as Comparable<Object>)
|
fun castingNaturalOrder(a : Object, b : Object) : Int = (a as Comparable<Object>).compareTo(b as Comparable<Object>)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
interface class IComparable<in T> {
|
virtual class IComparable<in T> {
|
||||||
fun compareTo(other : T) : Int
|
fun compareTo(other : T) : Int
|
||||||
}
|
}
|
||||||
+2
-1
@@ -1,7 +1,8 @@
|
|||||||
package org.jetbrains.jet.parsing;
|
package org.jetbrains.jet.checkers;
|
||||||
|
|
||||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||||
import com.intellij.openapi.application.PathManager;
|
import com.intellij.openapi.application.PathManager;
|
||||||
|
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
+65
-4
@@ -1,15 +1,16 @@
|
|||||||
package org.jetbrains.jet.parsing;
|
package org.jetbrains.jet.types;
|
||||||
|
|
||||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||||
import com.intellij.openapi.application.PathManager;
|
import com.intellij.openapi.application.PathManager;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import org.jetbrains.jet.lang.psi.JetChangeUtil;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
|
||||||
import org.jetbrains.jet.lang.types.JetStandardTypes;
|
import org.jetbrains.jet.lang.types.JetStandardTypes;
|
||||||
import org.jetbrains.jet.lang.types.Type;
|
|
||||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||||
|
import org.jetbrains.jet.lang.types.Type;
|
||||||
|
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -55,6 +56,66 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
|||||||
assertType("()", JetStandardTypes.getUnit());
|
assertType("()", JetStandardTypes.getUnit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSubtyping() throws Exception {
|
||||||
|
assertSubtype("Boolean", "Boolean");
|
||||||
|
assertSubtype("Byte", "Byte");
|
||||||
|
assertSubtype("Char", "Char");
|
||||||
|
assertSubtype("Short", "Short");
|
||||||
|
assertSubtype("Int", "Int");
|
||||||
|
assertSubtype("Long", "Long");
|
||||||
|
assertSubtype("Float", "Float");
|
||||||
|
assertSubtype("Double", "Double");
|
||||||
|
assertSubtype("Unit", "Unit");
|
||||||
|
|
||||||
|
assertNotSubtype("Boolean", "Byte");
|
||||||
|
assertNotSubtype("Byte", "Short");
|
||||||
|
assertNotSubtype("Char", "Int");
|
||||||
|
assertNotSubtype("Short", "Int");
|
||||||
|
assertNotSubtype("Int", "Long");
|
||||||
|
assertNotSubtype("Long", "Double");
|
||||||
|
assertNotSubtype("Float", "Double");
|
||||||
|
assertNotSubtype("Double", "Int");
|
||||||
|
assertNotSubtype("Unit", "Unit");
|
||||||
|
|
||||||
|
assertSubtype("(Boolean)", "(Boolean)");
|
||||||
|
assertSubtype("(Byte)", "(Byte)");
|
||||||
|
assertSubtype("(Char)", "(Char)");
|
||||||
|
assertSubtype("(Short)", "(Short)");
|
||||||
|
assertSubtype("(Int)", "(Int)");
|
||||||
|
assertSubtype("(Long)", "(Long)");
|
||||||
|
assertSubtype("(Float)", "(Float)");
|
||||||
|
assertSubtype("(Double)", "(Double)");
|
||||||
|
assertSubtype("(Unit)", "(Unit)");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSubtype(String type1, String type2) {
|
||||||
|
assertSubtypingRelation(type1, type2, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertNotSubtype(String type1, String type2) {
|
||||||
|
assertSubtypingRelation(type1, type2, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSubtypingRelation(String type1, String type2, boolean expected) {
|
||||||
|
Type typeNode1 = toType(JetChangeUtil.createType(getProject(), type1));
|
||||||
|
Type typeNode2 = toType(JetChangeUtil.createType(getProject(), type2));
|
||||||
|
boolean result = new JetTypeChecker().isSubtypeOf(
|
||||||
|
typeNode1,
|
||||||
|
typeNode2);
|
||||||
|
assertTrue(typeNode1 + " is not 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();
|
||||||
|
|
||||||
|
typeElement.accept(new JetVisitor());
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
public void testImplicitConversions() throws Exception {
|
public void testImplicitConversions() throws Exception {
|
||||||
assertConvertibleTo("1", JetStandardTypes.getByte());
|
assertConvertibleTo("1", JetStandardTypes.getByte());
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user