Index: compiler/java/com/google/dart/compiler/resolver/CompileTimeConstVisitor.java |
diff --git a/compiler/java/com/google/dart/compiler/resolver/CompileTimeConstVisitor.java b/compiler/java/com/google/dart/compiler/resolver/CompileTimeConstVisitor.java |
deleted file mode 100644 |
index a5e3dba613890d963cd49a99c4120e0a2dfc161a..0000000000000000000000000000000000000000 |
--- a/compiler/java/com/google/dart/compiler/resolver/CompileTimeConstVisitor.java |
+++ /dev/null |
@@ -1,410 +0,0 @@ |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-package com.google.dart.compiler.resolver; |
- |
-import com.google.dart.compiler.InternalCompilerException; |
-import com.google.dart.compiler.ast.DartArrayLiteral; |
-import com.google.dart.compiler.ast.DartBinaryExpression; |
-import com.google.dart.compiler.ast.DartExpression; |
-import com.google.dart.compiler.ast.DartFunction; |
-import com.google.dart.compiler.ast.DartFunctionObjectInvocation; |
-import com.google.dart.compiler.ast.DartIdentifier; |
-import com.google.dart.compiler.ast.DartInvocation; |
-import com.google.dart.compiler.ast.DartMapLiteral; |
-import com.google.dart.compiler.ast.DartMethodInvocation; |
-import com.google.dart.compiler.ast.DartNewExpression; |
-import com.google.dart.compiler.ast.DartNode; |
-import com.google.dart.compiler.ast.DartNodeTraverser; |
-import com.google.dart.compiler.ast.DartParenthesizedExpression; |
-import com.google.dart.compiler.ast.DartPropertyAccess; |
-import com.google.dart.compiler.ast.DartRedirectConstructorInvocation; |
-import com.google.dart.compiler.ast.DartStringInterpolation; |
-import com.google.dart.compiler.ast.DartSuperExpression; |
-import com.google.dart.compiler.ast.DartThisExpression; |
-import com.google.dart.compiler.ast.DartUnaryExpression; |
-import com.google.dart.compiler.ast.DartUnqualifiedInvocation; |
-import com.google.dart.compiler.type.Type; |
- |
-/** |
- * Given an expression, Determines if the expression matches all the rules for a |
- * compile-time constant expression and emits a resolution error if not. |
- * |
- * This script doesn't just resolve expressions, it also sets types to the |
- * extent needed to validate compile-time constant expressions (boolean, int, |
- * double, and string types might be set) |
- * |
- */ |
-public class CompileTimeConstVisitor extends DartNodeTraverser<Void> { |
- |
- static CompileTimeConstVisitor create(CoreTypeProvider typeProvider, ResolutionContext context) { |
- return new CompileTimeConstVisitor(typeProvider, context); |
- } |
- |
- private final ResolutionContext context; |
- |
- private final Type boolType; |
- private final Type doubleType; |
- private final Type intType; |
- private final Type numType; |
- private final Type stringType; |
- private final Type dynamicType; |
- |
- |
- private CompileTimeConstVisitor(CoreTypeProvider typeProvider, ResolutionContext context) { |
- this.context = context; |
- this.boolType = typeProvider.getBoolType(); |
- this.doubleType = typeProvider.getDoubleType(); |
- this.intType = typeProvider.getIntType(); |
- this.numType = typeProvider.getNumType(); |
- this.stringType = typeProvider.getStringType(); |
- this.dynamicType = typeProvider.getDynamicType(); |
- } |
- |
- private boolean checkBoolean(DartNode x, Type type) { |
- if (!type.equals(boolType)) { |
- context.onError(x, ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_BOOLEAN, |
- type.toString()); |
- return false; |
- } |
- return true; |
- } |
- |
- private boolean checkInt(DartNode x, Type type) { |
- if (!type.equals(intType)) { |
- context.onError(x, ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_INT, |
- type.toString()); |
- return false; |
- } |
- return true; |
- } |
- |
- private boolean checkNumber(DartNode x, Type type) { |
- if (!(type.equals(numType) || type.equals(intType) || type.equals(doubleType))) { |
- context.onError(x, ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_NUMBER, |
- type.toString()); |
- return false; |
- } |
- return true; |
- } |
- |
- private boolean checkNumberBooleanOrStringType(DartNode x, Type type) { |
- if (!type.equals(intType) && !type.equals(boolType) |
- && !type.equals(numType) && !type.equals(doubleType) && !type.equals(stringType)) { |
- context.onError(x, |
- ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_STRING_NUMBER_BOOL, |
- type.toString()); |
- return false; |
- } |
- return true; |
- } |
- |
- @Override |
- public Void visitBinaryExpression(DartBinaryExpression x) { |
- x.visitChildren(this); |
- |
- DartExpression lhs = x.getArg1(); |
- DartExpression rhs = x.getArg2(); |
- Type lhsType = getMostSpecificType(lhs); |
- Type rhsType = getMostSpecificType(rhs); |
- lhsType.getClass(); // fast null check |
- rhsType.getClass(); // fast null check |
- switch (x.getOperator()) { |
- case NE: |
- case EQ: |
- case NE_STRICT: |
- case EQ_STRICT: |
- if (checkNumberBooleanOrStringType(lhs, lhsType) |
- && checkNumberBooleanOrStringType(rhs, rhsType)) { |
- setType(x, boolType); |
- } |
- break; |
- |
- case AND: |
- case OR: |
- if (checkBoolean(lhs, lhsType) && checkBoolean(rhs, rhsType)) { |
- setType(x, boolType); |
- } |
- break; |
- |
- case BIT_NOT: |
- case TRUNC: |
- case BIT_XOR: |
- case BIT_AND: |
- case BIT_OR: |
- case SAR: |
- case SHL: |
- if (checkInt(lhs, lhsType) && checkInt(rhs, rhsType)) { |
- setType(x, intType); |
- } |
- break; |
- |
- case ADD: |
- case SUB: |
- case MUL: |
- case DIV: |
- case MOD: |
- if (checkNumber(lhs, lhsType) && checkNumber(rhs, rhsType)) { |
- setType(x, numType); |
- } |
- break; |
- case LT: |
- case GT: |
- case LTE: |
- case GTE: |
- if (checkNumber(lhs, lhsType) && checkNumber(rhs, rhsType)) { |
- setType(x, boolType); |
- } |
- break; |
- |
- default: |
- // all other operators... |
- expectedConstant(x); |
- } |
- return null; |
- } |
- |
- @Override |
- public Void visitParenthesizedExpression(DartParenthesizedExpression x) { |
- x.visitChildren(this); |
- Type type = getMostSpecificType(x.getExpression()); |
- setType(x, type); |
- return null; |
- } |
- |
- @Override |
- public Void visitPropertyAccess(DartPropertyAccess x) { |
- x.visitChildren(this); |
- switch (ElementKind.of(x.getQualifier().getSymbol())) { |
- case CLASS: |
- case LIBRARY: |
- case NONE: |
- // OK. |
- break; |
- default: |
- expectedConstant(x); |
- return null; |
- } |
- Element element = x.getName().getSymbol(); |
- if (element != null && !element.getModifiers().isConstant()) { |
- expectedConstant(x); |
- } |
- Type type = getMostSpecificType(x.getName()); |
- setType(x, type); |
- return null; |
- } |
- |
- @Override |
- public Void visitRedirectConstructorInvocation(DartRedirectConstructorInvocation x) { |
- Element element = x.getSymbol(); |
- if (element != null) { |
- if (!element.getModifiers().isConstant()) { |
- expectedConstant(x); |
- } |
- } |
- x.visitChildren(this); |
- return null; |
- } |
- |
- @Override |
- public Void visitStringInterpolation(DartStringInterpolation x) { |
- expectedConstant(x); |
- return null; |
- } |
- |
- @Override |
- public Void visitSuperExpression(DartSuperExpression x) { |
- // No need to traverse further - super() expressions are never constant |
- expectedConstant(x); |
- return null; |
- } |
- |
- @Override |
- public Void visitUnaryExpression(DartUnaryExpression x) { |
- x.visitChildren(this); |
- |
- Type type = getMostSpecificType(x.getArg()); |
- switch (x.getOperator()) { |
- case NOT: |
- if (checkBoolean(x, type)) { |
- x.setType(boolType); |
- } |
- break; |
- case SUB: |
- if (checkNumber(x, type)) { |
- x.setType(numType); |
- } |
- break; |
- case BIT_NOT: |
- if (checkInt(x, type)) { |
- x.setType(intType); |
- } |
- break; |
- default: |
- expectedConstant(x); |
- } |
- return null; |
- } |
- |
- @Override |
- public Void visitArrayLiteral(DartArrayLiteral x) { |
- if (!x.isConst()) { |
- expectedConstant(x); |
- } else { |
- x.visitChildren(this); |
- } |
- return null; |
- } |
- |
- @Override |
- public Void visitFunction(DartFunction x) { |
- // No need to traverse, functions are always disallowed. |
- expectedConstant(x); |
- return null; |
- } |
- |
- @Override |
- public Void visitFunctionObjectInvocation(DartFunctionObjectInvocation x) { |
- // No need to traverse, function object invocations are always disallowed. |
- expectedConstant(x); |
- return null; |
- } |
- |
- @Override |
- public Void visitIdentifier(DartIdentifier x) { |
- x.visitChildren(this); |
- |
- Element element = x.getSymbol(); |
- switch(ElementKind.of(element)) { |
- case CLASS: |
- case PARAMETER: |
- // OK |
- break; |
- case FIELD: |
- case CONSTRUCTOR: |
- case VARIABLE: |
- if (!element.getModifiers().isConstant()) { |
- expectedConstant(x); |
- } else { |
- setType(x, getMostSpecificType(x)); |
- } |
- break; |
- |
- case NONE: |
- Type type = getMostSpecificType(x); |
- if (dynamicType.equals(type)) { |
- // TODO(zundel) This is the case for unresolved identifiers that need to be recursively |
- // checked. |
- // expectedConstant(x); |
- } |
- setType(x, type); |
- break; |
- default: |
- throw new InternalCompilerException("Unexpected element " + x.toString() |
- + " kind: " + ElementKind.of(element) |
- + " evaluating type for compile-time constant expression."); |
- } |
- return null; |
- } |
- |
- |
- @Override |
- public Void visitInvocation(DartInvocation x) { |
- // No need to traverse, invocations are always disallowed. |
- expectedConstant(x); |
- return null; |
- } |
- |
- @Override |
- public Void visitMapLiteral(DartMapLiteral x) { |
- if (!x.isConst()) { |
- expectedConstant(x); |
- } else { |
- x.visitChildren(this); |
- } |
- return null; |
- } |
- |
- @Override |
- public Void visitMethodInvocation(DartMethodInvocation x) { |
- // No need to traverse, method invocations are always disallowed. |
- expectedConstant(x); |
- return null; |
- } |
- |
- @Override |
- public Void visitNewExpression(DartNewExpression x) { |
- if (!x.isConst()) { |
- expectedConstant(x); |
- } else { |
- x.visitChildren(this); |
- } |
- return null; |
- } |
- |
- |
- @Override |
- public Void visitThisExpression(DartThisExpression x) { |
- // No need to traverse, this expressions are always disallowed. |
- expectedConstant(x); |
- return null; |
- } |
- |
- @Override |
- public Void visitUnqualifiedInvocation(DartUnqualifiedInvocation x) { |
- // No need to traverse, always disallowed. |
- expectedConstant(x); |
- return null; |
- } |
- |
- /** |
- * Logs a general message "expected a constant expression" error. Use a more |
- * specific error message when possible. |
- */ |
- private void expectedConstant(DartNode x) { |
- context.onError(x, ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION); |
- } |
- |
- /** |
- * Determine the most specific type assigned to an expression node. Prefer the |
- * setting in the expression's symbol if present. Otherwise, use a type tagged |
- * in the expression node itself. |
- * |
- * @return a non <code>null</code> type value. Dynamic if none other can be |
- * determined. |
- */ |
- private Type getMostSpecificType(DartExpression expr) { |
- // TODO(zundel): this routine needs to recursively resolve as compile time constants any |
- // symbols that have not yet been resolved. |
- Element element = (Element)expr.getSymbol(); |
- switch (ElementKind.of(element)) { |
- case FIELD: |
- return ((FieldElement)element).getType(); |
- case METHOD: |
- return ((MethodElement)element).getType(); |
- case VARIABLE: |
- return((VariableElement)element).getType(); |
- case CONSTRUCTOR: |
- return ((ConstructorElement)element).getType(); |
- case NONE: |
- if (expr.getType() != null) { |
- return expr.getType(); |
- } |
- return dynamicType; |
- default: |
- throw new InternalCompilerException("Unexpected element " + expr.toString() |
- + " kind: " + ElementKind.of(element) |
- + "evaluating type for compile-time constant expression."); |
- } |
- } |
- |
- private void setType(DartExpression x, Type type) { |
- Element element = (Element)x.getSymbol(); |
- if (element != null) { |
- Elements.setType(element, type); |
- } |
- // Also set on the expression node itself. Not every expression has a symbol. |
- x.setType(type); |
- } |
-} |