Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Unified Diff: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java

Issue 10501008: Infer types using 'v is! Type' (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweaks for comments Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
index d8aa5ffe67dcd2d3be7721b8c3075e79669f8918..72188ed21b731815613ae7d6e77e746a1982d1ca 100644
--- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
+++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
@@ -75,6 +75,7 @@ import com.google.dart.compiler.ast.DartRedirectConstructorInvocation;
import com.google.dart.compiler.ast.DartResourceDirective;
import com.google.dart.compiler.ast.DartReturnStatement;
import com.google.dart.compiler.ast.DartSourceDirective;
+import com.google.dart.compiler.ast.DartStatement;
import com.google.dart.compiler.ast.DartStringInterpolation;
import com.google.dart.compiler.ast.DartStringLiteral;
import com.google.dart.compiler.ast.DartSuperConstructorInvocation;
@@ -598,6 +599,99 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
}
+ /**
+ * @return <code>true</code> if we can prove that given {@link DartStatement} always leads to
+ * the exit from the enclosing function.
+ */
+ private static boolean isExitFromFunction(DartStatement statement) {
+ // "return" is always exit
+ if (statement instanceof DartReturnStatement) {
+ return true;
+ }
+ // "throw" is exit if no enclosing "try"
+ if (statement instanceof DartThrowStatement) {
+ for (DartNode p = statement; p != null && !(p instanceof DartFunction); p = p.getParent()) {
+ // TODO(scheglov) Can be enhanced:
+ // 1. check if there is "catch" block which can catch this exception;
+ // 2. even if there is such "catch", we will not visit the rest of the "try".
+ if (p instanceof DartTryStatement) {
+ return false;
+ }
+ }
+ return true;
+ }
+ // "block" is exit if its last statement is exit
+ if (statement instanceof DartBlock) {
+ DartBlock block = (DartBlock) statement;
+ List<DartStatement> statements = block.getStatements();
+ if (!statements.isEmpty()) {
+ return isExitFromFunction(statements.get(statements.size() - 1));
+ }
+ }
+ // can not prove that given statement is always exit
+ return false;
+ }
+
+ /**
+ * Helper for setting {@link Type}s of {@link VariableElement}s when given "condition" is NOT
+ * satisfied.
+ */
+ private static void inferVariableTypesFromIsNotConditions(DartExpression condition,
+ final VariableElementsRestorer variableRestorer) {
+ condition.accept(new ASTVisitor<Void>() {
+ boolean negation = false;
+
+ @Override
+ public Void visitUnaryExpression(DartUnaryExpression node) {
+ boolean negationOld = negation;
+ try {
+ if (node.getOperator() == Token.NOT) {
+ negation = !negation;
+ }
+ return super.visitUnaryExpression(node);
+ } finally {
+ negation = negationOld;
+ }
+ }
+
+ @Override
+ public Void visitBinaryExpression(DartBinaryExpression node) {
+ // analyze (v is Type)
+ if (node.getOperator() == Token.IS) {
+ DartExpression arg1 = node.getArg1();
+ DartExpression arg2 = node.getArg2();
+ if (arg1 instanceof DartIdentifier && arg1.getElement() instanceof VariableElement) {
+ VariableElement variableElement = (VariableElement) arg1.getElement();
+ // !(v is Type)
+ if (negation && arg2 instanceof DartTypeExpression) {
+ Type isType = arg2.getType();
+ Type varType = Types.makeInferred(isType);
+ variableRestorer.setType(variableElement, varType);
+ }
+ // (v is! Type)
+ if (!negation) {
+ if (arg2 instanceof DartUnaryExpression) {
+ DartUnaryExpression unary2 = (DartUnaryExpression) arg2;
+ if (unary2.getOperator() == Token.NOT
+ && unary2.getArg() instanceof DartTypeExpression) {
+ Type isType = unary2.getArg().getType();
+ Type varType = Types.makeInferred(isType);
+ variableRestorer.setType(variableElement, varType);
+ }
+ }
+ }
+ }
+ }
+ // visit || expressions
+ if (node.getOperator() == Token.OR) {
+ return super.visitBinaryExpression(node);
+ }
+ // other operators, such as && - don't infer types
+ return null;
+ }
+ });
+ }
+
private boolean checkAssignable(DartNode node, Type t, Type s) {
t.getClass(); // Null check.
s.getClass(); // Null check.
@@ -1287,8 +1381,26 @@ public class TypeAnalyzer implements DartCompilationPhase {
public Type visitIfStatement(DartIfStatement node) {
DartExpression condition = node.getCondition();
checkCondition(condition);
- visitConditionalNode(condition, node.getThenStatement());
- typeOf(node.getElseStatement());
+ // visit "then"
+ DartStatement thenStatement = node.getThenStatement();
+ visitConditionalNode(condition, thenStatement);
+ // visit "else"
+ {
+ DartStatement elseStatement = node.getElseStatement();
+ VariableElementsRestorer variableRestorer = new VariableElementsRestorer();
+ // if has "else", then types inferred from "is! Type" applied only to "else"
+ if (elseStatement != null) {
+ inferVariableTypesFromIsNotConditions(condition, variableRestorer);
+ typeOf(elseStatement);
+ variableRestorer.restore();
+ }
+ // if no "else", then inferred types applied to the end of the method
+ if (elseStatement == null && isExitFromFunction(thenStatement)) {
+ inferVariableTypesFromIsNotConditions(condition, variableRestorer);
+ }
+
+ }
+ // done
return voidType;
}
« no previous file with comments | « no previous file | compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698