/* * Copyright (c) 2013, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.engine.constant; import com.google.dart.engine.ast.Expression; import com.google.dart.engine.internal.constant.ConstantVisitor; import com.google.dart.engine.internal.context.RecordingErrorListener; import com.google.dart.engine.internal.error.ErrorReporter; import com.google.dart.engine.internal.object.DartObjectImpl; import com.google.dart.engine.internal.resolver.TypeProvider; import com.google.dart.engine.source.Source; /** * Instances of the class {@code ConstantEvaluator} evaluate constant expressions to produce their * compile-time value. According to the Dart Language Specification: <blockquote> A constant * expression is one of the following: * <ul> * <li>A literal number.</li> * <li>A literal boolean.</li> * <li>A literal string where any interpolated expression is a compile-time constant that evaluates * to a numeric, string or boolean value or to <b>null</b>.</li> * <li>A literal symbol.</li> * <li><b>null</b>.</li> * <li>A qualified reference to a static constant variable.</li> * <li>An identifier expression that denotes a constant variable, class or type alias.</li> * <li>A constant constructor invocation.</li> * <li>A constant list literal.</li> * <li>A constant map literal.</li> * <li>A simple or qualified identifier denoting a top-level function or a static method.</li> * <li>A parenthesized expression <i>(e)</i> where <i>e</i> is a constant expression.</li> * <li>An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i> where * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions and <i>identical()</i> is * statically bound to the predefined dart function <i>identical()</i> discussed above.</li> * <li>An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or <i>e<sub>1</sub> * != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions * that evaluate to a numeric, string or boolean value.</li> * <li>An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> && e<sub>2</sub></i> or * <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>, <i>e1</sub></i> and <i>e2</sub></i> are * constant expressions that evaluate to a boolean value.</li> * <li>An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^ e<sub>2</sub></i>, * <i>e<sub>1</sub> & e<sub>2</sub></i>, <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> * >> e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, where <i>e</i>, * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions that evaluate to an * integer value or to <b>null</b>.</li> * <li>An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> + e<sub>2</sub></i>, * <i>e<sub>1</sub> -e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>, <i>e<sub>1</sub> / * e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> > * e<sub>2</sub></i>, <i>e<sub>1</sub> < e<sub>2</sub></i>, <i>e<sub>1</sub> >= * e<sub>2</sub></i>, <i>e<sub>1</sub> <= e<sub>2</sub></i> or <i>e<sub>1</sub> % * e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant * expressions that evaluate to a numeric value or to <b>null</b>.</li> * <li>An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub></i> where * <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and <i>e<sub>3</sub></i> are constant expressions, and * <i>e<sub>1</sub></i> evaluates to a boolean value.</li> * </ul> * </blockquote> */ public class ConstantEvaluator { /** * The source containing the expression(s) that will be evaluated. */ private Source source; /** * The type provider used to access the known types. */ private TypeProvider typeProvider; /** * Initialize a newly created evaluator to evaluate expressions in the given source. * * @param source the source containing the expression(s) that will be evaluated * @param typeProvider the type provider used to access known types */ public ConstantEvaluator(Source source, TypeProvider typeProvider) { this.source = source; this.typeProvider = typeProvider; } public EvaluationResult evaluate(Expression expression) { RecordingErrorListener errorListener = new RecordingErrorListener(); ErrorReporter errorReporter = new ErrorReporter(errorListener, source); DartObjectImpl result = expression.accept(new ConstantVisitor(typeProvider, errorReporter)); if (result != null) { return EvaluationResult.forValue(result); } return EvaluationResult.forErrors(errorListener.getErrors()); } }