/*
* 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());
}
}