Typing for try-expression

This commit is contained in:
Andrey Breslav
2011-02-03 15:32:12 +03:00
parent 2e2c31ea00
commit 7b15eea98a
7 changed files with 70 additions and 13 deletions
+1 -1
View File
@@ -82,7 +82,7 @@ public interface JetNodeTypes {
JetNodeType THEN = new JetNodeType("THEN", JetContainerNode.class);
JetNodeType ELSE = new JetNodeType("ELSE", JetContainerNode.class);
JetNodeType TRY = new JetNodeType("TRY", JetTryExpression.class);
JetNodeType CATCH = new JetNodeType("CATCH", JetCatchSection.class);
JetNodeType CATCH = new JetNodeType("CATCH", JetCatchClause.class);
JetNodeType FINALLY = new JetNodeType("FINALLY", JetFinallySection.class);
JetNodeType FOR = new JetNodeType("FOR", JetForExpression.class);
JetNodeType WHILE = new JetNodeType("WHILE", JetWhileExpression.class);
@@ -3,6 +3,9 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
/**
* @author max
*/
@@ -15,4 +18,8 @@ public class JetBlockExpression extends JetExpression {
public void accept(JetVisitor visitor) {
visitor.visitBlockExpression(this);
}
public List<JetExpression> getStatements() {
return Arrays.asList(findChildrenByClass(JetExpression.class));
}
}
@@ -10,8 +10,8 @@ import java.util.List;
/**
* @author max
*/
public class JetCatchSection extends JetElement {
public JetCatchSection(@NotNull ASTNode node) {
public class JetCatchClause extends JetElement {
public JetCatchClause(@NotNull ASTNode node) {
super(node);
}
@@ -2,6 +2,10 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import java.util.List;
/**
* @author max
@@ -16,9 +20,19 @@ public class JetTryExpression extends JetExpression {
visitor.visitTryExpression(this);
}
public JetExpression getBody() {
return findChildByClass(JetExpression.class);
@NotNull
public JetExpression getTryBlock() {
return (JetExpression) findChildByType(JetNodeTypes.BLOCK);
}
@NotNull
public List<JetCatchClause> getCatchClauses() {
return findChildrenByType(JetNodeTypes.CATCH);
}
@Nullable
public JetFinallySection getFinallyBlock() {
return (JetFinallySection) findChildByType(JetNodeTypes.FINALLY);
}
}
@@ -250,8 +250,8 @@ public class JetVisitor extends PsiElementVisitor {
visitExpression(expression);
}
public void visitCatchSection(JetCatchSection catchSection) {
visitJetElement(catchSection);
public void visitCatchSection(JetCatchClause catchClause) {
visitJetElement(catchClause);
}
public void visitFinallySection(JetFinallySection finallySection) {
@@ -18,8 +18,6 @@ public class JetTypeChecker {
public static final JetTypeChecker INSTANCE = new JetTypeChecker();
/*
: if
: when
: try
: SimpleName
@@ -133,13 +131,30 @@ public class JetTypeChecker {
@Override
public void visitWhenExpression(JetWhenExpression expression) {
// TODO : what if there're sub-whens?
// TODO : what if there's "else continue"?
// TODO :change scope according to the bound value in the when header
List<Type> expressions = new ArrayList<Type>();
collectAllReturnTypes(expression, scope, expressions);
result[0] = commonSupertype(expressions);
}
@Override
public void visitTryExpression(JetTryExpression expression) {
JetExpression tryBlock = expression.getTryBlock();
List<JetCatchClause> catchClauses = expression.getCatchClauses();
JetFinallySection finallyBlock = expression.getFinallyBlock();
List<Type> types = new ArrayList<Type>();
if (finallyBlock == null) {
for (JetCatchClause catchClause : catchClauses) {
// TODO: change scope here
types.add(getType(scope, catchClause.getCatchBody()));
}
} else {
types.add(getType(scope, finallyBlock.getFinalExpression()));
}
types.add(getType(scope, tryBlock));
result[0] = commonSupertype(types);
}
@Override
public void visitTupleExpression(JetTupleExpression expression) {
List<JetExpression> entries = expression.getEntries();
@@ -151,6 +166,17 @@ public class JetTypeChecker {
result[0] = JetStandardClasses.getTupleType(types);
}
@Override
public void visitBlockExpression(JetBlockExpression expression) {
// TODO : this is a stub, consider function literals
List<JetExpression> statements = expression.getStatements();
if (statements.isEmpty()) {
result[0] = JetStandardClasses.getUnitType();
} else {
result[0] = getType(scope, statements.get(statements.size() - 1));
}
}
@Override
public void visitJetElement(JetElement elem) {
throw new IllegalArgumentException("Unsupported element: " + elem);
@@ -161,8 +187,9 @@ public class JetTypeChecker {
private void collectAllReturnTypes(JetWhenExpression whenExpression, JetScope scope, List<Type> result) {
for (JetWhenEntry entry : whenExpression.getEntries()) {
if (entry.getSubWhen() != null) {
collectAllReturnTypes(entry.getSubWhen(), scope, result);
JetWhenExpression subWhen = entry.getSubWhen();
if (subWhen != null) {
collectAllReturnTypes(subWhen, scope, result);
} else {
JetExpression resultExpression = entry.getExpression();
if (resultExpression != null) {
@@ -99,6 +99,15 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertType("when (1) { is 1 => 2; is 1 => '2'; is 1 => when(e) {is 1 => null}} ", "Any?");
}
public void testTry() throws Exception {
assertType("try {1} finally{2}", "Int");
assertType("try {1} catch (e : e) {'a'} finally{2}", "Int");
assertType("try {1} catch (e : e) {'a'} finally{'2'}", "Any");
assertType("try {1} catch (e : e) {'a'}", "Any");
assertType("try {1} catch (e : e) {'a'} catch (e : e) {null}", "Any?");
assertType("try {} catch (e : e) {}", "Unit");
}
public void testCommonSupertypes() throws Exception {
assertCommonSupertype("Int", "Int", "Int");