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

Unified Diff: pkg/analyzer/lib/src/generated/constant.dart

Issue 622743002: New analyzer snapshot. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months 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: pkg/analyzer/lib/src/generated/constant.dart
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 45a774bbc4693bd9a2b85544b80eb55f05a8d311..89a8848485ebb0a14f5f6bfe79fde08e66249f3c 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -11,12 +11,12 @@ import 'dart:collection';
import 'java_core.dart';
import 'java_engine.dart' show ObjectUtilities;
import 'source.dart' show Source;
-import 'error.dart' show AnalysisError, ErrorCode, CompileTimeErrorCode;
+import 'error.dart';
import 'scanner.dart' show Token, TokenType;
import 'ast.dart';
import 'element.dart';
import 'resolver.dart' show TypeProvider;
-import 'engine.dart' show AnalysisEngine;
+import 'engine.dart' show AnalysisEngine, RecordingErrorListener;
import 'utilities_dart.dart' show ParameterKind;
import 'utilities_collection.dart';
@@ -208,16 +208,13 @@ class ConstantEvaluator {
ConstantEvaluator(this._source, this._typeProvider);
EvaluationResult evaluate(Expression expression) {
- EvaluationResultImpl result = expression.accept(new ConstantVisitor.con1(_typeProvider));
- if (result is ValidResult) {
- return EvaluationResult.forValue(result.value);
- }
- List<AnalysisError> errors = new List<AnalysisError>();
- for (ErrorResult_ErrorData data in (result as ErrorResult).errorData) {
- AstNode node = data.node;
- errors.add(new AnalysisError.con2(_source, node.offset, node.length, data.errorCode, []));
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
+ DartObjectImpl result = expression.accept(new ConstantVisitor.con1(_typeProvider, errorReporter));
+ if (result != null) {
+ return EvaluationResult.forValue(result);
}
- return EvaluationResult.forErrors(new List.from(errors));
+ return EvaluationResult.forErrors(errorListener.errors);
}
}
@@ -427,7 +424,7 @@ class ConstantValueComputer {
referenceGraph.addNode(expression);
ConstructorElement constructor = expression.staticElement;
if (constructor == null) {
- break;
+ continue;
}
constructor = _followConstantRedirectionChain(constructor);
ConstructorDeclaration declaration = findConstructorDeclaration(constructor);
@@ -477,7 +474,7 @@ class ConstantValueComputer {
* Create the ConstantVisitor used to evaluate constants. Unit tests will override this method to
* introduce additional error checking.
*/
- ConstantVisitor createConstantVisitor() => new ConstantVisitor.con1(typeProvider);
+ ConstantVisitor createConstantVisitor(ErrorReporter errorReporter) => new ConstantVisitor.con1(typeProvider, errorReporter);
ConstructorDeclaration findConstructorDeclaration(ConstructorElement constructor) => constructorDeclarationMap[_getConstructorBase(constructor)];
@@ -549,19 +546,25 @@ class ConstantValueComputer {
if (constNode is VariableDeclaration) {
VariableDeclaration declaration = constNode;
Element element = declaration.element;
- EvaluationResultImpl result = declaration.initializer.accept(createConstantVisitor());
- (element as VariableElementImpl).evaluationResult = result;
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ ErrorReporter errorReporter = new ErrorReporter(errorListener, element.source);
+ DartObjectImpl dartObject = declaration.initializer.accept(createConstantVisitor(errorReporter));
+ (element as VariableElementImpl).evaluationResult = new EvaluationResultImpl.con2(dartObject, errorListener.errors);
} else if (constNode is InstanceCreationExpression) {
InstanceCreationExpression expression = constNode;
ConstructorElement constructor = expression.staticElement;
if (constructor == null) {
// Couldn't resolve the constructor so we can't compute a value. No problem--the error
- // has already been reported.
+ // has already been reported. But we still need to store an evaluation result.
+ expression.evaluationResult = new EvaluationResultImpl.con1(null);
return;
}
- ConstantVisitor constantVisitor = createConstantVisitor();
- EvaluationResultImpl result = _evaluateConstructorCall(constNode, expression.argumentList.arguments, constructor, constantVisitor);
- expression.evaluationResult = result;
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ CompilationUnit sourceCompilationUnit = expression.getAncestor((node) => node is CompilationUnit);
+ ErrorReporter errorReporter = new ErrorReporter(errorListener, sourceCompilationUnit.element.source);
+ ConstantVisitor constantVisitor = createConstantVisitor(errorReporter);
+ DartObjectImpl result = _evaluateConstructorCall(constNode, expression.argumentList.arguments, constructor, constantVisitor, errorReporter);
+ expression.evaluationResult = new EvaluationResultImpl.con2(result, errorListener.errors);
} else if (constNode is ConstructorDeclaration) {
ConstructorDeclaration declaration = constNode;
NodeList<ConstructorInitializer> initializers = declaration.initializers;
@@ -573,8 +576,10 @@ class ConstantValueComputer {
ParameterElement element = parameter.element;
Expression defaultValue = parameter.defaultValue;
if (defaultValue != null) {
- EvaluationResultImpl result = defaultValue.accept(createConstantVisitor());
- (element as ParameterElementImpl).evaluationResult = result;
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ ErrorReporter errorReporter = new ErrorReporter(errorListener, element.source);
+ DartObjectImpl dartObject = defaultValue.accept(createConstantVisitor(errorReporter));
+ (element as ParameterElementImpl).evaluationResult = new EvaluationResultImpl.con2(dartObject, errorListener.errors);
}
}
} else {
@@ -591,9 +596,9 @@ class ConstantValueComputer {
* @param builtInDefaultValue Value that should be used as the default if no "defaultValue"
* argument appears in [namedArgumentValues].
* @param namedArgumentValues Named parameters passed to fromEnvironment()
- * @return A [ValidResult] object corresponding to the evaluated result
+ * @return A [DartObjectImpl] object corresponding to the evaluated result
*/
- ValidResult _computeValueFromEnvironment(DartObject environmentValue, DartObjectImpl builtInDefaultValue, HashMap<String, DartObjectImpl> namedArgumentValues) {
+ DartObjectImpl _computeValueFromEnvironment(DartObject environmentValue, DartObjectImpl builtInDefaultValue, HashMap<String, DartObjectImpl> namedArgumentValues) {
DartObjectImpl value = environmentValue as DartObjectImpl;
if (value.isUnknown || value.isNull) {
// The name either doesn't exist in the environment or we couldn't parse the corresponding
@@ -608,10 +613,10 @@ class ConstantValueComputer {
} else {
}
}
- return new ValidResult(value);
+ return value;
}
- EvaluationResultImpl _evaluateConstructorCall(AstNode node, NodeList<Expression> arguments, ConstructorElement constructor, ConstantVisitor constantVisitor) {
+ DartObjectImpl _evaluateConstructorCall(AstNode node, NodeList<Expression> arguments, ConstructorElement constructor, ConstantVisitor constantVisitor, ErrorReporter errorReporter) {
int argumentCount = arguments.length;
List<DartObjectImpl> argumentValues = new List<DartObjectImpl>(argumentCount);
HashMap<String, DartObjectImpl> namedArgumentValues = new HashMap<String, DartObjectImpl>();
@@ -633,7 +638,8 @@ class ConstantValueComputer {
// const factory constructor that we can emulate.
if (constructor.name == "fromEnvironment") {
if (!_checkFromEnvironmentArguments(arguments, argumentValues, namedArgumentValues, definingClass)) {
- return new ErrorResult.con1(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ errorReporter.reportErrorForNode(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node, []);
+ return null;
}
String variableName = argumentCount < 1 ? null : argumentValues[0].stringValue;
if (identical(definingClass, typeProvider.boolType)) {
@@ -651,10 +657,11 @@ class ConstantValueComputer {
}
} else if (constructor.name == "" && identical(definingClass, typeProvider.symbolType) && argumentCount == 1) {
if (!_checkSymbolArguments(arguments, argumentValues, namedArgumentValues)) {
- return new ErrorResult.con1(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ errorReporter.reportErrorForNode(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node, []);
+ return null;
}
String argumentValue = argumentValues[0].stringValue;
- return constantVisitor._valid(definingClass, new SymbolState(argumentValue));
+ return new DartObjectImpl(definingClass, new SymbolState(argumentValue));
}
// Either it's an external const factory constructor that we can't emulate, or an error
// occurred (a cycle, or a const constructor trying to delegate to a non-const constructor).
@@ -693,11 +700,11 @@ class ConstantValueComputer {
// use the default value.
beforeGetParameterDefault(parameter);
EvaluationResultImpl evaluationResult = (parameter as ParameterElementImpl).evaluationResult;
- if (evaluationResult is ValidResult) {
- argumentValue = evaluationResult.value;
- } else if (evaluationResult == null) {
+ if (evaluationResult == null) {
// No default was provided, so the default value is null.
argumentValue = constantVisitor.null2;
+ } else if (evaluationResult.value != null) {
+ argumentValue = evaluationResult.value;
}
}
if (argumentValue != null) {
@@ -713,18 +720,17 @@ class ConstantValueComputer {
}
}
}
- ConstantVisitor initializerVisitor = new ConstantVisitor.con2(typeProvider, parameterMap);
+ ConstantVisitor initializerVisitor = new ConstantVisitor.con2(typeProvider, parameterMap, errorReporter);
String superName = null;
NodeList<Expression> superArguments = null;
for (ConstructorInitializer initializer in initializers) {
if (initializer is ConstructorFieldInitializer) {
ConstructorFieldInitializer constructorFieldInitializer = initializer;
Expression initializerExpression = constructorFieldInitializer.expression;
- EvaluationResultImpl evaluationResult = initializerExpression.accept(initializerVisitor);
- if (evaluationResult is ValidResult) {
- DartObjectImpl value = evaluationResult.value;
+ DartObjectImpl evaluationResult = initializerExpression.accept(initializerVisitor);
+ if (evaluationResult != null) {
String fieldName = constructorFieldInitializer.fieldName.name;
- fieldMap[fieldName] = value;
+ fieldMap[fieldName] = evaluationResult;
}
} else if (initializer is SuperConstructorInvocation) {
SuperConstructorInvocation superConstructorInvocation = initializer;
@@ -743,18 +749,17 @@ class ConstantValueComputer {
if (superArguments == null) {
superArguments = new NodeList<Expression>(null);
}
- _evaluateSuperConstructorCall(node, fieldMap, superConstructor, superArguments, initializerVisitor);
+ _evaluateSuperConstructorCall(node, fieldMap, superConstructor, superArguments, initializerVisitor, errorReporter);
}
}
- return constantVisitor._valid(definingClass, new GenericState(fieldMap));
+ return new DartObjectImpl(definingClass, new GenericState(fieldMap));
}
- void _evaluateSuperConstructorCall(AstNode node, HashMap<String, DartObjectImpl> fieldMap, ConstructorElement superConstructor, NodeList<Expression> superArguments, ConstantVisitor initializerVisitor) {
+ void _evaluateSuperConstructorCall(AstNode node, HashMap<String, DartObjectImpl> fieldMap, ConstructorElement superConstructor, NodeList<Expression> superArguments, ConstantVisitor initializerVisitor, ErrorReporter errorReporter) {
if (superConstructor != null && superConstructor.isConst) {
- EvaluationResultImpl evaluationResult = _evaluateConstructorCall(node, superArguments, superConstructor, initializerVisitor);
- if (evaluationResult is ValidResult) {
- ValidResult validResult = evaluationResult;
- fieldMap[GenericState.SUPERCLASS_FIELD] = validResult.value;
+ DartObjectImpl evaluationResult = _evaluateConstructorCall(node, superArguments, superConstructor, initializerVisitor, errorReporter);
+ if (evaluationResult != null) {
+ fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
}
}
}
@@ -825,8 +830,7 @@ class ConstantValueComputer {
class ConstantValueComputer_InitializerCloner extends AstCloner {
@override
InstanceCreationExpression visitInstanceCreationExpression(InstanceCreationExpression node) {
- // All we need is the evaluation result, and the keyword so that we know whether it's const.
- InstanceCreationExpression expression = new InstanceCreationExpression(node.keyword, null, null);
+ InstanceCreationExpression expression = super.visitInstanceCreationExpression(node);
expression.evaluationResult = node.evaluationResult;
return expression;
}
@@ -889,7 +893,7 @@ class ConstantValueComputer_InitializerCloner extends AstCloner {
* <i>e<sub>1</sub></i> evaluates to a boolean value.
* </blockquote>
*/
-class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
+class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
/**
* The type provider used to access the known types.
*/
@@ -903,14 +907,25 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
HashMap<String, DartObjectImpl> _lexicalEnvironment;
/**
+ * Error reporter that we use to report errors accumulated while computing the constant.
+ */
+ final ErrorReporter _errorReporter;
+
+ /**
+ * Helper class used to compute constant values.
+ */
+ DartObjectComputer _dartObjectComputer;
+
+ /**
* Initialize a newly created constant visitor.
*
* @param typeProvider the type provider used to access known types
* @param lexicalEnvironment values which should override simpleIdentifiers, or null if no
* overriding is necessary.
*/
- ConstantVisitor.con1(this._typeProvider) {
+ ConstantVisitor.con1(this._typeProvider, this._errorReporter) {
this._lexicalEnvironment = null;
+ this._dartObjectComputer = new DartObjectComputer(_errorReporter, _typeProvider);
}
/**
@@ -920,192 +935,201 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
* @param lexicalEnvironment values which should override simpleIdentifiers, or null if no
* overriding is necessary.
*/
- ConstantVisitor.con2(this._typeProvider, HashMap<String, DartObjectImpl> lexicalEnvironment) {
+ ConstantVisitor.con2(this._typeProvider, HashMap<String, DartObjectImpl> lexicalEnvironment, this._errorReporter) {
this._lexicalEnvironment = lexicalEnvironment;
+ this._dartObjectComputer = new DartObjectComputer(_errorReporter, _typeProvider);
}
@override
- EvaluationResultImpl visitAdjacentStrings(AdjacentStrings node) {
- EvaluationResultImpl result = null;
+ DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
+ DartObjectImpl result = null;
for (StringLiteral string in node.strings) {
if (result == null) {
result = string.accept(this);
} else {
- result = result.concatenate(_typeProvider, node, string.accept(this));
+ result = _dartObjectComputer.concatenate(node, result, string.accept(this));
}
}
return result;
}
@override
- EvaluationResultImpl visitBinaryExpression(BinaryExpression node) {
- EvaluationResultImpl leftResult = node.leftOperand.accept(this);
- EvaluationResultImpl rightResult = node.rightOperand.accept(this);
+ DartObjectImpl visitBinaryExpression(BinaryExpression node) {
+ DartObjectImpl leftResult = node.leftOperand.accept(this);
+ DartObjectImpl rightResult = node.rightOperand.accept(this);
TokenType operatorType = node.operator.type;
// 'null' is almost never good operand
if (operatorType != TokenType.BANG_EQ && operatorType != TokenType.EQ_EQ) {
- if (leftResult is ValidResult && leftResult.isNull || rightResult is ValidResult && rightResult.isNull) {
- return _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ if (leftResult != null && leftResult.isNull || rightResult != null && rightResult.isNull) {
+ _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ return null;
}
}
// evaluate operator
while (true) {
if (operatorType == TokenType.AMPERSAND) {
- return leftResult.bitAnd(_typeProvider, node, rightResult);
+ return _dartObjectComputer.bitAnd(node, leftResult, rightResult);
} else if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
- return leftResult.logicalAnd(_typeProvider, node, rightResult);
+ return _dartObjectComputer.logicalAnd(node, leftResult, rightResult);
} else if (operatorType == TokenType.BANG_EQ) {
- return leftResult.notEqual(_typeProvider, node, rightResult);
+ return _dartObjectComputer.notEqual(node, leftResult, rightResult);
} else if (operatorType == TokenType.BAR) {
- return leftResult.bitOr(_typeProvider, node, rightResult);
+ return _dartObjectComputer.bitOr(node, leftResult, rightResult);
} else if (operatorType == TokenType.BAR_BAR) {
- return leftResult.logicalOr(_typeProvider, node, rightResult);
+ return _dartObjectComputer.logicalOr(node, leftResult, rightResult);
} else if (operatorType == TokenType.CARET) {
- return leftResult.bitXor(_typeProvider, node, rightResult);
+ return _dartObjectComputer.bitXor(node, leftResult, rightResult);
} else if (operatorType == TokenType.EQ_EQ) {
- return leftResult.equalEqual(_typeProvider, node, rightResult);
+ return _dartObjectComputer.equalEqual(node, leftResult, rightResult);
} else if (operatorType == TokenType.GT) {
- return leftResult.greaterThan(_typeProvider, node, rightResult);
+ return _dartObjectComputer.greaterThan(node, leftResult, rightResult);
} else if (operatorType == TokenType.GT_EQ) {
- return leftResult.greaterThanOrEqual(_typeProvider, node, rightResult);
+ return _dartObjectComputer.greaterThanOrEqual(node, leftResult, rightResult);
} else if (operatorType == TokenType.GT_GT) {
- return leftResult.shiftRight(_typeProvider, node, rightResult);
+ return _dartObjectComputer.shiftRight(node, leftResult, rightResult);
} else if (operatorType == TokenType.LT) {
- return leftResult.lessThan(_typeProvider, node, rightResult);
+ return _dartObjectComputer.lessThan(node, leftResult, rightResult);
} else if (operatorType == TokenType.LT_EQ) {
- return leftResult.lessThanOrEqual(_typeProvider, node, rightResult);
+ return _dartObjectComputer.lessThanOrEqual(node, leftResult, rightResult);
} else if (operatorType == TokenType.LT_LT) {
- return leftResult.shiftLeft(_typeProvider, node, rightResult);
+ return _dartObjectComputer.shiftLeft(node, leftResult, rightResult);
} else if (operatorType == TokenType.MINUS) {
- return leftResult.minus(_typeProvider, node, rightResult);
+ return _dartObjectComputer.minus(node, leftResult, rightResult);
} else if (operatorType == TokenType.PERCENT) {
- return leftResult.remainder(_typeProvider, node, rightResult);
+ return _dartObjectComputer.remainder(node, leftResult, rightResult);
} else if (operatorType == TokenType.PLUS) {
- return leftResult.add(_typeProvider, node, rightResult);
+ return _dartObjectComputer.add(node, leftResult, rightResult);
} else if (operatorType == TokenType.STAR) {
- return leftResult.times(_typeProvider, node, rightResult);
+ return _dartObjectComputer.times(node, leftResult, rightResult);
} else if (operatorType == TokenType.SLASH) {
- return leftResult.divide(_typeProvider, node, rightResult);
+ return _dartObjectComputer.divide(node, leftResult, rightResult);
} else if (operatorType == TokenType.TILDE_SLASH) {
- return leftResult.integerDivide(_typeProvider, node, rightResult);
+ return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
} else {
// TODO(brianwilkerson) Figure out which error to report.
- return _error(node, null);
+ _error(node, null);
+ return null;
}
break;
}
}
@override
- EvaluationResultImpl visitBooleanLiteral(BooleanLiteral node) => _valid(_typeProvider.boolType, BoolState.from(node.value));
+ DartObjectImpl visitBooleanLiteral(BooleanLiteral node) => new DartObjectImpl(_typeProvider.boolType, BoolState.from(node.value));
@override
- EvaluationResultImpl visitConditionalExpression(ConditionalExpression node) {
+ DartObjectImpl visitConditionalExpression(ConditionalExpression node) {
Expression condition = node.condition;
- EvaluationResultImpl conditionResult = condition.accept(this);
- EvaluationResultImpl thenResult = node.thenExpression.accept(this);
- EvaluationResultImpl elseResult = node.elseExpression.accept(this);
- if (conditionResult is ErrorResult) {
- return _union(_union(conditionResult as ErrorResult, thenResult), elseResult);
- } else if (!(conditionResult as ValidResult).isBool) {
- return new ErrorResult.con1(condition, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
- } else if (thenResult is ErrorResult) {
- return _union(thenResult, elseResult);
- } else if (elseResult is ErrorResult) {
+ DartObjectImpl conditionResult = condition.accept(this);
+ DartObjectImpl thenResult = node.thenExpression.accept(this);
+ DartObjectImpl elseResult = node.elseExpression.accept(this);
+ if (conditionResult == null) {
+ return conditionResult;
+ } else if (!conditionResult.isBool) {
+ _errorReporter.reportErrorForNode(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, condition, []);
+ return null;
+ } else if (thenResult == null) {
+ return thenResult;
+ } else if (elseResult == null) {
return elseResult;
}
- conditionResult = conditionResult.applyBooleanConversion(_typeProvider, condition);
- if (conditionResult is ErrorResult) {
+ conditionResult = _dartObjectComputer.applyBooleanConversion(condition, conditionResult);
+ if (conditionResult == null) {
return conditionResult;
}
- ValidResult validResult = conditionResult as ValidResult;
- if (validResult.isTrue) {
+ if (conditionResult.isTrue) {
return thenResult;
- } else if (validResult.isFalse) {
+ } else if (conditionResult.isFalse) {
return elseResult;
}
- InterfaceType thenType = (thenResult as ValidResult).value.type;
- InterfaceType elseType = (elseResult as ValidResult).value.type;
+ InterfaceType thenType = thenResult.type;
+ InterfaceType elseType = elseResult.type;
return _validWithUnknownValue(thenType.getLeastUpperBound(elseType) as InterfaceType);
}
@override
- EvaluationResultImpl visitDoubleLiteral(DoubleLiteral node) => _valid(_typeProvider.doubleType, new DoubleState(node.value));
+ DartObjectImpl visitDoubleLiteral(DoubleLiteral node) => new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value));
@override
- EvaluationResultImpl visitInstanceCreationExpression(InstanceCreationExpression node) {
+ DartObjectImpl visitInstanceCreationExpression(InstanceCreationExpression node) {
if (!node.isConst) {
// TODO(brianwilkerson) Figure out which error to report.
- return _error(node, null);
+ _error(node, null);
+ return null;
}
beforeGetEvaluationResult(node);
EvaluationResultImpl result = node.evaluationResult;
if (result != null) {
- return result;
+ return result.value;
}
// TODO(brianwilkerson) Figure out which error to report.
- return _error(node, null);
+ _error(node, null);
+ return null;
}
@override
- EvaluationResultImpl visitIntegerLiteral(IntegerLiteral node) => _valid(_typeProvider.intType, new IntState(node.value));
+ DartObjectImpl visitIntegerLiteral(IntegerLiteral node) => new DartObjectImpl(_typeProvider.intType, new IntState(node.value));
@override
- EvaluationResultImpl visitInterpolationExpression(InterpolationExpression node) {
- EvaluationResultImpl result = node.expression.accept(this);
- if (result is ValidResult && !result.isBoolNumStringOrNull) {
- return _error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+ DartObjectImpl visitInterpolationExpression(InterpolationExpression node) {
+ DartObjectImpl result = node.expression.accept(this);
+ if (result != null && !result.isBoolNumStringOrNull) {
+ _error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+ return null;
}
- return result.performToString(_typeProvider, node);
+ return _dartObjectComputer.performToString(node, result);
}
@override
- EvaluationResultImpl visitInterpolationString(InterpolationString node) => _valid(_typeProvider.stringType, new StringState(node.value));
+ DartObjectImpl visitInterpolationString(InterpolationString node) => new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
@override
- EvaluationResultImpl visitListLiteral(ListLiteral node) {
+ DartObjectImpl visitListLiteral(ListLiteral node) {
if (node.constKeyword == null) {
- return new ErrorResult.con1(node, CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL);
+ _errorReporter.reportErrorForNode(CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL, node, []);
+ return null;
}
- ErrorResult result = null;
+ bool errorOccurred = false;
List<DartObjectImpl> elements = new List<DartObjectImpl>();
for (Expression element in node.elements) {
- EvaluationResultImpl elementResult = element.accept(this);
- result = _union(result, elementResult);
- if (elementResult is ValidResult) {
- elements.add(elementResult.value);
+ DartObjectImpl elementResult = element.accept(this);
+ if (elementResult == null) {
+ errorOccurred = true;
+ } else {
+ elements.add(elementResult);
}
}
- if (result != null) {
- return result;
+ if (errorOccurred) {
+ return null;
}
- return _valid(_typeProvider.listType, new ListState(new List.from(elements)));
+ return new DartObjectImpl(_typeProvider.listType, new ListState(new List.from(elements)));
}
@override
- EvaluationResultImpl visitMapLiteral(MapLiteral node) {
+ DartObjectImpl visitMapLiteral(MapLiteral node) {
if (node.constKeyword == null) {
- return new ErrorResult.con1(node, CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL);
+ _errorReporter.reportErrorForNode(CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, node, []);
+ return null;
}
- ErrorResult result = null;
+ bool errorOccurred = false;
HashMap<DartObjectImpl, DartObjectImpl> map = new HashMap<DartObjectImpl, DartObjectImpl>();
for (MapLiteralEntry entry in node.entries) {
- EvaluationResultImpl keyResult = entry.key.accept(this);
- EvaluationResultImpl valueResult = entry.value.accept(this);
- result = _union(result, keyResult);
- result = _union(result, valueResult);
- if (keyResult is ValidResult && valueResult is ValidResult) {
- map[keyResult.value] = valueResult.value;
+ DartObjectImpl keyResult = entry.key.accept(this);
+ DartObjectImpl valueResult = entry.value.accept(this);
+ if (keyResult == null || valueResult == null) {
+ errorOccurred = true;
+ } else {
+ map[keyResult] = valueResult;
}
}
- if (result != null) {
- return result;
+ if (errorOccurred) {
+ return null;
}
- return _valid(_typeProvider.mapType, new MapState(map));
+ return new DartObjectImpl(_typeProvider.mapType, new MapState(map));
}
@override
- EvaluationResultImpl visitMethodInvocation(MethodInvocation node) {
+ DartObjectImpl visitMethodInvocation(MethodInvocation node) {
Element element = node.methodName.staticElement;
if (element is FunctionElement) {
FunctionElement function = element;
@@ -1116,39 +1140,50 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
if (enclosingElement is CompilationUnitElement) {
LibraryElement library = enclosingElement.library;
if (library.isDartCore) {
- EvaluationResultImpl leftArgument = arguments[0].accept(this);
- EvaluationResultImpl rightArgument = arguments[1].accept(this);
- return leftArgument.equalEqual(_typeProvider, node, rightArgument);
+ DartObjectImpl leftArgument = arguments[0].accept(this);
+ DartObjectImpl rightArgument = arguments[1].accept(this);
+ return _dartObjectComputer.equalEqual(node, leftArgument, rightArgument);
}
}
}
}
}
// TODO(brianwilkerson) Figure out which error to report.
- return _error(node, null);
+ _error(node, null);
+ return null;
}
@override
- EvaluationResultImpl visitNamedExpression(NamedExpression node) => node.expression.accept(this);
+ DartObjectImpl visitNamedExpression(NamedExpression node) => node.expression.accept(this);
@override
- EvaluationResultImpl visitNode(AstNode node) => _error(node, null);
+ DartObjectImpl visitNode(AstNode node) {
+ // TODO(brianwilkerson) Figure out which error to report.
+ _error(node, null);
+ return null;
+ }
@override
- EvaluationResultImpl visitNullLiteral(NullLiteral node) => new ValidResult(null2);
+ DartObjectImpl visitNullLiteral(NullLiteral node) => null2;
@override
- EvaluationResultImpl visitParenthesizedExpression(ParenthesizedExpression node) => node.expression.accept(this);
+ DartObjectImpl visitParenthesizedExpression(ParenthesizedExpression node) => node.expression.accept(this);
@override
- EvaluationResultImpl visitPrefixedIdentifier(PrefixedIdentifier node) {
- // validate prefix
+ DartObjectImpl visitPrefixedIdentifier(PrefixedIdentifier node) {
+ // TODO(brianwilkerson) Uncomment the lines below when the new constant support can be added.
+ // Element element = node.getStaticElement();
+ // if (isStringLength(element)) {
+ // EvaluationResultImpl target = node.getPrefix().accept(this);
+ // return target.stringLength(typeProvider, node);
+ // }
SimpleIdentifier prefixNode = node.prefix;
Element prefixElement = prefixNode.staticElement;
if (prefixElement is! PrefixElement) {
- EvaluationResultImpl prefixResult = prefixNode.accept(this);
- if (prefixResult is! ValidResult) {
- return _error(node, null);
+ DartObjectImpl prefixResult = prefixNode.accept(this);
+ if (prefixResult == null) {
+ // The error has already been reported.
+ return null;
}
}
// validate prefixed identifier
@@ -1156,55 +1191,67 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
}
@override
- EvaluationResultImpl visitPrefixExpression(PrefixExpression node) {
- EvaluationResultImpl operand = node.operand.accept(this);
- if (operand is ValidResult && operand.isNull) {
- return _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ DartObjectImpl visitPrefixExpression(PrefixExpression node) {
+ DartObjectImpl operand = node.operand.accept(this);
+ if (operand != null && operand.isNull) {
+ _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ return null;
}
while (true) {
if (node.operator.type == TokenType.BANG) {
- return operand.logicalNot(_typeProvider, node);
+ return _dartObjectComputer.logicalNot(node, operand);
} else if (node.operator.type == TokenType.TILDE) {
- return operand.bitNot(_typeProvider, node);
+ return _dartObjectComputer.bitNot(node, operand);
} else if (node.operator.type == TokenType.MINUS) {
- return operand.negated(_typeProvider, node);
+ return _dartObjectComputer.negated(node, operand);
} else {
// TODO(brianwilkerson) Figure out which error to report.
- return _error(node, null);
+ _error(node, null);
+ return null;
}
break;
}
}
@override
- EvaluationResultImpl visitPropertyAccess(PropertyAccess node) => _getConstantValue(node, node.propertyName.staticElement);
+ DartObjectImpl visitPropertyAccess(PropertyAccess node) {
+ Element element = node.propertyName.staticElement;
+ // TODO(brianwilkerson) Uncomment the lines below when the new constant support can be added.
+ // if (isStringLength(element)) {
+ // EvaluationResultImpl target = node.getRealTarget().accept(this);
+ // return target.stringLength(typeProvider, node);
+ // }
+ return _getConstantValue(node, element);
+ }
@override
- EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) {
+ DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) {
if (_lexicalEnvironment != null && _lexicalEnvironment.containsKey(node.name)) {
- return new ValidResult(_lexicalEnvironment[node.name]);
+ return _lexicalEnvironment[node.name];
}
return _getConstantValue(node, node.staticElement);
}
@override
- EvaluationResultImpl visitSimpleStringLiteral(SimpleStringLiteral node) => _valid(_typeProvider.stringType, new StringState(node.value));
+ DartObjectImpl visitSimpleStringLiteral(SimpleStringLiteral node) => new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
@override
- EvaluationResultImpl visitStringInterpolation(StringInterpolation node) {
- EvaluationResultImpl result = null;
+ DartObjectImpl visitStringInterpolation(StringInterpolation node) {
+ DartObjectImpl result = null;
+ bool first = true;
for (InterpolationElement element in node.elements) {
- if (result == null) {
+ if (first) {
result = element.accept(this);
+ first = false;
} else {
- result = result.concatenate(_typeProvider, node, element.accept(this));
+ result = _dartObjectComputer.concatenate(node, result, element.accept(this));
}
}
return result;
}
@override
- EvaluationResultImpl visitSymbolLiteral(SymbolLiteral node) {
+ DartObjectImpl visitSymbolLiteral(SymbolLiteral node) {
JavaStringBuilder builder = new JavaStringBuilder();
List<Token> components = node.components;
for (int i = 0; i < components.length; i++) {
@@ -1213,7 +1260,7 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
}
builder.append(components[i].lexeme);
}
- return _valid(_typeProvider.symbolType, new SymbolState(builder.toString()));
+ return new DartObjectImpl(_typeProvider.symbolType, new SymbolState(builder.toString()));
}
/**
@@ -1235,22 +1282,20 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
return _nullObject;
}
- ValidResult _valid(InterfaceType type, InstanceState state) => new ValidResult(new DartObjectImpl(type, state));
-
- ValidResult _validWithUnknownValue(InterfaceType type) {
+ DartObjectImpl _validWithUnknownValue(InterfaceType type) {
if (type.element.library.isDartCore) {
String typeName = type.name;
if (typeName == "bool") {
- return _valid(type, BoolState.UNKNOWN_VALUE);
+ return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
} else if (typeName == "double") {
- return _valid(type, DoubleState.UNKNOWN_VALUE);
+ return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
} else if (typeName == "int") {
- return _valid(type, IntState.UNKNOWN_VALUE);
+ return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
} else if (typeName == "String") {
- return _valid(type, StringState.UNKNOWN_VALUE);
+ return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
}
}
- return _valid(type, GenericState.UNKNOWN_VALUE);
+ return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
}
/**
@@ -1261,21 +1306,22 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
* @return the value of the given expression
*/
DartObjectImpl _valueOf(Expression expression) {
- EvaluationResultImpl expressionValue = expression.accept(this);
- if (expressionValue is ValidResult) {
- return expressionValue.value;
+ DartObjectImpl expressionValue = expression.accept(this);
+ if (expressionValue != null) {
+ return expressionValue;
}
return null2;
}
/**
- * Return a result object representing an error associated with the given node.
+ * Create an error associated with the given node.
*
* @param node the AST node associated with the error
* @param code the error code indicating the nature of the error
- * @return a result object representing an error associated with the given node
*/
- ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node, code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code);
+ void _error(AstNode node, ErrorCode code) {
+ _errorReporter.reportErrorForNode(code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code, node, []);
+ }
/**
* Return the constant value of the static constant represented by the given element.
@@ -1284,7 +1330,7 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
* @param element the element whose value is to be returned
* @return the constant value of the static constant
*/
- EvaluationResultImpl _getConstantValue(AstNode node, Element element) {
+ DartObjectImpl _getConstantValue(AstNode node, Element element) {
if (element is PropertyAccessorElement) {
element = (element as PropertyAccessorElement).variable;
}
@@ -1293,38 +1339,37 @@ class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
beforeGetEvaluationResult(node);
EvaluationResultImpl value = variableElementImpl.evaluationResult;
if (variableElementImpl.isConst && value != null) {
- return value;
+ return value.value;
}
} else if (element is ExecutableElement) {
ExecutableElement function = element;
if (function.isStatic) {
- return _valid(_typeProvider.functionType, new FunctionState(function));
+ return new DartObjectImpl(_typeProvider.functionType, new FunctionState(function));
}
} else if (element is ClassElement || element is FunctionTypeAliasElement) {
- return _valid(_typeProvider.typeType, new TypeState(element));
+ return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
}
// TODO(brianwilkerson) Figure out which error to report.
- return _error(node, null);
+ _error(node, null);
+ return null;
}
/**
- * Return the union of the errors encoded in the given results.
+ * Return `true` if the given element represents the 'length' getter in class 'String'.
*
- * @param leftResult the first set of errors, or `null` if there was no previous collection
- * of errors
- * @param rightResult the errors to be added to the collection, or a valid result if there are no
- * errors to be added
- * @return the union of the errors encoded in the given results
- */
- ErrorResult _union(ErrorResult leftResult, EvaluationResultImpl rightResult) {
- if (rightResult is ErrorResult) {
- if (leftResult != null) {
- return new ErrorResult.con2(leftResult, rightResult);
- } else {
- return rightResult;
- }
+ * @param element the element being tested.
+ * @return
+ */
+ bool _isStringLength(Element element) {
+ if (element is! PropertyAccessorElement) {
+ return false;
}
- return leftResult;
+ PropertyAccessorElement accessor = element as PropertyAccessorElement;
+ if (!accessor.isGetter || accessor.name != "length") {
+ return false;
+ }
+ Element parent = accessor.enclosingElement;
+ return parent == _typeProvider.stringType.element;
}
}
@@ -1411,6 +1456,324 @@ abstract class DartObject {
}
/**
+ * Instances of the class `DartObjectComputer` contain methods for manipulating instances of a
+ * Dart class and for collecting errors during evaluation.
+ */
+class DartObjectComputer {
+ /**
+ * The error reporter that we are using to collect errors.
+ */
+ final ErrorReporter _errorReporter;
+
+ /**
+ * The type provider. Used to create objects of the appropriate types, and to identify when an
+ * object is of a built-in type.
+ */
+ final TypeProvider _typeProvider;
+
+ DartObjectComputer(this._errorReporter, this._typeProvider);
+
+ DartObjectImpl add(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.add(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the result of applying boolean conversion to this result.
+ *
+ * @param node the node against which errors should be reported
+ * @return the result of applying boolean conversion to the given value
+ */
+ DartObjectImpl applyBooleanConversion(AstNode node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.convertToBool(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl bitAnd(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.bitAnd(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl bitNot(Expression node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.bitNot(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl bitOr(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.bitOr(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl bitXor(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.bitXor(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl concatenate(Expression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.concatenate(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl divide(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.divide(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl equalEqual(Expression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.equalEqual(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl greaterThan(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.greaterThan(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl greaterThanOrEqual(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl integerDivide(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.integerDivide(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl lessThan(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.lessThan(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl lessThanOrEqual(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl logicalAnd(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.logicalAnd(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl logicalNot(Expression node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.logicalNot(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl logicalOr(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.logicalOr(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl minus(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.minus(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl negated(Expression node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.negated(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl notEqual(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.notEqual(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl performToString(AstNode node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.performToString(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl remainder(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.remainder(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl shiftLeft(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.shiftLeft(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl shiftRight(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.shiftRight(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the result of invoking the 'length' getter on this result.
+ *
+ * @param node the node against which errors should be reported
+ * @return the result of invoking the 'length' getter on this result
+ */
+ EvaluationResultImpl stringLength(Expression node, EvaluationResultImpl evaluationResult) {
+ if (evaluationResult.value != null) {
+ try {
+ return new EvaluationResultImpl.con1(evaluationResult.value.stringLength(_typeProvider));
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return new EvaluationResultImpl.con1(null);
+ }
+
+ DartObjectImpl times(BinaryExpression node, DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.times(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node, []);
+ }
+ }
+ return null;
+ }
+}
+
+/**
* Instances of the class `DartObjectImpl` represent an instance of a Dart class.
*/
class DartObjectImpl implements DartObject {
@@ -1448,6 +1811,8 @@ class DartObjectImpl implements DartObject {
return new DartObjectImpl(typeProvider.doubleType, result);
} else if (result is NumState) {
return new DartObjectImpl(typeProvider.numType, result);
+ } else if (result is StringState) {
+ return new DartObjectImpl(typeProvider.stringType, result);
}
// We should never get here.
throw new IllegalStateException("add returned a ${result.runtimeType.toString()}");
@@ -1839,6 +2204,15 @@ class DartObjectImpl implements DartObject {
DartObjectImpl shiftRight(TypeProvider typeProvider, DartObjectImpl rightOperand) => new DartObjectImpl(typeProvider.intType, _state.shiftRight(rightOperand._state));
/**
+ * Return the result of invoking the 'length' getter on this object.
+ *
+ * @param typeProvider the type provider used to find known types
+ * @return the result of invoking the 'length' getter on this object
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
+ */
+ DartObjectImpl stringLength(TypeProvider typeProvider) => new DartObjectImpl(typeProvider.intType, _state.stringLength());
+
+ /**
* Return the result of invoking the '*' operator on this object with the given argument.
*
* @param typeProvider the type provider used to find known types
@@ -2438,788 +2812,439 @@ class DynamicState extends InstanceState {
}
/**
- * Instances of the class `ErrorResult` represent the result of evaluating an expression that
- * is not a valid compile time constant.
+ * Instances of the class `EvaluationException` represent a run-time exception that would be
+ * thrown during the evaluation of Dart code.
*/
-class ErrorResult extends EvaluationResultImpl {
+class EvaluationException extends JavaException {
/**
- * The errors that prevent the expression from being a valid compile time constant.
+ * The error code associated with the exception.
*/
- List<ErrorResult_ErrorData> _errors = new List<ErrorResult_ErrorData>();
+ final ErrorCode errorCode;
/**
- * Initialize a newly created result representing the error with the given code reported against
- * the given node.
+ * Initialize a newly created exception to have the given error code.
*
- * @param node the node against which the error should be reported
- * @param errorCode the error code for the error to be generated
+ * @param errorCode the error code associated with the exception
*/
- ErrorResult.con1(AstNode node, ErrorCode errorCode) {
- _errors.add(new ErrorResult_ErrorData(node, errorCode));
- }
+ EvaluationException(this.errorCode);
+}
+/**
+ * Instances of the class `EvaluationResult` represent the result of attempting to evaluate an
+ * expression.
+ */
+class EvaluationResult {
/**
- * Initialize a newly created result to represent the union of the errors in the given result
- * objects.
+ * Return an evaluation result representing the result of evaluating an expression that is not a
+ * compile-time constant because of the given errors.
*
- * @param firstResult the first set of results being merged
- * @param secondResult the second set of results being merged
+ * @param errors the errors that should be reported for the expression(s) that were evaluated
+ * @return the result of evaluating an expression that is not a compile-time constant
*/
- ErrorResult.con2(ErrorResult firstResult, ErrorResult secondResult) {
- _errors.addAll(firstResult._errors);
- _errors.addAll(secondResult._errors);
- }
-
- @override
- EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.addToError(node, this);
-
- @override
- EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode node) => this;
+ static EvaluationResult forErrors(List<AnalysisError> errors) => new EvaluationResult(null, errors);
- @override
- EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitAndError(node, this);
+ /**
+ * Return an evaluation result representing the result of evaluating an expression that is a
+ * compile-time constant that evaluates to the given value.
+ *
+ * @param value the value of the expression
+ * @return the result of evaluating an expression that is a compile-time constant
+ */
+ static EvaluationResult forValue(DartObject value) => new EvaluationResult(value, null);
- @override
- EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node) => this;
+ /**
+ * The value of the expression.
+ */
+ final DartObject value;
- @override
- EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitOrError(node, this);
+ /**
+ * The errors that should be reported for the expression(s) that were evaluated.
+ */
+ final List<AnalysisError> _errors;
- @override
- EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitXorError(node, this);
+ /**
+ * Initialize a newly created result object with the given state. Clients should use one of the
+ * factory methods: [forErrors] and [forValue].
+ *
+ * @param value the value of the expression
+ * @param errors the errors that should be reported for the expression(s) that were evaluated
+ */
+ EvaluationResult(this.value, this._errors);
- @override
- EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, EvaluationResultImpl rightOperand) => rightOperand.concatenateError(node, this);
+ /**
+ * Return an array containing the errors that should be reported for the expression(s) that were
+ * evaluated. If there are no such errors, the array will be empty. The array can be empty even if
+ * the expression is not a valid compile time constant if the errors would have been reported by
+ * other parts of the analysis engine.
+ */
+ List<AnalysisError> get errors => _errors == null ? AnalysisError.NO_ERRORS : _errors;
- @override
- EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.divideError(node, this);
-
- @override
- EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, EvaluationResultImpl rightOperand) => rightOperand.equalEqualError(node, this);
-
- @override
- bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) => false;
-
- List<ErrorResult_ErrorData> get errorData => _errors;
-
- @override
- EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanError(node, this);
-
- @override
- EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanOrEqualError(node, this);
-
- @override
- EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.integerDivideError(node, this);
-
- @override
- EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
-
- @override
- EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.lessThanError(node, this);
-
- @override
- EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.lessThanOrEqualError(node, this);
-
- @override
- EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.logicalAndError(node, this);
-
- @override
- EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node) => this;
-
- @override
- EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.logicalOrError(node, this);
-
- @override
- EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.minusError(node, this);
-
- @override
- EvaluationResultImpl negated(TypeProvider typeProvider, Expression node) => this;
-
- @override
- EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.notEqualError(node, this);
-
- @override
- EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node) => this;
-
- @override
- EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.remainderError(node, this);
-
- @override
- EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.shiftLeftError(node, this);
-
- @override
- EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.shiftRightError(node, this);
-
- @override
- EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.timesError(node, this);
-
- @override
- EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
-
- @override
- EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
-
- @override
- EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
-
- @override
- EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
-
- @override
- EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
-
- @override
- EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
-
- @override
- EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
-
- @override
- EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
-
- @override
- EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
-
- @override
- EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression node, ValidResult leftOperand) => this;
-
- @override
- EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
-
- @override
- EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
-
- @override
- EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ /**
+ * Return `true` if the expression is a compile-time constant expression that would not
+ * throw an exception when evaluated.
+ *
+ * @return `true` if the expression is a valid compile-time constant expression
+ */
+ bool get isValid => _errors == null;
+}
- @override
- EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression node, ValidResult leftOperand) => this;
+/**
+ * Instances of the class `InternalResult` represent the result of attempting to evaluate a
+ * expression.
+ */
+class EvaluationResultImpl {
+ /**
+ * The errors encountered while trying to evaluate the compile time constant. These errors may or
+ * may not have prevented the expression from being a valid compile time constant.
+ */
+ List<AnalysisError> _errors;
- @override
- EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ /**
+ * The value of the expression, or null if the value couldn't be computed due to errors.
+ */
+ final DartObjectImpl value;
- @override
- EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ EvaluationResultImpl.con1(this.value) {
+ this._errors = new List<AnalysisError>(0);
+ }
- @override
- EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ EvaluationResultImpl.con2(this.value, List<AnalysisError> errors) {
+ this._errors = errors;
+ }
- @override
- EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) {
+ if (this.value != null) {
+ if (result.value == null) {
+ return false;
+ }
+ return value == result.value;
+ } else {
+ return false;
+ }
+ }
- @override
- EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ List<AnalysisError> get errors => _errors;
@override
- EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ String toString() {
+ if (value == null) {
+ return "error";
+ }
+ return value.toString();
+ }
+}
- @override
- EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+/**
+ * Instances of the class `FunctionState` represent the state of an object representing a
+ * function.
+ */
+class FunctionState extends InstanceState {
+ /**
+ * The element representing the function being modeled.
+ */
+ final ExecutableElement _element;
- @override
- EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ /**
+ * Initialize a newly created state to represent the given function.
+ *
+ * @param element the element representing the function being modeled
+ */
+ FunctionState(this._element);
@override
- EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ StringState convertToString() {
+ if (_element == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(_element.name);
+ }
@override
- EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ bool operator ==(Object object) => object is FunctionState && (_element == object._element);
@override
- EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ BoolState equalEqual(InstanceState rightOperand) {
+ if (_element == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is FunctionState) {
+ ExecutableElement rightElement = rightOperand._element;
+ if (rightElement == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(_element == rightElement);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
@override
- EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ String get typeName => "Function";
@override
- EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ int get hashCode => _element == null ? 0 : _element.hashCode;
@override
- EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ String toString() => _element == null ? "-unknown-" : _element.name;
+}
- @override
- EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+/**
+ * Instances of the class `GenericState` represent the state of an object representing a Dart
+ * object for which there is no more specific state.
+ */
+class GenericState extends InstanceState {
+ /**
+ * The values of the fields of this instance.
+ */
+ final HashMap<String, DartObjectImpl> _fieldMap;
- @override
- EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ /**
+ * Pseudo-field that we use to represent fields in the superclass.
+ */
+ static String SUPERCLASS_FIELD = "(super)";
- @override
- EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ /**
+ * A state that can be used to represent an object whose state is not known.
+ */
+ static GenericState UNKNOWN_VALUE = new GenericState(new HashMap<String, DartObjectImpl>());
- @override
- EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ /**
+ * Initialize a newly created state to represent a newly created object.
+ *
+ * @param fieldMap the values of the fields of this instance
+ */
+ GenericState(this._fieldMap);
@override
- EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
@override
- EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(this == rightOperand);
+ }
@override
- EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ bool operator ==(Object object) {
+ if (object is! GenericState) {
+ return false;
+ }
+ GenericState state = object as GenericState;
+ HashSet<String> otherFields = new HashSet<String>.from(state._fieldMap.keys.toSet());
+ for (String fieldName in _fieldMap.keys.toSet()) {
+ if (_fieldMap[fieldName] != state._fieldMap[fieldName]) {
+ return false;
+ }
+ otherFields.remove(fieldName);
+ }
+ for (String fieldName in otherFields) {
+ if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
+ return false;
+ }
+ }
+ return true;
+ }
@override
- EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ HashMap<String, DartObjectImpl> get fields => _fieldMap;
@override
- EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ String get typeName => "user defined type";
@override
- EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
+ int get hashCode {
+ int hashCode = 0;
+ for (DartObjectImpl value in _fieldMap.values) {
+ hashCode += value.hashCode;
+ }
+ return hashCode;
+ }
@override
- EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
+ bool get isUnknown => identical(this, UNKNOWN_VALUE);
}
-class ErrorResult_ErrorData {
- /**
- * The node against which the error should be reported.
- */
- final AstNode node;
-
+/**
+ * The class `InstanceState` defines the behavior of objects representing the state of a Dart
+ * object.
+ */
+abstract class InstanceState {
/**
- * The error code for the error to be generated.
+ * Return the result of invoking the '+' operator on this object with the given argument.
+ *
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the '+' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- final ErrorCode errorCode;
+ InstanceState add(InstanceState rightOperand) {
+ // TODO(brianwilkerson) Uncomment the code below when the new constant support can be added.
+ // if (this instanceof StringState || rightOperand instanceof StringState) {
+ // return concatenate(rightOperand);
+ // }
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
/**
- * Initialize a newly created data holder to represent the error with the given code reported
- * against the given node.
+ * Return the result of invoking the '&' operator on this object with the given argument.
*
- * @param node the node against which the error should be reported
- * @param errorCode the error code for the error to be generated
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the '&' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- ErrorResult_ErrorData(this.node, this.errorCode);
-}
+ IntState bitAnd(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
-/**
- * Instances of the class `EvaluationException` represent a run-time exception that would be
- * thrown during the evaluation of Dart code.
- */
-class EvaluationException extends JavaException {
/**
- * The error code associated with the exception.
+ * Return the result of invoking the '~' operator on this object.
+ *
+ * @return the result of invoking the '~' operator on this object
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- final ErrorCode errorCode;
+ IntState bitNot() {
+ assertIntOrNull(this);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
/**
- * Initialize a newly created exception to have the given error code.
+ * Return the result of invoking the '|' operator on this object with the given argument.
*
- * @param errorCode the error code associated with the exception
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the '|' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- EvaluationException(this.errorCode);
-}
+ IntState bitOr(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
-/**
- * Instances of the class `EvaluationResult` represent the result of attempting to evaluate an
- * expression.
- */
-class EvaluationResult {
/**
- * Return an evaluation result representing the result of evaluating an expression that is not a
- * compile-time constant because of the given errors.
+ * Return the result of invoking the '^' operator on this object with the given argument.
*
- * @param errors the errors that should be reported for the expression(s) that were evaluated
- * @return the result of evaluating an expression that is not a compile-time constant
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the '^' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- static EvaluationResult forErrors(List<AnalysisError> errors) => new EvaluationResult(null, errors);
+ IntState bitXor(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
/**
- * Return an evaluation result representing the result of evaluating an expression that is a
- * compile-time constant that evaluates to the given value.
+ * Return the result of invoking the ' ' operator on this object with the given argument.
*
- * @param value the value of the expression
- * @return the result of evaluating an expression that is a compile-time constant
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the ' ' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- static EvaluationResult forValue(DartObject value) => new EvaluationResult(value, null);
+ StringState concatenate(InstanceState rightOperand) {
+ assertString(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
/**
- * The value of the expression.
+ * Return the result of applying boolean conversion to this object.
+ *
+ * @param typeProvider the type provider used to find known types
+ * @return the result of applying boolean conversion to this object
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- final DartObject value;
+ BoolState convertToBool() => BoolState.FALSE_STATE;
/**
- * The errors that should be reported for the expression(s) that were evaluated.
+ * Return the result of converting this object to a String.
+ *
+ * @return the result of converting this object to a String
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- final List<AnalysisError> _errors;
+ StringState convertToString();
/**
- * Initialize a newly created result object with the given state. Clients should use one of the
- * factory methods: [forErrors] and [forValue].
+ * Return the result of invoking the '/' operator on this object with the given argument.
*
- * @param value the value of the expression
- * @param errors the errors that should be reported for the expression(s) that were evaluated
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the '/' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- EvaluationResult(this.value, this._errors);
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
/**
- * Return an array containing the errors that should be reported for the expression(s) that were
- * evaluated. If there are no such errors, the array will be empty. The array can be empty even if
- * the expression is not a valid compile time constant if the errors would have been reported by
- * other parts of the analysis engine.
+ * Return the result of invoking the '==' operator on this object with the given argument.
+ *
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the '==' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- List<AnalysisError> get errors => _errors == null ? AnalysisError.NO_ERRORS : _errors;
+ BoolState equalEqual(InstanceState rightOperand);
/**
- * Return `true` if the expression is a compile-time constant expression that would not
- * throw an exception when evaluated.
- *
- * @return `true` if the expression is a valid compile-time constant expression
+ * If this represents a generic dart object, return a map from its fieldnames to their values.
+ * Otherwise return null.
*/
- bool get isValid => _errors == null;
-}
-
-/**
- * Instances of the class `InternalResult` represent the result of attempting to evaluate a
- * expression.
- */
-abstract class EvaluationResultImpl {
- EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
+ HashMap<String, DartObjectImpl> get fields => null;
/**
- * Return the result of applying boolean conversion to this result.
+ * Return the name of the type of this value.
*
- * @param typeProvider the type provider used to access known types
- * @param node the node against which errors should be reported
- * @return the result of applying boolean conversion to the given value
+ * @return the name of the type of this value
*/
- EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode node);
-
- EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node);
-
- EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, EvaluationResultImpl rightOperand);
-
- bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result);
-
- EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node);
-
- EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl negated(TypeProvider typeProvider, Expression node);
-
- EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node);
-
- EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
-
- EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand);
-
- EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression node, ValidResult leftOperand);
-
- EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand);
-
- EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression node, ValidResult leftOperand);
-
- EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-
- EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand);
-
- EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
-}
+ String get typeName;
-/**
- * Instances of the class `FunctionState` represent the state of an object representing a
- * function.
- */
-class FunctionState extends InstanceState {
/**
- * The element representing the function being modeled.
+ * Return this object's value if it can be represented exactly, or `null` if either the
+ * value cannot be represented exactly or if the value is `null`. Clients should use
+ * [hasExactValue] to distinguish between these two cases.
+ *
+ * @return this object's value
*/
- final ExecutableElement _element;
+ Object get value => null;
/**
- * Initialize a newly created state to represent the given function.
+ * Return the result of invoking the '&gt;' operator on this object with the given argument.
*
- * @param element the element representing the function being modeled
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the '&gt;' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- FunctionState(this._element);
-
- @override
- StringState convertToString() {
- if (_element == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(_element.name);
- }
-
- @override
- bool operator ==(Object object) => object is FunctionState && (_element == object._element);
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- if (_element == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is FunctionState) {
- ExecutableElement rightElement = rightOperand._element;
- if (rightElement == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(_element == rightElement);
- } else if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
}
- @override
- String get typeName => "Function";
-
- @override
- int get hashCode => _element == null ? 0 : _element.hashCode;
-
- @override
- String toString() => _element == null ? "-unknown-" : _element.name;
-}
-
-/**
- * Instances of the class `GenericState` represent the state of an object representing a Dart
- * object for which there is no more specific state.
- */
-class GenericState extends InstanceState {
/**
- * The values of the fields of this instance.
+ * Return the result of invoking the '&gt;=' operator on this object with the given argument.
+ *
+ * @param rightOperand the right-hand operand of the operation
+ * @return the result of invoking the '&gt;=' operator on this object with the given argument
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
*/
- final HashMap<String, DartObjectImpl> _fieldMap;
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
/**
- * Pseudo-field that we use to represent fields in the superclass.
+ * Return `true` if this object's value can be represented exactly.
+ *
+ * @return `true` if this object's value can be represented exactly
*/
- static String SUPERCLASS_FIELD = "(super)";
-
- /**
- * A state that can be used to represent an object whose state is not known.
- */
- static GenericState UNKNOWN_VALUE = new GenericState(new HashMap<String, DartObjectImpl>());
-
- /**
- * Initialize a newly created state to represent a newly created object.
- *
- * @param fieldMap the values of the fields of this instance
- */
- GenericState(this._fieldMap);
-
- @override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(this == rightOperand);
- }
-
- @override
- bool operator ==(Object object) {
- if (object is! GenericState) {
- return false;
- }
- GenericState state = object as GenericState;
- HashSet<String> otherFields = new HashSet<String>.from(state._fieldMap.keys.toSet());
- for (String fieldName in _fieldMap.keys.toSet()) {
- if (_fieldMap[fieldName] != state._fieldMap[fieldName]) {
- return false;
- }
- otherFields.remove(fieldName);
- }
- for (String fieldName in otherFields) {
- if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
- return false;
- }
- }
- return true;
- }
-
- @override
- HashMap<String, DartObjectImpl> get fields => _fieldMap;
-
- @override
- String get typeName => "user defined type";
-
- @override
- int get hashCode {
- int hashCode = 0;
- for (DartObjectImpl value in _fieldMap.values) {
- hashCode += value.hashCode;
- }
- return hashCode;
- }
-
- @override
- bool get isUnknown => identical(this, UNKNOWN_VALUE);
-}
-
-/**
- * The class `InstanceState` defines the behavior of objects representing the state of a Dart
- * object.
- */
-abstract class InstanceState {
- /**
- * Return the result of invoking the '+' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the '+' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- NumState add(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '&' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the '&' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- IntState bitAnd(InstanceState rightOperand) {
- assertIntOrNull(this);
- assertIntOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '~' operator on this object.
- *
- * @return the result of invoking the '~' operator on this object
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- IntState bitNot() {
- assertIntOrNull(this);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '|' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the '|' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- IntState bitOr(InstanceState rightOperand) {
- assertIntOrNull(this);
- assertIntOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '^' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the '^' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- IntState bitXor(InstanceState rightOperand) {
- assertIntOrNull(this);
- assertIntOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the ' ' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the ' ' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- StringState concatenate(InstanceState rightOperand) {
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of applying boolean conversion to this object.
- *
- * @param typeProvider the type provider used to find known types
- * @return the result of applying boolean conversion to this object
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- BoolState convertToBool() => BoolState.FALSE_STATE;
-
- /**
- * Return the result of converting this object to a String.
- *
- * @return the result of converting this object to a String
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- StringState convertToString();
-
- /**
- * Return the result of invoking the '/' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the '/' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- NumState divide(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '==' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the '==' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- BoolState equalEqual(InstanceState rightOperand);
-
- /**
- * If this represents a generic dart object, return a map from its fieldnames to their values.
- * Otherwise return null.
- */
- HashMap<String, DartObjectImpl> get fields => null;
-
- /**
- * Return the name of the type of this value.
- *
- * @return the name of the type of this value
- */
- String get typeName;
-
- /**
- * Return this object's value if it can be represented exactly, or `null` if either the
- * value cannot be represented exactly or if the value is `null`. Clients should use
- * [hasExactValue] to distinguish between these two cases.
- *
- * @return this object's value
- */
- Object get value => null;
-
- /**
- * Return the result of invoking the '&gt;' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the '&gt;' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- BoolState greaterThan(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '&gt;=' operator on this object with the given argument.
- *
- * @param rightOperand the right-hand operand of the operation
- * @return the result of invoking the '&gt;=' operator on this object with the given argument
- * @throws EvaluationException if the operator is not appropriate for an object of this kind
- */
- BoolState greaterThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return `true` if this object's value can be represented exactly.
- *
- * @return `true` if this object's value can be represented exactly
- */
- bool get hasExactValue => false;
+ bool get hasExactValue => false;
/**
* Return the result of invoking the '~/' operator on this object with the given argument.
@@ -3381,6 +3406,17 @@ abstract class InstanceState {
}
/**
+ * Return the result of invoking the 'length' getter on this object.
+ *
+ * @return the result of invoking the 'length' getter on this object
+ * @throws EvaluationException if the operator is not appropriate for an object of this kind
+ */
+ IntState stringLength() {
+ assertString(this);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
* Return the result of invoking the '*' operator on this object with the given argument.
*
* @param rightOperand the right-hand operand of the operation
@@ -3564,1410 +3600,973 @@ class IntState extends NumState {
return new IntState(value ^ rightValue);
} else if (rightOperand is DynamicState || rightOperand is NumState) {
return UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- StringState convertToString() {
- if (value == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(value.toString());
- }
-
- @override
- NumState divide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue == 0) {
- return new DoubleState(value.toDouble() / rightValue.toDouble());
- }
- return new IntState(value ~/ rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() / rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value == rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(rightValue == value.toDouble());
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
- }
-
- @override
- bool operator ==(Object object) => object is IntState && (value == object.value);
-
- @override
- String get typeName => "int";
-
- @override
- BoolState greaterThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.compareTo(rightValue) > 0);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.toDouble() > rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState greaterThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.compareTo(rightValue) >= 0);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.toDouble() >= rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- bool get hasExactValue => true;
-
- @override
- int get hashCode => value == null ? 0 : value.hashCode;
-
- @override
- IntState integerDivide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue == 0) {
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
- }
- return new IntState(value ~/ rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- double result = value.toDouble() / rightValue;
- return new IntState(result.toInt());
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- bool get isUnknown => value == null;
-
- @override
- BoolState lessThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.compareTo(rightValue) < 0);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.toDouble() < rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState lessThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.compareTo(rightValue) <= 0);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.toDouble() <= rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState minus(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value - rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() - rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState negated() {
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(-value);
- }
-
- @override
- NumState remainder(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue == 0) {
- return new DoubleState(value.toDouble() % rightValue.toDouble());
- }
- return new IntState(value.remainder(rightValue));
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() % rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState shiftLeft(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue.bitLength > 31) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value << rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState shiftRight(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue.bitLength > 31) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value >> rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState times(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value * rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() * rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- String toString() => value == null ? "-unknown-" : value.toString();
-}
-
-/**
- * The unique instance of the class `ListState` represents the state of an object representing
- * a list.
- */
-class ListState extends InstanceState {
- /**
- * The elements of the list.
- */
- final List<DartObjectImpl> _elements;
-
- /**
- * Initialize a newly created state to represent a list with the given elements.
- *
- * @param elements the elements of the list
- */
- ListState(this._elements);
-
- @override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(this == rightOperand);
- }
-
- @override
- bool operator ==(Object object) {
- if (object is! ListState) {
- return false;
- }
- List<DartObjectImpl> otherElements = (object as ListState)._elements;
- int count = _elements.length;
- if (otherElements.length != count) {
- return false;
- } else if (count == 0) {
- return true;
- }
- for (int i = 0; i < count; i++) {
- if (_elements[i] != otherElements[i]) {
- return false;
- }
- }
- return true;
- }
-
- @override
- String get typeName => "List";
-
- @override
- List<Object> get value {
- int count = _elements.length;
- List<Object> result = new List<Object>(count);
- for (int i = 0; i < count; i++) {
- DartObjectImpl element = _elements[i];
- if (!element.hasExactValue) {
- return null;
- }
- result[i] = element.value;
- }
- return result;
- }
-
- @override
- bool get hasExactValue {
- int count = _elements.length;
- for (int i = 0; i < count; i++) {
- if (!_elements[i].hasExactValue) {
- return false;
- }
- }
- return true;
- }
-
- @override
- int get hashCode {
- int value = 0;
- int count = _elements.length;
- for (int i = 0; i < count; i++) {
- value = (value << 3) ^ _elements[i].hashCode;
- }
- return value;
- }
-}
-
-/**
- * The unique instance of the class `ListState` represents the state of an object representing
- * a map.
- */
-class MapState extends InstanceState {
- /**
- * The entries in the map.
- */
- final HashMap<DartObjectImpl, DartObjectImpl> _entries;
-
- /**
- * Initialize a newly created state to represent a map with the given entries.
- *
- * @param entries the entries in the map
- */
- MapState(this._entries);
-
- @override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(this == rightOperand);
- }
-
- @override
- bool operator ==(Object object) {
- if (object is! MapState) {
- return false;
- }
- HashMap<DartObjectImpl, DartObjectImpl> otherElements = (object as MapState)._entries;
- int count = _entries.length;
- if (otherElements.length != count) {
- return false;
- } else if (count == 0) {
- return true;
- }
- for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entries)) {
- DartObjectImpl key = entry.getKey();
- DartObjectImpl value = entry.getValue();
- DartObjectImpl otherValue = otherElements[key];
- if (value != otherValue) {
- return false;
- }
- }
- return true;
- }
-
- @override
- String get typeName => "Map";
-
- @override
- Map<Object, Object> get value {
- HashMap<Object, Object> result = new HashMap<Object, Object>();
- for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entries)) {
- DartObjectImpl key = entry.getKey();
- DartObjectImpl value = entry.getValue();
- if (!key.hasExactValue || !value.hasExactValue) {
- return null;
- }
- result[key.value] = value.value;
- }
- return result;
- }
-
- @override
- bool get hasExactValue {
- for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entries)) {
- if (!entry.getKey().hasExactValue || !entry.getValue().hasExactValue) {
- return false;
- }
- }
- return true;
- }
-
- @override
- int get hashCode {
- int value = 0;
- for (DartObjectImpl key in _entries.keys.toSet()) {
- value = (value << 3) ^ key.hashCode;
- }
- return value;
- }
-}
-
-/**
- * The unique instance of the class `NullState` represents the state of the value 'null'.
- */
-class NullState extends InstanceState {
- /**
- * An instance representing the boolean value 'true'.
- */
- static NullState NULL_STATE = new NullState();
-
- @override
- BoolState convertToBool() {
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- StringState convertToString() => new StringState("null");
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(rightOperand is NullState);
- }
-
- @override
- bool operator ==(Object object) => object is NullState;
-
- @override
- String get typeName => "Null";
-
- @override
- bool get hasExactValue => true;
-
- @override
- int get hashCode => 0;
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- BoolState logicalNot() {
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- String toString() => "null";
-}
-
-/**
- * Instances of the class `NumState` represent the state of an object representing a number of
- * an unknown type (a 'num').
- */
-class NumState extends InstanceState {
- /**
- * A state that can be used to represent a number whose value is not known.
- */
- static NumState UNKNOWN_VALUE = new NumState();
-
- @override
- NumState add(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value.toString());
+ }
@override
NumState divide(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ return new DoubleState(value.toDouble() / rightValue.toDouble());
+ }
+ return new IntState(value ~/ rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() / rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
BoolState equalEqual(InstanceState rightOperand) {
assertBoolNumStringOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(rightValue == value.toDouble());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
}
@override
- bool operator ==(Object object) => object is NumState;
+ bool operator ==(Object object) => object is IntState && (value == object.value);
@override
- String get typeName => "num";
+ String get typeName => "int";
@override
BoolState greaterThan(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) > 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() > rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
BoolState greaterThanOrEqual(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) >= 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() >= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
- int get hashCode => 7;
+ bool get hasExactValue => true;
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
@override
IntState integerDivide(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
if (rightOperand is IntState) {
int rightValue = rightOperand.value;
if (rightValue == null) {
- return IntState.UNKNOWN_VALUE;
+ return UNKNOWN_VALUE;
} else if (rightValue == 0) {
throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
}
- } else if (rightOperand is DynamicState) {
- return IntState.UNKNOWN_VALUE;
+ return new IntState(value ~/ rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ double result = value.toDouble() / rightValue;
+ return new IntState(result.toInt());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
}
- return IntState.UNKNOWN_VALUE;
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
bool get isBoolNumStringOrNull => true;
@override
- bool get isUnknown => identical(this, UNKNOWN_VALUE);
+ bool get isUnknown => value == null;
@override
BoolState lessThan(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) < 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() < rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
BoolState lessThanOrEqual(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) <= 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() <= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
NumState minus(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value - rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() - rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
- NumState negated() => UNKNOWN_VALUE;
+ NumState negated() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(-value);
+ }
@override
NumState remainder(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ return new DoubleState(value.toDouble() % rightValue.toDouble());
+ }
+ return new IntState(value.remainder(rightValue));
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() % rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState shiftLeft(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue.bitLength > 31) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value << rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState shiftRight(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue.bitLength > 31) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value >> rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
NumState times(InstanceState rightOperand) {
assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value * rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() * rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
- String toString() => "-unknown-";
+ String toString() => value == null ? "-unknown-" : value.toString();
}
/**
- * Instances of the class `ReferenceFinder` add reference information for a given variable to
- * the bi-directional mapping used to order the evaluation of constants.
+ * The unique instance of the class `ListState` represents the state of an object representing
+ * a list.
*/
-class ReferenceFinder extends RecursiveAstVisitor<Object> {
- /**
- * The element representing the construct that will be visited.
- */
- final AstNode _source;
-
- /**
- * A graph in which the nodes are the constant variables and the edges are from each variable to
- * the other constant variables that are referenced in the head's initializer.
- */
- final DirectedGraph<AstNode> _referenceGraph;
-
- /**
- * A table mapping constant variables to the declarations of those variables.
- */
- final HashMap<VariableElement, VariableDeclaration> _variableDeclarationMap;
-
+class ListState extends InstanceState {
/**
- * A table mapping constant constructors to the declarations of those constructors.
+ * The elements of the list.
*/
- final HashMap<ConstructorElement, ConstructorDeclaration> _constructorDeclarationMap;
+ final List<DartObjectImpl> _elements;
/**
- * Initialize a newly created reference finder to find references from the given variable to other
- * variables and to add those references to the given graph.
+ * Initialize a newly created state to represent a list with the given elements.
*
- * @param source the element representing the variable whose initializer will be visited
- * @param referenceGraph a graph recording which variables (heads) reference which other variables
- * (tails) in their initializers
- * @param variableDeclarationMap A table mapping constant variables to the declarations of those
- * variables.
- * @param constructorDeclarationMap A table mapping constant constructors to the declarations of
- * those constructors.
+ * @param elements the elements of the list
*/
- ReferenceFinder(this._source, this._referenceGraph, this._variableDeclarationMap, this._constructorDeclarationMap);
+ ListState(this._elements);
@override
- Object visitInstanceCreationExpression(InstanceCreationExpression node) {
- if (node.isConst) {
- _referenceGraph.addEdge(_source, node);
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
}
- return null;
+ return BoolState.from(this == rightOperand);
}
@override
- Object visitSimpleIdentifier(SimpleIdentifier node) {
- Element element = node.staticElement;
- if (element is PropertyAccessorElement) {
- element = (element as PropertyAccessorElement).variable;
+ bool operator ==(Object object) {
+ if (object is! ListState) {
+ return false;
}
- if (element is VariableElement) {
- VariableElement variable = element as VariableElement;
- if (variable.isConst) {
- VariableDeclaration variableDeclaration = _variableDeclarationMap[variable];
- // The declaration will be null when the variable is not defined in the compilation units
- // that were used to produce the variableDeclarationMap. In such cases, the variable should
- // already have a value associated with it, but we don't bother to check because there's
- // nothing we can do about it at this point.
- if (variableDeclaration != null) {
- _referenceGraph.addEdge(_source, variableDeclaration);
- }
+ List<DartObjectImpl> otherElements = (object as ListState)._elements;
+ int count = _elements.length;
+ if (otherElements.length != count) {
+ return false;
+ } else if (count == 0) {
+ return true;
+ }
+ for (int i = 0; i < count; i++) {
+ if (_elements[i] != otherElements[i]) {
+ return false;
}
}
- return null;
+ return true;
}
@override
- Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- super.visitSuperConstructorInvocation(node);
- ConstructorElement constructor = node.staticElement;
- if (constructor != null && constructor.isConst) {
- ConstructorDeclaration constructorDeclaration = _constructorDeclarationMap[constructor];
- // The declaration will be null when the constructor is not defined in the compilation
- // units that were used to produce the constructorDeclarationMap. In such cases, the
- // constructor should already have its initializer AST's stored in it, but we don't bother
- // to check because there's nothing we can do about it at this point.
- if (constructorDeclaration != null) {
- _referenceGraph.addEdge(_source, constructorDeclaration);
+ String get typeName => "List";
+
+ @override
+ List<Object> get value {
+ int count = _elements.length;
+ List<Object> result = new List<Object>(count);
+ for (int i = 0; i < count; i++) {
+ DartObjectImpl element = _elements[i];
+ if (!element.hasExactValue) {
+ return null;
}
+ result[i] = element.value;
}
- return null;
+ return result;
+ }
+
+ @override
+ bool get hasExactValue {
+ int count = _elements.length;
+ for (int i = 0; i < count; i++) {
+ if (!_elements[i].hasExactValue) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @override
+ int get hashCode {
+ int value = 0;
+ int count = _elements.length;
+ for (int i = 0; i < count; i++) {
+ value = (value << 3) ^ _elements[i].hashCode;
+ }
+ return value;
}
}
/**
- * Instances of the class `StringState` represent the state of an object representing a
- * string.
+ * The unique instance of the class `ListState` represents the state of an object representing
+ * a map.
*/
-class StringState extends InstanceState {
- /**
- * The value of this instance.
- */
- final String value;
-
+class MapState extends InstanceState {
/**
- * A state that can be used to represent a double whose value is not known.
+ * The entries in the map.
*/
- static StringState UNKNOWN_VALUE = new StringState(null);
+ final HashMap<DartObjectImpl, DartObjectImpl> _entries;
/**
- * Initialize a newly created state to represent the given value.
+ * Initialize a newly created state to represent a map with the given entries.
*
- * @param value the value of this instance
+ * @param entries the entries in the map
*/
- StringState(this.value);
-
- @override
- StringState concatenate(InstanceState rightOperand) {
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is StringState) {
- String rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new StringState("${value}${rightValue}");
- } else if (rightOperand is DynamicState) {
- return UNKNOWN_VALUE;
- }
- return super.concatenate(rightOperand);
- }
+ MapState(this._entries);
@override
- StringState convertToString() => this;
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
@override
BoolState equalEqual(InstanceState rightOperand) {
assertBoolNumStringOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is StringState) {
- String rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value == rightValue);
- } else if (rightOperand is DynamicState) {
+ if (rightOperand is DynamicState) {
return BoolState.UNKNOWN_VALUE;
}
- return BoolState.FALSE_STATE;
+ return BoolState.from(this == rightOperand);
}
@override
- bool operator ==(Object object) => object is StringState && (value == object.value);
-
- @override
- String get typeName => "String";
-
- @override
- bool get hasExactValue => true;
+ bool operator ==(Object object) {
+ if (object is! MapState) {
+ return false;
+ }
+ HashMap<DartObjectImpl, DartObjectImpl> otherElements = (object as MapState)._entries;
+ int count = _entries.length;
+ if (otherElements.length != count) {
+ return false;
+ } else if (count == 0) {
+ return true;
+ }
+ for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entries)) {
+ DartObjectImpl key = entry.getKey();
+ DartObjectImpl value = entry.getValue();
+ DartObjectImpl otherValue = otherElements[key];
+ if (value != otherValue) {
+ return false;
+ }
+ }
+ return true;
+ }
@override
- int get hashCode => value == null ? 0 : value.hashCode;
+ String get typeName => "Map";
@override
- bool get isBoolNumStringOrNull => true;
+ Map<Object, Object> get value {
+ HashMap<Object, Object> result = new HashMap<Object, Object>();
+ for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entries)) {
+ DartObjectImpl key = entry.getKey();
+ DartObjectImpl value = entry.getValue();
+ if (!key.hasExactValue || !value.hasExactValue) {
+ return null;
+ }
+ result[key.value] = value.value;
+ }
+ return result;
+ }
@override
- bool get isUnknown => value == null;
+ bool get hasExactValue {
+ for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entries)) {
+ if (!entry.getKey().hasExactValue || !entry.getValue().hasExactValue) {
+ return false;
+ }
+ }
+ return true;
+ }
@override
- String toString() => value == null ? "-unknown-" : "'${value}'";
+ int get hashCode {
+ int value = 0;
+ for (DartObjectImpl key in _entries.keys.toSet()) {
+ value = (value << 3) ^ key.hashCode;
+ }
+ return value;
+ }
}
/**
- * Instances of the class `StringState` represent the state of an object representing a
- * symbol.
+ * The unique instance of the class `NullState` represents the state of the value 'null'.
*/
-class SymbolState extends InstanceState {
- /**
- * The value of this instance.
- */
- final String value;
-
+class NullState extends InstanceState {
/**
- * Initialize a newly created state to represent the given value.
- *
- * @param value the value of this instance
+ * An instance representing the boolean value 'true'.
*/
- SymbolState(this.value);
+ static NullState NULL_STATE = new NullState();
@override
- StringState convertToString() {
- if (value == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(value);
+ BoolState convertToBool() {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
@override
+ StringState convertToString() => new StringState("null");
+
+ @override
BoolState equalEqual(InstanceState rightOperand) {
assertBoolNumStringOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is SymbolState) {
- String rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value == rightValue);
- } else if (rightOperand is DynamicState) {
+ if (rightOperand is DynamicState) {
return BoolState.UNKNOWN_VALUE;
}
- return BoolState.FALSE_STATE;
+ return BoolState.from(rightOperand is NullState);
}
@override
- bool operator ==(Object object) => object is SymbolState && (value == object.value);
+ bool operator ==(Object object) => object is NullState;
@override
- String get typeName => "Symbol";
+ String get typeName => "Null";
@override
bool get hasExactValue => true;
@override
- int get hashCode => value == null ? 0 : value.hashCode;
+ int get hashCode => 0;
@override
- String toString() => value == null ? "-unknown-" : "#${value}";
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ BoolState logicalNot() {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ String toString() => "null";
}
/**
- * Instances of the class `TypeState` represent the state of an object representing a type.
+ * Instances of the class `NumState` represent the state of an object representing a number of
+ * an unknown type (a 'num').
*/
-class TypeState extends InstanceState {
- /**
- * The element representing the type being modeled.
- */
- final Element _element;
-
+class NumState extends InstanceState {
/**
- * Initialize a newly created state to represent the given value.
- *
- * @param element the element representing the type being modeled
+ * A state that can be used to represent a number whose value is not known.
*/
- TypeState(this._element);
+ static NumState UNKNOWN_VALUE = new NumState();
@override
- StringState convertToString() {
- if (_element == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(_element.name);
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
}
@override
- bool operator ==(Object object) => object is TypeState && (_element == object._element);
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
@override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- if (_element == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is TypeState) {
- Element rightElement = rightOperand._element;
- if (rightElement == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(_element == rightElement);
- } else if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
}
@override
- String get typeName => "Type";
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
@override
- int get hashCode => _element == null ? 0 : _element.hashCode;
+ bool operator ==(Object object) => object is NumState;
@override
- String toString() => _element == null ? "-unknown-" : _element.name;
-}
-
-/**
- * Instances of the class `ValidResult` represent the result of attempting to evaluate a valid
- * compile time constant expression.
- */
-class ValidResult extends EvaluationResultImpl {
- /**
- * The value of the expression.
- */
- final DartObjectImpl value;
-
- /**
- * Initialize a newly created result to represent the given value.
- *
- * @param value the value of the expression
- */
- ValidResult(this.value);
+ String get typeName => "num";
@override
- EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.addToValid(typeProvider, node, this);
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
- /**
- * Return the result of applying boolean conversion to this result.
- *
- * @param node the node against which errors should be reported
- * @return the result of applying boolean conversion to the given value
- */
@override
- EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode node) {
- try {
- return _valueOf(value.convertToBool(typeProvider));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
}
@override
- EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitAndValid(typeProvider, node, this);
+ int get hashCode => 7;
@override
- EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node) {
- try {
- return _valueOf(value.bitNot(typeProvider));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return IntState.UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
+ }
+ } else if (rightOperand is DynamicState) {
+ return IntState.UNKNOWN_VALUE;
}
+ return IntState.UNKNOWN_VALUE;
}
@override
- EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitOrValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitXorValid(typeProvider, node, this);
+ bool get isBoolNumStringOrNull => true;
@override
- EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, EvaluationResultImpl rightOperand) => rightOperand.concatenateValid(typeProvider, node, this);
+ bool get isUnknown => identical(this, UNKNOWN_VALUE);
@override
- EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.divideValid(typeProvider, node, this);
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
@override
- EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, EvaluationResultImpl rightOperand) => rightOperand.equalEqualValid(typeProvider, node, this);
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
@override
- bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) {
- if (result is! ValidResult) {
- return false;
- }
- return value == (result as ValidResult).value;
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
}
@override
- EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanValid(typeProvider, node, this);
+ NumState negated() => UNKNOWN_VALUE;
@override
- EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanOrEqualValid(typeProvider, node, this);
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
@override
- EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.integerDivideValid(typeProvider, node, this);
-
- /**
- * Return `true` if this object represents an object whose type is 'bool'.
- *
- * @return `true` if this object represents a boolean value
- */
- bool get isBool => value.isBool;
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
- /**
- * Return `true` if this object represents an object whose type is either 'bool', 'num',
- * 'String', or 'Null'.
- *
- * @return `true` if this object represents either a boolean, numeric, string or null value
- */
- bool get isBoolNumStringOrNull => value.isBoolNumStringOrNull;
+ @override
+ String toString() => "-unknown-";
+}
+/**
+ * Instances of the class `ReferenceFinder` add reference information for a given variable to
+ * the bi-directional mapping used to order the evaluation of constants.
+ */
+class ReferenceFinder extends RecursiveAstVisitor<Object> {
/**
- * Return `true` if this result represents the value 'false'.
- *
- * @return `true` if this result represents the value 'false'
+ * The element representing the construct that will be visited.
*/
- bool get isFalse => value.isFalse;
+ final AstNode _source;
/**
- * Return `true` if this result represents the value 'null'.
- *
- * @return `true` if this result represents the value 'null'
+ * A graph in which the nodes are the constant variables and the edges are from each variable to
+ * the other constant variables that are referenced in the head's initializer.
*/
- bool get isNull => value.isNull;
+ final DirectedGraph<AstNode> _referenceGraph;
/**
- * Return `true` if this result represents the value 'true'.
- *
- * @return `true` if this result represents the value 'true'
+ * A table mapping constant variables to the declarations of those variables.
*/
- bool get isTrue => value.isTrue;
+ final HashMap<VariableElement, VariableDeclaration> _variableDeclarationMap;
/**
- * Return `true` if this object represents an instance of a user-defined class.
- *
- * @return `true` if this object represents an instance of a user-defined class
+ * A table mapping constant constructors to the declarations of those constructors.
*/
- bool get isUserDefinedObject => value.isUserDefinedObject;
-
- @override
- EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.lessThanValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.lessThanOrEqualValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.logicalAndValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node) {
- try {
- return _valueOf(value.logicalNot(typeProvider));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
-
- @override
- EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.logicalOrValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.minusValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl negated(TypeProvider typeProvider, Expression node) {
- try {
- return _valueOf(value.negated(typeProvider));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
-
- @override
- EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.notEqualValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node) {
- try {
- return _valueOf(value.performToString(typeProvider));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
-
- @override
- EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.remainderValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.shiftLeftValid(typeProvider, node, this);
-
- @override
- EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.shiftRightValid(typeProvider, node, this);
+ final HashMap<ConstructorElement, ConstructorDeclaration> _constructorDeclarationMap;
- @override
- EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.timesValid(typeProvider, node, this);
+ /**
+ * Initialize a newly created reference finder to find references from the given variable to other
+ * variables and to add those references to the given graph.
+ *
+ * @param source the element representing the variable whose initializer will be visited
+ * @param referenceGraph a graph recording which variables (heads) reference which other variables
+ * (tails) in their initializers
+ * @param variableDeclarationMap A table mapping constant variables to the declarations of those
+ * variables.
+ * @param constructorDeclarationMap A table mapping constant constructors to the declarations of
+ * those constructors.
+ */
+ ReferenceFinder(this._source, this._referenceGraph, this._variableDeclarationMap, this._constructorDeclarationMap);
@override
- String toString() {
- if (value == null) {
- return "null";
+ Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (node.isConst) {
+ _referenceGraph.addEdge(_source, node);
}
- return value.toString();
+ return null;
}
@override
- EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-
- @override
- EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.add(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ Object visitSimpleIdentifier(SimpleIdentifier node) {
+ Element element = node.staticElement;
+ if (element is PropertyAccessorElement) {
+ element = (element as PropertyAccessorElement).variable;
}
- }
-
- @override
- EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-
- @override
- EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.bitAnd(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ if (element is VariableElement) {
+ VariableElement variable = element as VariableElement;
+ if (variable.isConst) {
+ VariableDeclaration variableDeclaration = _variableDeclarationMap[variable];
+ // The declaration will be null when the variable is not defined in the compilation units
+ // that were used to produce the variableDeclarationMap. In such cases, the variable should
+ // already have a value associated with it, but we don't bother to check because there's
+ // nothing we can do about it at this point.
+ if (variableDeclaration != null) {
+ _referenceGraph.addEdge(_source, variableDeclaration);
+ }
+ }
}
+ return null;
}
@override
- EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-
- @override
- EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.bitOr(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ super.visitSuperConstructorInvocation(node);
+ ConstructorElement constructor = node.staticElement;
+ if (constructor != null && constructor.isConst) {
+ ConstructorDeclaration constructorDeclaration = _constructorDeclarationMap[constructor];
+ // The declaration will be null when the constructor is not defined in the compilation
+ // units that were used to produce the constructorDeclarationMap. In such cases, the
+ // constructor should already have its initializer AST's stored in it, but we don't bother
+ // to check because there's nothing we can do about it at this point.
+ if (constructorDeclaration != null) {
+ _referenceGraph.addEdge(_source, constructorDeclaration);
+ }
}
+ return null;
}
+}
- @override
- EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+/**
+ * Instances of the class `StringState` represent the state of an object representing a
+ * string.
+ */
+class StringState extends InstanceState {
+ /**
+ * The value of this instance.
+ */
+ final String value;
- @override
- EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.bitXor(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
+ /**
+ * A state that can be used to represent a double whose value is not known.
+ */
+ static StringState UNKNOWN_VALUE = new StringState(null);
- @override
- EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand) => leftOperand;
+ /**
+ * Initialize a newly created state to represent the given value.
+ *
+ * @param value the value of this instance
+ */
+ StringState(this.value);
@override
- EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.concatenate(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ StringState concatenate(InstanceState rightOperand) {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is StringState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new StringState("${value}${rightValue}");
+ } else if (rightOperand is DynamicState) {
+ return UNKNOWN_VALUE;
}
+ return super.concatenate(rightOperand);
}
@override
- EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ StringState convertToString() => this;
@override
- EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.divide(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is StringState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
}
+ return BoolState.FALSE_STATE;
}
@override
- EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand) => leftOperand;
-
- @override
- EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.equalEqual(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
+ bool operator ==(Object object) => object is StringState && (value == object.value);
@override
- EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ String get typeName => "String";
@override
- EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ bool get hasExactValue => true;
@override
- EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.greaterThanOrEqual(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
+ int get hashCode => value == null ? 0 : value.hashCode;
@override
- EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.greaterThan(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
+ bool get isBoolNumStringOrNull => true;
@override
- EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ bool get isUnknown => value == null;
@override
- EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.integerDivide(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ IntState stringLength() {
+ if (value == null) {
+ return IntState.UNKNOWN_VALUE;
}
+ return new IntState(value.length);
}
@override
- EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ String toString() => value == null ? "-unknown-" : "'${value}'";
+}
- @override
- EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+/**
+ * Instances of the class `StringState` represent the state of an object representing a
+ * symbol.
+ */
+class SymbolState extends InstanceState {
+ /**
+ * The value of this instance.
+ */
+ final String value;
- @override
- EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.lessThanOrEqual(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
+ /**
+ * Initialize a newly created state to represent the given value.
+ *
+ * @param value the value of this instance
+ */
+ SymbolState(this.value);
@override
- EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.lessThan(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
}
+ return new StringState(value);
}
@override
- EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-
- @override
- EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.logicalAnd(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
}
- }
-
- @override
- EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
-
- @override
- EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.logicalOr(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ if (rightOperand is SymbolState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
}
+ return BoolState.FALSE_STATE;
}
@override
- EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ bool operator ==(Object object) => object is SymbolState && (value == object.value);
@override
- EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.minus(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
+ String get typeName => "Symbol";
@override
- EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ bool get hasExactValue => true;
@override
- EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.notEqual(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
+ int get hashCode => value == null ? 0 : value.hashCode;
@override
- EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ String toString() => value == null ? "-unknown-" : "#${value}";
+}
- @override
- EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.remainder(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
+/**
+ * Instances of the class `TypeState` represent the state of an object representing a type.
+ */
+class TypeState extends InstanceState {
+ /**
+ * The element representing the type being modeled.
+ */
+ final Element _element;
- @override
- EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ /**
+ * Initialize a newly created state to represent the given value.
+ *
+ * @param element the element representing the type being modeled
+ */
+ TypeState(this._element);
@override
- EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.shiftLeft(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ StringState convertToString() {
+ if (_element == null) {
+ return StringState.UNKNOWN_VALUE;
}
+ return new StringState(_element.name);
}
@override
- EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ bool operator ==(Object object) => object is TypeState && (_element == object._element);
@override
- EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.shiftRight(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ if (_element == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is TypeState) {
+ Element rightElement = rightOperand._element;
+ if (rightElement == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(_element == rightElement);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
}
+ return BoolState.FALSE_STATE;
}
@override
- EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
+ String get typeName => "Type";
@override
- EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
- try {
- return _valueOf(leftOperand.value.times(typeProvider, value));
- } on EvaluationException catch (exception) {
- return _error(node, exception.errorCode);
- }
- }
-
- /**
- * Return a result object representing an error associated with the given node.
- *
- * @param node the AST node associated with the error
- * @param code the error code indicating the nature of the error
- * @return a result object representing an error associated with the given node
- */
- ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node, code);
+ int get hashCode => _element == null ? 0 : _element.hashCode;
- /**
- * Return a result object representing the given value.
- *
- * @param value the value to be represented as a result object
- * @return a result object representing the given value
- */
- ValidResult _valueOf(DartObjectImpl value) => new ValidResult(value);
+ @override
+ String toString() => _element == null ? "-unknown-" : _element.name;
}

Powered by Google App Engine
This is Rietveld 408576698