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

Unified Diff: compiler/java/com/google/dart/compiler/resolver/CompileTimeConstVisitor.java

Issue 8523034: Compile Time Constants cycle check (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added new test to exercise code that was throwing ICE Created 9 years, 1 month 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
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);
- }
-}

Powered by Google App Engine
This is Rietveld 408576698