| 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);
|
| - }
|
| -}
|
|
|