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

Side by Side Diff: observatory_pub_packages/analyzer/src/generated/constant.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information.
7
8 library engine.constant;
9
10 import 'dart:collection';
11 import 'java_core.dart';
12 import 'java_engine.dart' show ObjectUtilities;
13 import 'source.dart' show Source;
14 import 'error.dart' show AnalysisError, ErrorCode, CompileTimeErrorCode;
15 import 'scanner.dart' show Token, TokenType;
16 import 'ast.dart';
17 import 'element.dart';
18 import 'resolver.dart' show TypeProvider;
19 import 'engine.dart' show AnalysisEngine;
20 import 'utilities_dart.dart' show ParameterKind;
21 import 'utilities_collection.dart';
22
23 /**
24 * Instances of the class `BoolState` represent the state of an object represent ing a boolean
25 * value.
26 */
27 class BoolState extends InstanceState {
28 /**
29 * The value of this instance.
30 */
31 final bool value;
32
33 /**
34 * An instance representing the boolean value 'false'.
35 */
36 static BoolState FALSE_STATE = new BoolState(false);
37
38 /**
39 * An instance representing the boolean value 'true'.
40 */
41 static BoolState TRUE_STATE = new BoolState(true);
42
43 /**
44 * A state that can be used to represent a boolean whose value is not known.
45 */
46 static BoolState UNKNOWN_VALUE = new BoolState(null);
47
48 /**
49 * Return the boolean state representing the given boolean value.
50 *
51 * @param value the value to be represented
52 * @return the boolean state representing the given boolean value
53 */
54 static BoolState from(bool value) => value ? BoolState.TRUE_STATE : BoolState. FALSE_STATE;
55
56 /**
57 * Initialize a newly created state to represent the given value.
58 *
59 * @param value the value of this instance
60 */
61 BoolState(this.value);
62
63 @override
64 BoolState convertToBool() => this;
65
66 @override
67 StringState convertToString() {
68 if (value == null) {
69 return StringState.UNKNOWN_VALUE;
70 }
71 return new StringState(value ? "true" : "false");
72 }
73
74 @override
75 BoolState equalEqual(InstanceState rightOperand) {
76 assertBoolNumStringOrNull(rightOperand);
77 if (value == null) {
78 return UNKNOWN_VALUE;
79 }
80 if (rightOperand is BoolState) {
81 bool rightValue = rightOperand.value;
82 if (rightValue == null) {
83 return UNKNOWN_VALUE;
84 }
85 return BoolState.from(identical(value, rightValue));
86 } else if (rightOperand is DynamicState) {
87 return UNKNOWN_VALUE;
88 }
89 return FALSE_STATE;
90 }
91
92 @override
93 bool operator ==(Object object) => object is BoolState && identical(value, obj ect.value);
94
95 @override
96 String get typeName => "bool";
97
98 @override
99 bool get hasExactValue => true;
100
101 @override
102 int get hashCode => value == null ? 0 : (value ? 2 : 3);
103
104 /**
105 * Return `true` if this object represents an object whose type is 'bool'.
106 *
107 * @return `true` if this object represents a boolean value
108 */
109 @override
110 bool get isBool => true;
111
112 @override
113 bool get isBoolNumStringOrNull => true;
114
115 @override
116 bool get isUnknown => value == null;
117
118 @override
119 BoolState logicalAnd(InstanceState rightOperand) {
120 assertBool(rightOperand);
121 if (value == null) {
122 return UNKNOWN_VALUE;
123 }
124 return value ? rightOperand.convertToBool() : FALSE_STATE;
125 }
126
127 @override
128 BoolState logicalNot() {
129 if (value == null) {
130 return UNKNOWN_VALUE;
131 }
132 return value ? FALSE_STATE : TRUE_STATE;
133 }
134
135 @override
136 BoolState logicalOr(InstanceState rightOperand) {
137 assertBool(rightOperand);
138 if (value == null) {
139 return UNKNOWN_VALUE;
140 }
141 return value ? TRUE_STATE : rightOperand.convertToBool();
142 }
143
144 @override
145 String toString() => value == null ? "-unknown-" : (value ? "true" : "false");
146 }
147
148 /**
149 * Instances of the class `ConstantEvaluator` evaluate constant expressions to p roduce their
150 * compile-time value. According to the Dart Language Specification: <blockquote > A constant
151 * expression is one of the following:
152 * * A literal number.
153 * * A literal boolean.
154 * * A literal string where any interpolated expression is a compile-time consta nt that evaluates
155 * to a numeric, string or boolean value or to <b>null</b>.
156 * * A literal symbol.
157 * * <b>null</b>.
158 * * A qualified reference to a static constant variable.
159 * * An identifier expression that denotes a constant variable, class or type al ias.
160 * * A constant constructor invocation.
161 * * A constant list literal.
162 * * A constant map literal.
163 * * A simple or qualified identifier denoting a top-level function or a static method.
164 * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant expressi on.
165 * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i> wh ere
166 * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions and <i >identical()</i> is
167 * statically bound to the predefined dart function <i>identical()</i> discussed above.
168 * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or <i>e<sub>1</sub>
169 * != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions
170 * that evaluate to a numeric, string or boolean value.
171 * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp; e< sub>2</sub></i> or
172 * <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>, <i>e1</sub></i> and <i >e2</sub></i> are
173 * constant expressions that evaluate to a boolean value.
174 * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^ e<sub>2</su b></i>,
175 * <i>e<sub>1</sub> &amp; e<sub>2</sub></i>, <i>e<sub>1</sub> | e<sub>2</sub></i >, <i>e<sub>1</sub>
176 * &gt;&gt; e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, wh ere <i>e</i>,
177 * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions that e valuate to an
178 * integer value or to <b>null</b>.
179 * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> + e<sub>2</su b></i>,
180 * <i>e<sub>1</sub> -e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>, <i >e<sub>1</sub> /
181 * e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> &g t;
182 * e<sub>2</sub></i>, <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
183 * e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or <i>e<sub>1</su b> %
184 * e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub>< /i> are constant
185 * expressions that evaluate to a numeric value or to <b>null</b>.
186 * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub>< /i> where
187 * <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and <i>e<sub>3</sub></i> are const ant expressions, and
188 * <i>e<sub>1</sub></i> evaluates to a boolean value.
189 * </blockquote>
190 */
191 class ConstantEvaluator {
192 /**
193 * The source containing the expression(s) that will be evaluated.
194 */
195 final Source _source;
196
197 /**
198 * The type provider used to access the known types.
199 */
200 final TypeProvider _typeProvider;
201
202 /**
203 * Initialize a newly created evaluator to evaluate expressions in the given s ource.
204 *
205 * @param source the source containing the expression(s) that will be evaluate d
206 * @param typeProvider the type provider used to access known types
207 */
208 ConstantEvaluator(this._source, this._typeProvider);
209
210 EvaluationResult evaluate(Expression expression) {
211 EvaluationResultImpl result = expression.accept(new ConstantVisitor.con1(_ty peProvider));
212 if (result is ValidResult) {
213 return EvaluationResult.forValue(result.value);
214 }
215 List<AnalysisError> errors = new List<AnalysisError>();
216 for (ErrorResult_ErrorData data in (result as ErrorResult).errorData) {
217 AstNode node = data.node;
218 errors.add(new AnalysisError.con2(_source, node.offset, node.length, data. errorCode, []));
219 }
220 return EvaluationResult.forErrors(new List.from(errors));
221 }
222 }
223
224 /**
225 * Instances of the class `ConstantFinder` are used to traverse the AST structur es of all of
226 * the compilation units being resolved and build a table mapping constant varia ble elements to the
227 * declarations of those variables.
228 */
229 class ConstantFinder extends RecursiveAstVisitor<Object> {
230 /**
231 * A table mapping constant variable elements to the declarations of those var iables.
232 */
233 final HashMap<VariableElement, VariableDeclaration> variableMap = new HashMap< VariableElement, VariableDeclaration>();
234
235 /**
236 * A table mapping constant constructors to the declarations of those construc tors.
237 */
238 final HashMap<ConstructorElement, ConstructorDeclaration> constructorMap = new HashMap<ConstructorElement, ConstructorDeclaration>();
239
240 /**
241 * A collection of constant constructor invocations.
242 */
243 final List<InstanceCreationExpression> constructorInvocations = new List<Insta nceCreationExpression>();
244
245 @override
246 Object visitConstructorDeclaration(ConstructorDeclaration node) {
247 super.visitConstructorDeclaration(node);
248 if (node.constKeyword != null) {
249 ConstructorElement element = node.element;
250 if (element != null) {
251 constructorMap[element] = node;
252 }
253 }
254 return null;
255 }
256
257 @override
258 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
259 super.visitInstanceCreationExpression(node);
260 if (node.isConst) {
261 constructorInvocations.add(node);
262 }
263 return null;
264 }
265
266 @override
267 Object visitVariableDeclaration(VariableDeclaration node) {
268 super.visitVariableDeclaration(node);
269 Expression initializer = node.initializer;
270 if (initializer != null && node.isConst) {
271 VariableElement element = node.element;
272 if (element != null) {
273 variableMap[element] = node;
274 }
275 }
276 return null;
277 }
278 }
279
280 /**
281 * Instances of the class `ConstantValueComputer` compute the values of constant variables and
282 * constant constructor invocations in one or more compilation units. The expect ed usage pattern is
283 * for the compilation units to be added to this computer using the method
284 * [add] and then for the method [computeValues] to be invoked
285 * exactly once. Any use of an instance after invoking the method [computeValues ] will
286 * result in unpredictable behavior.
287 */
288 class ConstantValueComputer {
289 /**
290 * Parameter to "fromEnvironment" methods that denotes the default value.
291 */
292 static String _DEFAULT_VALUE_PARAM = "defaultValue";
293
294 /**
295 * Source of RegExp matching declarable operator names. From sdk/lib/internal/ symbol.dart.
296 */
297 static String _OPERATOR_RE = "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|un ary-)";
298
299 /**
300 * Source of RegExp matching any public identifier. From sdk/lib/internal/symb ol.dart.
301 */
302 static String _PUBLIC_IDENTIFIER_RE = "(?!${ConstantValueComputer._RESERVED_WO RD_RE}\\b(?!\\\$))[a-zA-Z\$][\\w\$]*";
303
304 /**
305 * Source of RegExp matching Dart reserved words. From sdk/lib/internal/symbol .dart.
306 */
307 static String _RESERVED_WORD_RE = "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:s t|tinue))|d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?: ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|v(?:ar|oid)|w (?:hile|ith))";
308
309 /**
310 * RegExp that validates a non-empty non-private symbol. From sdk/lib/internal /symbol.dart.
311 */
312 static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp("^(?:${ConstantValueComputer ._OPERATOR_RE}\$|${_PUBLIC_IDENTIFIER_RE}(?:=?\$|[.](?!\$)))+?\$");
313
314 /**
315 * Determine whether the given string is a valid name for a public symbol (i.e . whether it is
316 * allowed for a call to the Symbol constructor).
317 */
318 static bool isValidPublicSymbol(String name) => name.isEmpty || name == "void" || new JavaPatternMatcher(_PUBLIC_SYMBOL_PATTERN, name).matches();
319
320 /**
321 * The type provider used to access the known types.
322 */
323 TypeProvider typeProvider;
324
325 /**
326 * The object used to find constant variables and constant constructor invocat ions in the
327 * compilation units that were added.
328 */
329 ConstantFinder _constantFinder = new ConstantFinder();
330
331 /**
332 * A graph in which the nodes are the constants, and the edges are from each c onstant to the other
333 * constants that are referenced by it.
334 */
335 DirectedGraph<AstNode> referenceGraph = new DirectedGraph<AstNode>();
336
337 /**
338 * A table mapping constant variables to the declarations of those variables.
339 */
340 HashMap<VariableElement, VariableDeclaration> _variableDeclarationMap;
341
342 /**
343 * A table mapping constant constructors to the declarations of those construc tors.
344 */
345 HashMap<ConstructorElement, ConstructorDeclaration> constructorDeclarationMap;
346
347 /**
348 * A collection of constant constructor invocations.
349 */
350 List<InstanceCreationExpression> _constructorInvocations;
351
352 /**
353 * The set of variables declared on the command line using '-D'.
354 */
355 final DeclaredVariables _declaredVariables;
356
357 /**
358 * Initialize a newly created constant value computer.
359 *
360 * @param typeProvider the type provider used to access known types
361 * @param declaredVariables the set of variables declared on the command line using '-D'
362 */
363 ConstantValueComputer(TypeProvider typeProvider, this._declaredVariables) {
364 this.typeProvider = typeProvider;
365 }
366
367 /**
368 * Add the constants in the given compilation unit to the list of constants wh ose value needs to
369 * be computed.
370 *
371 * @param unit the compilation unit defining the constants to be added
372 */
373 void add(CompilationUnit unit) {
374 unit.accept(_constantFinder);
375 }
376
377 /**
378 * Compute values for all of the constants in the compilation units that were added.
379 */
380 void computeValues() {
381 _variableDeclarationMap = _constantFinder.variableMap;
382 constructorDeclarationMap = _constantFinder.constructorMap;
383 _constructorInvocations = _constantFinder.constructorInvocations;
384 for (MapEntry<VariableElement, VariableDeclaration> entry in getMapEntrySet( _variableDeclarationMap)) {
385 VariableDeclaration declaration = entry.getValue();
386 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, referen ceGraph, _variableDeclarationMap, constructorDeclarationMap);
387 referenceGraph.addNode(declaration);
388 declaration.initializer.accept(referenceFinder);
389 }
390 for (MapEntry<ConstructorElement, ConstructorDeclaration> entry in getMapEnt rySet(constructorDeclarationMap)) {
391 ConstructorDeclaration declaration = entry.getValue();
392 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, referen ceGraph, _variableDeclarationMap, constructorDeclarationMap);
393 referenceGraph.addNode(declaration);
394 bool superInvocationFound = false;
395 NodeList<ConstructorInitializer> initializers = declaration.initializers;
396 for (ConstructorInitializer initializer in initializers) {
397 if (initializer is SuperConstructorInvocation) {
398 superInvocationFound = true;
399 }
400 initializer.accept(referenceFinder);
401 }
402 if (!superInvocationFound) {
403 // No explicit superconstructor invocation found, so we need to manually insert
404 // a reference to the implicit superconstructor.
405 InterfaceType superclass = (entry.getKey().returnType as InterfaceType). superclass;
406 if (superclass != null && !superclass.isObject) {
407 ConstructorElement unnamedConstructor = superclass.element.unnamedCons tructor;
408 ConstructorDeclaration superConstructorDeclaration = findConstructorDe claration(unnamedConstructor);
409 if (superConstructorDeclaration != null) {
410 referenceGraph.addEdge(declaration, superConstructorDeclaration);
411 }
412 }
413 }
414 for (FormalParameter parameter in declaration.parameters.parameters) {
415 referenceGraph.addNode(parameter);
416 referenceGraph.addEdge(declaration, parameter);
417 if (parameter is DefaultFormalParameter) {
418 Expression defaultValue = parameter.defaultValue;
419 if (defaultValue != null) {
420 ReferenceFinder parameterReferenceFinder = new ReferenceFinder(param eter, referenceGraph, _variableDeclarationMap, constructorDeclarationMap);
421 defaultValue.accept(parameterReferenceFinder);
422 }
423 }
424 }
425 }
426 for (InstanceCreationExpression expression in _constructorInvocations) {
427 referenceGraph.addNode(expression);
428 ConstructorElement constructor = expression.staticElement;
429 if (constructor == null) {
430 break;
431 }
432 constructor = _followConstantRedirectionChain(constructor);
433 ConstructorDeclaration declaration = findConstructorDeclaration(constructo r);
434 // An instance creation expression depends both on the constructor and the arguments passed
435 // to it.
436 ReferenceFinder referenceFinder = new ReferenceFinder(expression, referenc eGraph, _variableDeclarationMap, constructorDeclarationMap);
437 if (declaration != null) {
438 referenceGraph.addEdge(expression, declaration);
439 }
440 expression.argumentList.accept(referenceFinder);
441 }
442 List<List<AstNode>> topologicalSort = referenceGraph.computeTopologicalSort( );
443 for (List<AstNode> constantsInCycle in topologicalSort) {
444 if (constantsInCycle.length == 1) {
445 _computeValueFor(constantsInCycle[0]);
446 } else {
447 for (AstNode constant in constantsInCycle) {
448 _generateCycleError(constantsInCycle, constant);
449 }
450 }
451 }
452 }
453
454 /**
455 * This method is called just before computing the constant value associated w ith an AST node.
456 * Unit tests will override this method to introduce additional error checking .
457 */
458 void beforeComputeValue(AstNode constNode) {
459 }
460
461 /**
462 * This method is called just before getting the constant initializers associa ted with a
463 * constructor AST node. Unit tests will override this method to introduce add itional error
464 * checking.
465 */
466 void beforeGetConstantInitializers(ConstructorElement constructor) {
467 }
468
469 /**
470 * This method is called just before getting a parameter's default value. Unit tests will override
471 * this method to introduce additional error checking.
472 */
473 void beforeGetParameterDefault(ParameterElement parameter) {
474 }
475
476 /**
477 * Create the ConstantVisitor used to evaluate constants. Unit tests will over ride this method to
478 * introduce additional error checking.
479 */
480 ConstantVisitor createConstantVisitor() => new ConstantVisitor.con1(typeProvid er);
481
482 ConstructorDeclaration findConstructorDeclaration(ConstructorElement construct or) => constructorDeclarationMap[_getConstructorBase(constructor)];
483
484 /**
485 * Check that the arguments to a call to fromEnvironment() are correct.
486 *
487 * @param arguments the AST nodes of the arguments.
488 * @param argumentValues the values of the unnamed arguments.
489 * @param namedArgumentValues the values of the named arguments.
490 * @param expectedDefaultValueType the allowed type of the "defaultValue" para meter (if present).
491 * Note: "defaultValue" is always allowed to be null.
492 * @return true if the arguments are correct, false if there is an error.
493 */
494 bool _checkFromEnvironmentArguments(NodeList<Expression> arguments, List<DartO bjectImpl> argumentValues, HashMap<String, DartObjectImpl> namedArgumentValues, InterfaceType expectedDefaultValueType) {
495 int argumentCount = arguments.length;
496 if (argumentCount < 1 || argumentCount > 2) {
497 return false;
498 }
499 if (arguments[0] is NamedExpression) {
500 return false;
501 }
502 if (!identical(argumentValues[0].type, typeProvider.stringType)) {
503 return false;
504 }
505 if (argumentCount == 2) {
506 if (arguments[1] is! NamedExpression) {
507 return false;
508 }
509 if (!((arguments[1] as NamedExpression).name.label.name == _DEFAULT_VALUE_ PARAM)) {
510 return false;
511 }
512 InterfaceType defaultValueType = namedArgumentValues[_DEFAULT_VALUE_PARAM] .type;
513 if (!(identical(defaultValueType, expectedDefaultValueType) || identical(d efaultValueType, typeProvider.nullType))) {
514 return false;
515 }
516 }
517 return true;
518 }
519
520 /**
521 * Check that the arguments to a call to Symbol() are correct.
522 *
523 * @param arguments the AST nodes of the arguments.
524 * @param argumentValues the values of the unnamed arguments.
525 * @param namedArgumentValues the values of the named arguments.
526 * @return true if the arguments are correct, false if there is an error.
527 */
528 bool _checkSymbolArguments(NodeList<Expression> arguments, List<DartObjectImpl > argumentValues, HashMap<String, DartObjectImpl> namedArgumentValues) {
529 if (arguments.length != 1) {
530 return false;
531 }
532 if (arguments[0] is NamedExpression) {
533 return false;
534 }
535 if (!identical(argumentValues[0].type, typeProvider.stringType)) {
536 return false;
537 }
538 String name = argumentValues[0].stringValue;
539 return isValidPublicSymbol(name);
540 }
541
542 /**
543 * Compute a value for the given constant.
544 *
545 * @param constNode the constant for which a value is to be computed
546 */
547 void _computeValueFor(AstNode constNode) {
548 beforeComputeValue(constNode);
549 if (constNode is VariableDeclaration) {
550 VariableDeclaration declaration = constNode;
551 Element element = declaration.element;
552 EvaluationResultImpl result = declaration.initializer.accept(createConstan tVisitor());
553 (element as VariableElementImpl).evaluationResult = result;
554 } else if (constNode is InstanceCreationExpression) {
555 InstanceCreationExpression expression = constNode;
556 ConstructorElement constructor = expression.staticElement;
557 if (constructor == null) {
558 // Couldn't resolve the constructor so we can't compute a value. No pro blem--the error
559 // has already been reported.
560 return;
561 }
562 ConstantVisitor constantVisitor = createConstantVisitor();
563 EvaluationResultImpl result = _evaluateConstructorCall(constNode, expressi on.argumentList.arguments, constructor, constantVisitor);
564 expression.evaluationResult = result;
565 } else if (constNode is ConstructorDeclaration) {
566 ConstructorDeclaration declaration = constNode;
567 NodeList<ConstructorInitializer> initializers = declaration.initializers;
568 ConstructorElementImpl constructor = declaration.element as ConstructorEle mentImpl;
569 constructor.constantInitializers = new ConstantValueComputer_InitializerCl oner().cloneNodeList(initializers);
570 } else if (constNode is FormalParameter) {
571 if (constNode is DefaultFormalParameter) {
572 DefaultFormalParameter parameter = constNode;
573 ParameterElement element = parameter.element;
574 Expression defaultValue = parameter.defaultValue;
575 if (defaultValue != null) {
576 EvaluationResultImpl result = defaultValue.accept(createConstantVisito r());
577 (element as ParameterElementImpl).evaluationResult = result;
578 }
579 }
580 } else {
581 // Should not happen.
582 AnalysisEngine.instance.logger.logError("Constant value computer trying to compute the value of a node which is not a VariableDeclaration, InstanceCreatio nExpression, FormalParameter, or ConstructorDeclaration");
583 return;
584 }
585 }
586
587 /**
588 * Evaluate a call to fromEnvironment() on the bool, int, or String class.
589 *
590 * @param environmentValue Value fetched from the environment
591 * @param builtInDefaultValue Value that should be used as the default if no " defaultValue"
592 * argument appears in [namedArgumentValues].
593 * @param namedArgumentValues Named parameters passed to fromEnvironment()
594 * @return A [ValidResult] object corresponding to the evaluated result
595 */
596 ValidResult _computeValueFromEnvironment(DartObject environmentValue, DartObje ctImpl builtInDefaultValue, HashMap<String, DartObjectImpl> namedArgumentValues) {
597 DartObjectImpl value = environmentValue as DartObjectImpl;
598 if (value.isUnknown || value.isNull) {
599 // The name either doesn't exist in the environment or we couldn't parse t he corresponding
600 // value. If the code supplied an explicit default, use it.
601 if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) {
602 value = namedArgumentValues[_DEFAULT_VALUE_PARAM];
603 } else if (value.isNull) {
604 // The code didn't supply an explicit default. The name exists in the e nvironment but
605 // we couldn't parse the corresponding value. So use the built-in defau lt value, because
606 // this is what the VM does.
607 value = builtInDefaultValue;
608 } else {
609 }
610 }
611 return new ValidResult(value);
612 }
613
614 EvaluationResultImpl _evaluateConstructorCall(AstNode node, NodeList<Expressio n> arguments, ConstructorElement constructor, ConstantVisitor constantVisitor) {
615 int argumentCount = arguments.length;
616 List<DartObjectImpl> argumentValues = new List<DartObjectImpl>(argumentCount );
617 HashMap<String, DartObjectImpl> namedArgumentValues = new HashMap<String, Da rtObjectImpl>();
618 for (int i = 0; i < argumentCount; i++) {
619 Expression argument = arguments[i];
620 if (argument is NamedExpression) {
621 NamedExpression namedExpression = argument;
622 String name = namedExpression.name.label.name;
623 namedArgumentValues[name] = constantVisitor._valueOf(namedExpression.exp ression);
624 argumentValues[i] = constantVisitor.null2;
625 } else {
626 argumentValues[i] = constantVisitor._valueOf(argument);
627 }
628 }
629 constructor = _followConstantRedirectionChain(constructor);
630 InterfaceType definingClass = constructor.returnType as InterfaceType;
631 if (constructor.isFactory) {
632 // We couldn't find a non-factory constructor. See if it's because we rea ched an external
633 // const factory constructor that we can emulate.
634 if (constructor.name == "fromEnvironment") {
635 if (!_checkFromEnvironmentArguments(arguments, argumentValues, namedArgu mentValues, definingClass)) {
636 return new ErrorResult.con1(node, CompileTimeErrorCode.CONST_EVAL_THRO WS_EXCEPTION);
637 }
638 String variableName = argumentCount < 1 ? null : argumentValues[0].strin gValue;
639 if (identical(definingClass, typeProvider.boolType)) {
640 DartObject valueFromEnvironment;
641 valueFromEnvironment = _declaredVariables.getBool(typeProvider, variab leName);
642 return _computeValueFromEnvironment(valueFromEnvironment, new DartObje ctImpl(typeProvider.boolType, BoolState.FALSE_STATE), namedArgumentValues);
643 } else if (identical(definingClass, typeProvider.intType)) {
644 DartObject valueFromEnvironment;
645 valueFromEnvironment = _declaredVariables.getInt(typeProvider, variabl eName);
646 return _computeValueFromEnvironment(valueFromEnvironment, new DartObje ctImpl(typeProvider.nullType, NullState.NULL_STATE), namedArgumentValues);
647 } else if (identical(definingClass, typeProvider.stringType)) {
648 DartObject valueFromEnvironment;
649 valueFromEnvironment = _declaredVariables.getString(typeProvider, vari ableName);
650 return _computeValueFromEnvironment(valueFromEnvironment, new DartObje ctImpl(typeProvider.nullType, NullState.NULL_STATE), namedArgumentValues);
651 }
652 } else if (constructor.name == "" && identical(definingClass, typeProvider .symbolType) && argumentCount == 1) {
653 if (!_checkSymbolArguments(arguments, argumentValues, namedArgumentValue s)) {
654 return new ErrorResult.con1(node, CompileTimeErrorCode.CONST_EVAL_THRO WS_EXCEPTION);
655 }
656 String argumentValue = argumentValues[0].stringValue;
657 return constantVisitor._valid(definingClass, new SymbolState(argumentVal ue));
658 }
659 // Either it's an external const factory constructor that we can't emulate , or an error
660 // occurred (a cycle, or a const constructor trying to delegate to a non-c onst constructor).
661 // In the former case, the best we can do is consider it an unknown value. In the latter
662 // case, the error has already been reported, so considering it an unknown value will
663 // suppress further errors.
664 return constantVisitor._validWithUnknownValue(definingClass);
665 }
666 beforeGetConstantInitializers(constructor);
667 ConstructorElementImpl constructorBase = _getConstructorBase(constructor) as ConstructorElementImpl;
668 List<ConstructorInitializer> initializers = constructorBase.constantInitiali zers;
669 if (initializers == null) {
670 // This can happen in some cases where there are compile errors in the cod e being analyzed
671 // (for example if the code is trying to create a const instance using a n on-const
672 // constructor, or the node we're visiting is involved in a cycle). The e rror has already
673 // been reported, so consider it an unknown value to suppress further erro rs.
674 return constantVisitor._validWithUnknownValue(definingClass);
675 }
676 HashMap<String, DartObjectImpl> fieldMap = new HashMap<String, DartObjectImp l>();
677 HashMap<String, DartObjectImpl> parameterMap = new HashMap<String, DartObjec tImpl>();
678 List<ParameterElement> parameters = constructorBase.parameters;
679 int parameterCount = parameters.length;
680 for (int i = 0; i < parameterCount; i++) {
681 ParameterElement parameter = parameters[i];
682 while (parameter is ParameterMember) {
683 parameter = (parameter as ParameterMember).baseElement;
684 }
685 DartObjectImpl argumentValue = null;
686 if (parameter.parameterKind == ParameterKind.NAMED) {
687 argumentValue = namedArgumentValues[parameter.name];
688 } else if (i < argumentCount) {
689 argumentValue = argumentValues[i];
690 }
691 if (argumentValue == null && parameter is ParameterElementImpl) {
692 // The parameter is an optional positional parameter for which no value was provided, so
693 // use the default value.
694 beforeGetParameterDefault(parameter);
695 EvaluationResultImpl evaluationResult = (parameter as ParameterElementIm pl).evaluationResult;
696 if (evaluationResult is ValidResult) {
697 argumentValue = evaluationResult.value;
698 } else if (evaluationResult == null) {
699 // No default was provided, so the default value is null.
700 argumentValue = constantVisitor.null2;
701 }
702 }
703 if (argumentValue != null) {
704 if (parameter.isInitializingFormal) {
705 FieldElement field = (parameter as FieldFormalParameterElement).field;
706 if (field != null) {
707 String fieldName = field.name;
708 fieldMap[fieldName] = argumentValue;
709 }
710 } else {
711 String name = parameter.name;
712 parameterMap[name] = argumentValue;
713 }
714 }
715 }
716 ConstantVisitor initializerVisitor = new ConstantVisitor.con2(typeProvider, parameterMap);
717 String superName = null;
718 NodeList<Expression> superArguments = null;
719 for (ConstructorInitializer initializer in initializers) {
720 if (initializer is ConstructorFieldInitializer) {
721 ConstructorFieldInitializer constructorFieldInitializer = initializer;
722 Expression initializerExpression = constructorFieldInitializer.expressio n;
723 EvaluationResultImpl evaluationResult = initializerExpression.accept(ini tializerVisitor);
724 if (evaluationResult is ValidResult) {
725 DartObjectImpl value = evaluationResult.value;
726 String fieldName = constructorFieldInitializer.fieldName.name;
727 fieldMap[fieldName] = value;
728 }
729 } else if (initializer is SuperConstructorInvocation) {
730 SuperConstructorInvocation superConstructorInvocation = initializer;
731 SimpleIdentifier name = superConstructorInvocation.constructorName;
732 if (name != null) {
733 superName = name.name;
734 }
735 superArguments = superConstructorInvocation.argumentList.arguments;
736 }
737 }
738 // Evaluate explicit or implicit call to super().
739 InterfaceType superclass = definingClass.superclass;
740 if (superclass != null && !superclass.isObject) {
741 ConstructorElement superConstructor = superclass.lookUpConstructor(superNa me, constructor.library);
742 if (superConstructor != null) {
743 if (superArguments == null) {
744 superArguments = new NodeList<Expression>(null);
745 }
746 _evaluateSuperConstructorCall(node, fieldMap, superConstructor, superArg uments, initializerVisitor);
747 }
748 }
749 return constantVisitor._valid(definingClass, new GenericState(fieldMap));
750 }
751
752 void _evaluateSuperConstructorCall(AstNode node, HashMap<String, DartObjectImp l> fieldMap, ConstructorElement superConstructor, NodeList<Expression> superArgu ments, ConstantVisitor initializerVisitor) {
753 if (superConstructor != null && superConstructor.isConst) {
754 EvaluationResultImpl evaluationResult = _evaluateConstructorCall(node, sup erArguments, superConstructor, initializerVisitor);
755 if (evaluationResult is ValidResult) {
756 ValidResult validResult = evaluationResult;
757 fieldMap[GenericState.SUPERCLASS_FIELD] = validResult.value;
758 }
759 }
760 }
761
762 /**
763 * Attempt to follow the chain of factory redirections until a constructor is reached which is not
764 * a const factory constructor.
765 *
766 * @return the constant constructor which terminates the chain of factory redi rections, if the
767 * chain terminates. If there is a problem (e.g. a redirection can't b e found, or a cycle
768 * is encountered), the chain will be followed as far as possible and then a const factory
769 * constructor will be returned.
770 */
771 ConstructorElement _followConstantRedirectionChain(ConstructorElement construc tor) {
772 HashSet<ConstructorElement> constructorsVisited = new HashSet<ConstructorEle ment>();
773 while (constructor.isFactory) {
774 if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
775 // The dart:core.Symbol has a const factory constructor that redirects t o
776 // dart:_internal.Symbol. That in turn redirects to an external const c onstructor, which
777 // we won't be able to evaluate. So stop following the chain of redirec tions at
778 // dart:core.Symbol, and let [evaluateInstanceCreationExpression] handle it specially.
779 break;
780 }
781 constructorsVisited.add(constructor);
782 ConstructorElement redirectedConstructor = constructor.redirectedConstruct or;
783 if (redirectedConstructor == null) {
784 // This can happen if constructor is an external factory constructor.
785 break;
786 }
787 if (!redirectedConstructor.isConst) {
788 // Delegating to a non-const constructor--this is not allowed (and
789 // is checked elsewhere--see [ErrorVerifier.checkForRedirectToNonConstCo nstructor()]).
790 break;
791 }
792 if (constructorsVisited.contains(redirectedConstructor)) {
793 // Cycle in redirecting factory constructors--this is not allowed
794 // and is checked elsewhere--see [ErrorVerifier.checkForRecursiveFactory Redirect()]).
795 break;
796 }
797 constructor = redirectedConstructor;
798 }
799 return constructor;
800 }
801
802 /**
803 * Generate an error indicating that the given constant is not a valid compile -time constant
804 * because it references at least one of the constants in the given cycle, eac h of which directly
805 * or indirectly references the constant.
806 *
807 * @param constantsInCycle the constants in the cycle that includes the given constant
808 * @param constant the constant that is not a valid compile-time constant
809 */
810 void _generateCycleError(List<AstNode> constantsInCycle, AstNode constant) {
811 }
812
813 ConstructorElement _getConstructorBase(ConstructorElement constructor) {
814 while (constructor is ConstructorMember) {
815 constructor = (constructor as ConstructorMember).baseElement;
816 }
817 return constructor;
818 }
819 }
820
821 /**
822 * [AstCloner] that copies the necessary information from the AST to allow const constructor
823 * initializers to be evaluated.
824 */
825 class ConstantValueComputer_InitializerCloner extends AstCloner {
826 @override
827 InstanceCreationExpression visitInstanceCreationExpression(InstanceCreationExp ression node) {
828 // All we need is the evaluation result, and the keyword so that we know whe ther it's const.
829 InstanceCreationExpression expression = new InstanceCreationExpression(node. keyword, null, null);
830 expression.evaluationResult = node.evaluationResult;
831 return expression;
832 }
833
834 @override
835 SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
836 SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
837 identifier.staticElement = node.staticElement;
838 return identifier;
839 }
840
841 @override
842 SuperConstructorInvocation visitSuperConstructorInvocation(SuperConstructorInv ocation node) {
843 SuperConstructorInvocation invocation = super.visitSuperConstructorInvocatio n(node);
844 invocation.staticElement = node.staticElement;
845 return invocation;
846 }
847 }
848
849 /**
850 * Instances of the class `ConstantVisitor` evaluate constant expressions to pro duce their
851 * compile-time value. According to the Dart Language Specification: <blockquote > A constant
852 * expression is one of the following:
853 * * A literal number.
854 * * A literal boolean.
855 * * A literal string where any interpolated expression is a compile-time consta nt that evaluates
856 * to a numeric, string or boolean value or to <b>null</b>.
857 * * A literal symbol.
858 * * <b>null</b>.
859 * * A qualified reference to a static constant variable.
860 * * An identifier expression that denotes a constant variable, class or type al ias.
861 * * A constant constructor invocation.
862 * * A constant list literal.
863 * * A constant map literal.
864 * * A simple or qualified identifier denoting a top-level function or a static method.
865 * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant expressi on.
866 * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i> wh ere
867 * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions and <i >identical()</i> is
868 * statically bound to the predefined dart function <i>identical()</i> discussed above.
869 * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or <i>e<sub>1</sub>
870 * != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions
871 * that evaluate to a numeric, string or boolean value.
872 * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp; e< sub>2</sub></i> or
873 * <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>, <i>e1</sub></i> and <i >e2</sub></i> are
874 * constant expressions that evaluate to a boolean value.
875 * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^ e<sub>2</su b></i>,
876 * <i>e<sub>1</sub> &amp; e<sub>2</sub></i>, <i>e<sub>1</sub> | e<sub>2</sub></i >, <i>e<sub>1</sub>
877 * &gt;&gt; e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, wh ere <i>e</i>,
878 * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions that e valuate to an
879 * integer value or to <b>null</b>.
880 * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> + e<sub>2</su b></i>,
881 * <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>, < i>e<sub>1</sub> /
882 * e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> &g t;
883 * e<sub>2</sub></i>, <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
884 * e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or <i>e<sub>1</su b> %
885 * e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub>< /i> are constant
886 * expressions that evaluate to a numeric value or to <b>null</b>.
887 * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub>< /i> where
888 * <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and <i>e<sub>3</sub></i> are const ant expressions, and
889 * <i>e<sub>1</sub></i> evaluates to a boolean value.
890 * </blockquote>
891 */
892 class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> {
893 /**
894 * The type provider used to access the known types.
895 */
896 final TypeProvider _typeProvider;
897
898 /**
899 * An shared object representing the value 'null'.
900 */
901 DartObjectImpl _nullObject;
902
903 HashMap<String, DartObjectImpl> _lexicalEnvironment;
904
905 /**
906 * Initialize a newly created constant visitor.
907 *
908 * @param typeProvider the type provider used to access known types
909 * @param lexicalEnvironment values which should override simpleIdentifiers, o r null if no
910 * overriding is necessary.
911 */
912 ConstantVisitor.con1(this._typeProvider) {
913 this._lexicalEnvironment = null;
914 }
915
916 /**
917 * Initialize a newly created constant visitor.
918 *
919 * @param typeProvider the type provider used to access known types
920 * @param lexicalEnvironment values which should override simpleIdentifiers, o r null if no
921 * overriding is necessary.
922 */
923 ConstantVisitor.con2(this._typeProvider, HashMap<String, DartObjectImpl> lexic alEnvironment) {
924 this._lexicalEnvironment = lexicalEnvironment;
925 }
926
927 @override
928 EvaluationResultImpl visitAdjacentStrings(AdjacentStrings node) {
929 EvaluationResultImpl result = null;
930 for (StringLiteral string in node.strings) {
931 if (result == null) {
932 result = string.accept(this);
933 } else {
934 result = result.concatenate(_typeProvider, node, string.accept(this));
935 }
936 }
937 return result;
938 }
939
940 @override
941 EvaluationResultImpl visitBinaryExpression(BinaryExpression node) {
942 EvaluationResultImpl leftResult = node.leftOperand.accept(this);
943 EvaluationResultImpl rightResult = node.rightOperand.accept(this);
944 TokenType operatorType = node.operator.type;
945 // 'null' is almost never good operand
946 if (operatorType != TokenType.BANG_EQ && operatorType != TokenType.EQ_EQ) {
947 if (leftResult is ValidResult && leftResult.isNull || rightResult is Valid Result && rightResult.isNull) {
948 return _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
949 }
950 }
951 // evaluate operator
952 while (true) {
953 if (operatorType == TokenType.AMPERSAND) {
954 return leftResult.bitAnd(_typeProvider, node, rightResult);
955 } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
956 return leftResult.logicalAnd(_typeProvider, node, rightResult);
957 } else if (operatorType == TokenType.BANG_EQ) {
958 return leftResult.notEqual(_typeProvider, node, rightResult);
959 } else if (operatorType == TokenType.BAR) {
960 return leftResult.bitOr(_typeProvider, node, rightResult);
961 } else if (operatorType == TokenType.BAR_BAR) {
962 return leftResult.logicalOr(_typeProvider, node, rightResult);
963 } else if (operatorType == TokenType.CARET) {
964 return leftResult.bitXor(_typeProvider, node, rightResult);
965 } else if (operatorType == TokenType.EQ_EQ) {
966 return leftResult.equalEqual(_typeProvider, node, rightResult);
967 } else if (operatorType == TokenType.GT) {
968 return leftResult.greaterThan(_typeProvider, node, rightResult);
969 } else if (operatorType == TokenType.GT_EQ) {
970 return leftResult.greaterThanOrEqual(_typeProvider, node, rightResult);
971 } else if (operatorType == TokenType.GT_GT) {
972 return leftResult.shiftRight(_typeProvider, node, rightResult);
973 } else if (operatorType == TokenType.LT) {
974 return leftResult.lessThan(_typeProvider, node, rightResult);
975 } else if (operatorType == TokenType.LT_EQ) {
976 return leftResult.lessThanOrEqual(_typeProvider, node, rightResult);
977 } else if (operatorType == TokenType.LT_LT) {
978 return leftResult.shiftLeft(_typeProvider, node, rightResult);
979 } else if (operatorType == TokenType.MINUS) {
980 return leftResult.minus(_typeProvider, node, rightResult);
981 } else if (operatorType == TokenType.PERCENT) {
982 return leftResult.remainder(_typeProvider, node, rightResult);
983 } else if (operatorType == TokenType.PLUS) {
984 return leftResult.add(_typeProvider, node, rightResult);
985 } else if (operatorType == TokenType.STAR) {
986 return leftResult.times(_typeProvider, node, rightResult);
987 } else if (operatorType == TokenType.SLASH) {
988 return leftResult.divide(_typeProvider, node, rightResult);
989 } else if (operatorType == TokenType.TILDE_SLASH) {
990 return leftResult.integerDivide(_typeProvider, node, rightResult);
991 } else {
992 // TODO(brianwilkerson) Figure out which error to report.
993 return _error(node, null);
994 }
995 break;
996 }
997 }
998
999 @override
1000 EvaluationResultImpl visitBooleanLiteral(BooleanLiteral node) => _valid(_typeP rovider.boolType, BoolState.from(node.value));
1001
1002 @override
1003 EvaluationResultImpl visitConditionalExpression(ConditionalExpression node) {
1004 Expression condition = node.condition;
1005 EvaluationResultImpl conditionResult = condition.accept(this);
1006 EvaluationResultImpl thenResult = node.thenExpression.accept(this);
1007 EvaluationResultImpl elseResult = node.elseExpression.accept(this);
1008 if (conditionResult is ErrorResult) {
1009 return _union(_union(conditionResult as ErrorResult, thenResult), elseResu lt);
1010 } else if (!(conditionResult as ValidResult).isBool) {
1011 return new ErrorResult.con1(condition, CompileTimeErrorCode.CONST_EVAL_TYP E_BOOL);
1012 } else if (thenResult is ErrorResult) {
1013 return _union(thenResult, elseResult);
1014 } else if (elseResult is ErrorResult) {
1015 return elseResult;
1016 }
1017 conditionResult = conditionResult.applyBooleanConversion(_typeProvider, cond ition);
1018 if (conditionResult is ErrorResult) {
1019 return conditionResult;
1020 }
1021 ValidResult validResult = conditionResult as ValidResult;
1022 if (validResult.isTrue) {
1023 return thenResult;
1024 } else if (validResult.isFalse) {
1025 return elseResult;
1026 }
1027 InterfaceType thenType = (thenResult as ValidResult).value.type;
1028 InterfaceType elseType = (elseResult as ValidResult).value.type;
1029 return _validWithUnknownValue(thenType.getLeastUpperBound(elseType) as Inter faceType);
1030 }
1031
1032 @override
1033 EvaluationResultImpl visitDoubleLiteral(DoubleLiteral node) => _valid(_typePro vider.doubleType, new DoubleState(node.value));
1034
1035 @override
1036 EvaluationResultImpl visitInstanceCreationExpression(InstanceCreationExpressio n node) {
1037 if (!node.isConst) {
1038 // TODO(brianwilkerson) Figure out which error to report.
1039 return _error(node, null);
1040 }
1041 beforeGetEvaluationResult(node);
1042 EvaluationResultImpl result = node.evaluationResult;
1043 if (result != null) {
1044 return result;
1045 }
1046 // TODO(brianwilkerson) Figure out which error to report.
1047 return _error(node, null);
1048 }
1049
1050 @override
1051 EvaluationResultImpl visitIntegerLiteral(IntegerLiteral node) => _valid(_typeP rovider.intType, new IntState(node.value));
1052
1053 @override
1054 EvaluationResultImpl visitInterpolationExpression(InterpolationExpression node ) {
1055 EvaluationResultImpl result = node.expression.accept(this);
1056 if (result is ValidResult && !result.isBoolNumStringOrNull) {
1057 return _error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
1058 }
1059 return result.performToString(_typeProvider, node);
1060 }
1061
1062 @override
1063 EvaluationResultImpl visitInterpolationString(InterpolationString node) => _va lid(_typeProvider.stringType, new StringState(node.value));
1064
1065 @override
1066 EvaluationResultImpl visitListLiteral(ListLiteral node) {
1067 if (node.constKeyword == null) {
1068 return new ErrorResult.con1(node, CompileTimeErrorCode.MISSING_CONST_IN_LI ST_LITERAL);
1069 }
1070 ErrorResult result = null;
1071 List<DartObjectImpl> elements = new List<DartObjectImpl>();
1072 for (Expression element in node.elements) {
1073 EvaluationResultImpl elementResult = element.accept(this);
1074 result = _union(result, elementResult);
1075 if (elementResult is ValidResult) {
1076 elements.add(elementResult.value);
1077 }
1078 }
1079 if (result != null) {
1080 return result;
1081 }
1082 return _valid(_typeProvider.listType, new ListState(new List.from(elements)) );
1083 }
1084
1085 @override
1086 EvaluationResultImpl visitMapLiteral(MapLiteral node) {
1087 if (node.constKeyword == null) {
1088 return new ErrorResult.con1(node, CompileTimeErrorCode.MISSING_CONST_IN_MA P_LITERAL);
1089 }
1090 ErrorResult result = null;
1091 HashMap<DartObjectImpl, DartObjectImpl> map = new HashMap<DartObjectImpl, Da rtObjectImpl>();
1092 for (MapLiteralEntry entry in node.entries) {
1093 EvaluationResultImpl keyResult = entry.key.accept(this);
1094 EvaluationResultImpl valueResult = entry.value.accept(this);
1095 result = _union(result, keyResult);
1096 result = _union(result, valueResult);
1097 if (keyResult is ValidResult && valueResult is ValidResult) {
1098 map[keyResult.value] = valueResult.value;
1099 }
1100 }
1101 if (result != null) {
1102 return result;
1103 }
1104 return _valid(_typeProvider.mapType, new MapState(map));
1105 }
1106
1107 @override
1108 EvaluationResultImpl visitMethodInvocation(MethodInvocation node) {
1109 Element element = node.methodName.staticElement;
1110 if (element is FunctionElement) {
1111 FunctionElement function = element;
1112 if (function.name == "identical") {
1113 NodeList<Expression> arguments = node.argumentList.arguments;
1114 if (arguments.length == 2) {
1115 Element enclosingElement = function.enclosingElement;
1116 if (enclosingElement is CompilationUnitElement) {
1117 LibraryElement library = enclosingElement.library;
1118 if (library.isDartCore) {
1119 EvaluationResultImpl leftArgument = arguments[0].accept(this);
1120 EvaluationResultImpl rightArgument = arguments[1].accept(this);
1121 return leftArgument.equalEqual(_typeProvider, node, rightArgument) ;
1122 }
1123 }
1124 }
1125 }
1126 }
1127 // TODO(brianwilkerson) Figure out which error to report.
1128 return _error(node, null);
1129 }
1130
1131 @override
1132 EvaluationResultImpl visitNamedExpression(NamedExpression node) => node.expres sion.accept(this);
1133
1134 @override
1135 EvaluationResultImpl visitNode(AstNode node) => _error(node, null);
1136
1137 @override
1138 EvaluationResultImpl visitNullLiteral(NullLiteral node) => new ValidResult(nul l2);
1139
1140 @override
1141 EvaluationResultImpl visitParenthesizedExpression(ParenthesizedExpression node ) => node.expression.accept(this);
1142
1143 @override
1144 EvaluationResultImpl visitPrefixedIdentifier(PrefixedIdentifier node) {
1145 // validate prefix
1146 SimpleIdentifier prefixNode = node.prefix;
1147 Element prefixElement = prefixNode.staticElement;
1148 if (prefixElement is! PrefixElement) {
1149 EvaluationResultImpl prefixResult = prefixNode.accept(this);
1150 if (prefixResult is! ValidResult) {
1151 return _error(node, null);
1152 }
1153 }
1154 // validate prefixed identifier
1155 return _getConstantValue(node, node.staticElement);
1156 }
1157
1158 @override
1159 EvaluationResultImpl visitPrefixExpression(PrefixExpression node) {
1160 EvaluationResultImpl operand = node.operand.accept(this);
1161 if (operand is ValidResult && operand.isNull) {
1162 return _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
1163 }
1164 while (true) {
1165 if (node.operator.type == TokenType.BANG) {
1166 return operand.logicalNot(_typeProvider, node);
1167 } else if (node.operator.type == TokenType.TILDE) {
1168 return operand.bitNot(_typeProvider, node);
1169 } else if (node.operator.type == TokenType.MINUS) {
1170 return operand.negated(_typeProvider, node);
1171 } else {
1172 // TODO(brianwilkerson) Figure out which error to report.
1173 return _error(node, null);
1174 }
1175 break;
1176 }
1177 }
1178
1179 @override
1180 EvaluationResultImpl visitPropertyAccess(PropertyAccess node) => _getConstantV alue(node, node.propertyName.staticElement);
1181
1182 @override
1183 EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) {
1184 if (_lexicalEnvironment != null && _lexicalEnvironment.containsKey(node.name )) {
1185 return new ValidResult(_lexicalEnvironment[node.name]);
1186 }
1187 return _getConstantValue(node, node.staticElement);
1188 }
1189
1190 @override
1191 EvaluationResultImpl visitSimpleStringLiteral(SimpleStringLiteral node) => _va lid(_typeProvider.stringType, new StringState(node.value));
1192
1193 @override
1194 EvaluationResultImpl visitStringInterpolation(StringInterpolation node) {
1195 EvaluationResultImpl result = null;
1196 for (InterpolationElement element in node.elements) {
1197 if (result == null) {
1198 result = element.accept(this);
1199 } else {
1200 result = result.concatenate(_typeProvider, node, element.accept(this));
1201 }
1202 }
1203 return result;
1204 }
1205
1206 @override
1207 EvaluationResultImpl visitSymbolLiteral(SymbolLiteral node) {
1208 JavaStringBuilder builder = new JavaStringBuilder();
1209 List<Token> components = node.components;
1210 for (int i = 0; i < components.length; i++) {
1211 if (i > 0) {
1212 builder.appendChar(0x2E);
1213 }
1214 builder.append(components[i].lexeme);
1215 }
1216 return _valid(_typeProvider.symbolType, new SymbolState(builder.toString())) ;
1217 }
1218
1219 /**
1220 * This method is called just before retrieving an evaluation result from an A ST node. Unit tests
1221 * will override it to introduce additional error checking.
1222 */
1223 void beforeGetEvaluationResult(AstNode node) {
1224 }
1225
1226 /**
1227 * Return an object representing the value 'null'.
1228 *
1229 * @return an object representing the value 'null'
1230 */
1231 DartObjectImpl get null2 {
1232 if (_nullObject == null) {
1233 _nullObject = new DartObjectImpl(_typeProvider.nullType, NullState.NULL_ST ATE);
1234 }
1235 return _nullObject;
1236 }
1237
1238 ValidResult _valid(InterfaceType type, InstanceState state) => new ValidResult (new DartObjectImpl(type, state));
1239
1240 ValidResult _validWithUnknownValue(InterfaceType type) {
1241 if (type.element.library.isDartCore) {
1242 String typeName = type.name;
1243 if (typeName == "bool") {
1244 return _valid(type, BoolState.UNKNOWN_VALUE);
1245 } else if (typeName == "double") {
1246 return _valid(type, DoubleState.UNKNOWN_VALUE);
1247 } else if (typeName == "int") {
1248 return _valid(type, IntState.UNKNOWN_VALUE);
1249 } else if (typeName == "String") {
1250 return _valid(type, StringState.UNKNOWN_VALUE);
1251 }
1252 }
1253 return _valid(type, GenericState.UNKNOWN_VALUE);
1254 }
1255
1256 /**
1257 * Return the value of the given expression, or a representation of 'null' if the expression
1258 * cannot be evaluated.
1259 *
1260 * @param expression the expression whose value is to be returned
1261 * @return the value of the given expression
1262 */
1263 DartObjectImpl _valueOf(Expression expression) {
1264 EvaluationResultImpl expressionValue = expression.accept(this);
1265 if (expressionValue is ValidResult) {
1266 return expressionValue.value;
1267 }
1268 return null2;
1269 }
1270
1271 /**
1272 * Return a result object representing an error associated with the given node .
1273 *
1274 * @param node the AST node associated with the error
1275 * @param code the error code indicating the nature of the error
1276 * @return a result object representing an error associated with the given nod e
1277 */
1278 ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node, code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code);
1279
1280 /**
1281 * Return the constant value of the static constant represented by the given e lement.
1282 *
1283 * @param node the node to be used if an error needs to be reported
1284 * @param element the element whose value is to be returned
1285 * @return the constant value of the static constant
1286 */
1287 EvaluationResultImpl _getConstantValue(AstNode node, Element element) {
1288 if (element is PropertyAccessorElement) {
1289 element = (element as PropertyAccessorElement).variable;
1290 }
1291 if (element is VariableElementImpl) {
1292 VariableElementImpl variableElementImpl = element;
1293 beforeGetEvaluationResult(node);
1294 EvaluationResultImpl value = variableElementImpl.evaluationResult;
1295 if (variableElementImpl.isConst && value != null) {
1296 return value;
1297 }
1298 } else if (element is ExecutableElement) {
1299 ExecutableElement function = element;
1300 if (function.isStatic) {
1301 return _valid(_typeProvider.functionType, new FunctionState(function));
1302 }
1303 } else if (element is ClassElement || element is FunctionTypeAliasElement) {
1304 return _valid(_typeProvider.typeType, new TypeState(element));
1305 }
1306 // TODO(brianwilkerson) Figure out which error to report.
1307 return _error(node, null);
1308 }
1309
1310 /**
1311 * Return the union of the errors encoded in the given results.
1312 *
1313 * @param leftResult the first set of errors, or `null` if there was no previo us collection
1314 * of errors
1315 * @param rightResult the errors to be added to the collection, or a valid res ult if there are no
1316 * errors to be added
1317 * @return the union of the errors encoded in the given results
1318 */
1319 ErrorResult _union(ErrorResult leftResult, EvaluationResultImpl rightResult) {
1320 if (rightResult is ErrorResult) {
1321 if (leftResult != null) {
1322 return new ErrorResult.con2(leftResult, rightResult);
1323 } else {
1324 return rightResult;
1325 }
1326 }
1327 return leftResult;
1328 }
1329 }
1330
1331 /**
1332 * The interface `DartObject` defines the behavior of objects that represent the state of a
1333 * Dart object.
1334 */
1335 abstract class DartObject {
1336 /**
1337 * Return the boolean value of this object, or `null` if either the value of t his object is
1338 * not known or this object is not of type 'bool'.
1339 *
1340 * @return the boolean value of this object
1341 */
1342 bool get boolValue;
1343
1344 /**
1345 * Return the floating point value of this object, or `null` if either the val ue of this
1346 * object is not known or this object is not of type 'double'.
1347 *
1348 * @return the floating point value of this object
1349 */
1350 double get doubleValue;
1351
1352 /**
1353 * Return the integer value of this object, or `null` if either the value of t his object is
1354 * not known or this object is not of type 'int'.
1355 *
1356 * @return the integer value of this object
1357 */
1358 int get intValue;
1359
1360 /**
1361 * Return the string value of this object, or `null` if either the value of th is object is
1362 * not known or this object is not of type 'String'.
1363 *
1364 * @return the string value of this object
1365 */
1366 String get stringValue;
1367
1368 /**
1369 * Return the run-time type of this object.
1370 *
1371 * @return the run-time type of this object
1372 */
1373 InterfaceType get type;
1374
1375 /**
1376 * Return this object's value if it can be represented exactly, or `null` if e ither the
1377 * value cannot be represented exactly or if the value is `null`. Clients shou ld use
1378 * [hasExactValue] to distinguish between these two cases.
1379 *
1380 * @return this object's value
1381 */
1382 Object get value;
1383
1384 /**
1385 * Return `true` if this object's value can be represented exactly.
1386 *
1387 * @return `true` if this object's value can be represented exactly
1388 */
1389 bool get hasExactValue;
1390
1391 /**
1392 * Return `true` if this object represents the value 'false'.
1393 *
1394 * @return `true` if this object represents the value 'false'
1395 */
1396 bool get isFalse;
1397
1398 /**
1399 * Return `true` if this object represents the value 'null'.
1400 *
1401 * @return `true` if this object represents the value 'null'
1402 */
1403 bool get isNull;
1404
1405 /**
1406 * Return `true` if this object represents the value 'true'.
1407 *
1408 * @return `true` if this object represents the value 'true'
1409 */
1410 bool get isTrue;
1411 }
1412
1413 /**
1414 * Instances of the class `DartObjectImpl` represent an instance of a Dart class .
1415 */
1416 class DartObjectImpl implements DartObject {
1417 /**
1418 * The run-time type of this object.
1419 */
1420 final InterfaceType type;
1421
1422 /**
1423 * The state of the object.
1424 */
1425 final InstanceState _state;
1426
1427 /**
1428 * Initialize a newly created object to have the given type and state.
1429 *
1430 * @param type the run-time type of this object
1431 * @param state the state of the object
1432 */
1433 DartObjectImpl(this.type, this._state);
1434
1435 /**
1436 * Return the result of invoking the '+' operator on this object with the give n argument.
1437 *
1438 * @param typeProvider the type provider used to find known types
1439 * @param rightOperand the right-hand operand of the operation
1440 * @return the result of invoking the '+' operator on this object with the giv en argument
1441 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1442 */
1443 DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) {
1444 InstanceState result = _state.add(rightOperand._state);
1445 if (result is IntState) {
1446 return new DartObjectImpl(typeProvider.intType, result);
1447 } else if (result is DoubleState) {
1448 return new DartObjectImpl(typeProvider.doubleType, result);
1449 } else if (result is NumState) {
1450 return new DartObjectImpl(typeProvider.numType, result);
1451 }
1452 // We should never get here.
1453 throw new IllegalStateException("add returned a ${result.runtimeType.toStrin g()}");
1454 }
1455
1456 /**
1457 * Return the result of invoking the '&' operator on this object with the give n argument.
1458 *
1459 * @param typeProvider the type provider used to find known types
1460 * @param rightOperand the right-hand operand of the operation
1461 * @return the result of invoking the '&' operator on this object with the giv en argument
1462 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1463 */
1464 DartObjectImpl bitAnd(TypeProvider typeProvider, DartObjectImpl rightOperand) => new DartObjectImpl(typeProvider.intType, _state.bitAnd(rightOperand._state));
1465
1466 /**
1467 * Return the result of invoking the '~' operator on this object.
1468 *
1469 * @param typeProvider the type provider used to find known types
1470 * @return the result of invoking the '~' operator on this object
1471 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1472 */
1473 DartObjectImpl bitNot(TypeProvider typeProvider) => new DartObjectImpl(typePro vider.intType, _state.bitNot());
1474
1475 /**
1476 * Return the result of invoking the '|' operator on this object with the give n argument.
1477 *
1478 * @param typeProvider the type provider used to find known types
1479 * @param rightOperand the right-hand operand of the operation
1480 * @return the result of invoking the '|' operator on this object with the giv en argument
1481 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1482 */
1483 DartObjectImpl bitOr(TypeProvider typeProvider, DartObjectImpl rightOperand) = > new DartObjectImpl(typeProvider.intType, _state.bitOr(rightOperand._state));
1484
1485 /**
1486 * Return the result of invoking the '^' operator on this object with the give n argument.
1487 *
1488 * @param typeProvider the type provider used to find known types
1489 * @param rightOperand the right-hand operand of the operation
1490 * @return the result of invoking the '^' operator on this object with the giv en argument
1491 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1492 */
1493 DartObjectImpl bitXor(TypeProvider typeProvider, DartObjectImpl rightOperand) => new DartObjectImpl(typeProvider.intType, _state.bitXor(rightOperand._state));
1494
1495 /**
1496 * Return the result of invoking the ' ' operator on this object with the give n argument.
1497 *
1498 * @param typeProvider the type provider used to find known types
1499 * @param rightOperand the right-hand operand of the operation
1500 * @return the result of invoking the ' ' operator on this object with the giv en argument
1501 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1502 */
1503 DartObjectImpl concatenate(TypeProvider typeProvider, DartObjectImpl rightOper and) => new DartObjectImpl(typeProvider.stringType, _state.concatenate(rightOper and._state));
1504
1505 /**
1506 * Return the result of applying boolean conversion to this object.
1507 *
1508 * @param typeProvider the type provider used to find known types
1509 * @return the result of applying boolean conversion to this object
1510 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1511 */
1512 DartObjectImpl convertToBool(TypeProvider typeProvider) {
1513 InterfaceType boolType = typeProvider.boolType;
1514 if (identical(type, boolType)) {
1515 return this;
1516 }
1517 return new DartObjectImpl(boolType, _state.convertToBool());
1518 }
1519
1520 /**
1521 * Return the result of invoking the '/' operator on this object with the give n argument.
1522 *
1523 * @param typeProvider the type provider used to find known types
1524 * @param rightOperand the right-hand operand of the operation
1525 * @return the result of invoking the '/' operator on this object with the giv en argument
1526 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1527 */
1528 DartObjectImpl divide(TypeProvider typeProvider, DartObjectImpl rightOperand) {
1529 InstanceState result = _state.divide(rightOperand._state);
1530 if (result is IntState) {
1531 return new DartObjectImpl(typeProvider.intType, result);
1532 } else if (result is DoubleState) {
1533 return new DartObjectImpl(typeProvider.doubleType, result);
1534 } else if (result is NumState) {
1535 return new DartObjectImpl(typeProvider.numType, result);
1536 }
1537 // We should never get here.
1538 throw new IllegalStateException("divide returned a ${result.runtimeType.toSt ring()}");
1539 }
1540
1541 /**
1542 * Return the result of invoking the '==' operator on this object with the giv en argument.
1543 *
1544 * @param typeProvider the type provider used to find known types
1545 * @param rightOperand the right-hand operand of the operation
1546 * @return the result of invoking the '==' operator on this object with the gi ven argument
1547 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1548 */
1549 DartObjectImpl equalEqual(TypeProvider typeProvider, DartObjectImpl rightOpera nd) {
1550 if (type != rightOperand.type) {
1551 String typeName = type.name;
1552 if (!(typeName == "bool" || typeName == "double" || typeName == "int" || t ypeName == "num" || typeName == "String" || typeName == "Null" || type.isDynamic )) {
1553 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_ NUM_STRING);
1554 }
1555 }
1556 return new DartObjectImpl(typeProvider.boolType, _state.equalEqual(rightOper and._state));
1557 }
1558
1559 @override
1560 bool operator ==(Object object) {
1561 if (object is! DartObjectImpl) {
1562 return false;
1563 }
1564 DartObjectImpl dartObject = object as DartObjectImpl;
1565 return type == dartObject.type && _state == dartObject._state;
1566 }
1567
1568 @override
1569 bool get boolValue {
1570 if (_state is BoolState) {
1571 return (_state as BoolState).value;
1572 }
1573 return null;
1574 }
1575
1576 @override
1577 double get doubleValue {
1578 if (_state is DoubleState) {
1579 return (_state as DoubleState).value;
1580 }
1581 return null;
1582 }
1583
1584 HashMap<String, DartObjectImpl> get fields => _state.fields;
1585
1586 @override
1587 int get intValue {
1588 if (_state is IntState) {
1589 return (_state as IntState).value;
1590 }
1591 return null;
1592 }
1593
1594 @override
1595 String get stringValue {
1596 if (_state is StringState) {
1597 return (_state as StringState).value;
1598 }
1599 return null;
1600 }
1601
1602 @override
1603 Object get value => _state.value;
1604
1605 /**
1606 * Return the result of invoking the '&gt;' operator on this object with the g iven argument.
1607 *
1608 * @param typeProvider the type provider used to find known types
1609 * @param rightOperand the right-hand operand of the operation
1610 * @return the result of invoking the '&gt;' operator on this object with the given argument
1611 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1612 */
1613 DartObjectImpl greaterThan(TypeProvider typeProvider, DartObjectImpl rightOper and) => new DartObjectImpl(typeProvider.boolType, _state.greaterThan(rightOperan d._state));
1614
1615 /**
1616 * Return the result of invoking the '&gt;=' operator on this object with the given argument.
1617 *
1618 * @param typeProvider the type provider used to find known types
1619 * @param rightOperand the right-hand operand of the operation
1620 * @return the result of invoking the '&gt;=' operator on this object with the given argument
1621 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1622 */
1623 DartObjectImpl greaterThanOrEqual(TypeProvider typeProvider, DartObjectImpl ri ghtOperand) => new DartObjectImpl(typeProvider.boolType, _state.greaterThanOrEqu al(rightOperand._state));
1624
1625 @override
1626 bool get hasExactValue => _state.hasExactValue;
1627
1628 @override
1629 int get hashCode => ObjectUtilities.combineHashCodes(type.hashCode, _state.has hCode);
1630
1631 /**
1632 * Return the result of invoking the '~/' operator on this object with the giv en argument.
1633 *
1634 * @param typeProvider the type provider used to find known types
1635 * @param rightOperand the right-hand operand of the operation
1636 * @return the result of invoking the '~/' operator on this object with the gi ven argument
1637 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1638 */
1639 DartObjectImpl integerDivide(TypeProvider typeProvider, DartObjectImpl rightOp erand) => new DartObjectImpl(typeProvider.intType, _state.integerDivide(rightOpe rand._state));
1640
1641 /**
1642 * Return `true` if this object represents an object whose type is 'bool'.
1643 *
1644 * @return `true` if this object represents a boolean value
1645 */
1646 bool get isBool => _state.isBool;
1647
1648 /**
1649 * Return `true` if this object represents an object whose type is either 'boo l', 'num',
1650 * 'String', or 'Null'.
1651 *
1652 * @return `true` if this object represents either a boolean, numeric, string or null value
1653 */
1654 bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
1655
1656 @override
1657 bool get isFalse => _state is BoolState && identical((_state as BoolState).val ue, false);
1658
1659 @override
1660 bool get isNull => _state is NullState;
1661
1662 @override
1663 bool get isTrue => _state is BoolState && identical((_state as BoolState).valu e, true);
1664
1665 /**
1666 * Return true if this object represents an unknown value.
1667 */
1668 bool get isUnknown => _state.isUnknown;
1669
1670 /**
1671 * Return `true` if this object represents an instance of a user-defined class .
1672 *
1673 * @return `true` if this object represents an instance of a user-defined clas s
1674 */
1675 bool get isUserDefinedObject => _state is GenericState;
1676
1677 /**
1678 * Return the result of invoking the '&lt;' operator on this object with the g iven argument.
1679 *
1680 * @param typeProvider the type provider used to find known types
1681 * @param rightOperand the right-hand operand of the operation
1682 * @return the result of invoking the '&lt;' operator on this object with the given argument
1683 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1684 */
1685 DartObjectImpl lessThan(TypeProvider typeProvider, DartObjectImpl rightOperand ) => new DartObjectImpl(typeProvider.boolType, _state.lessThan(rightOperand._sta te));
1686
1687 /**
1688 * Return the result of invoking the '&lt;=' operator on this object with the given argument.
1689 *
1690 * @param typeProvider the type provider used to find known types
1691 * @param rightOperand the right-hand operand of the operation
1692 * @return the result of invoking the '&lt;=' operator on this object with the given argument
1693 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1694 */
1695 DartObjectImpl lessThanOrEqual(TypeProvider typeProvider, DartObjectImpl right Operand) => new DartObjectImpl(typeProvider.boolType, _state.lessThanOrEqual(rig htOperand._state));
1696
1697 /**
1698 * Return the result of invoking the '&&' operator on this object with the giv en argument.
1699 *
1700 * @param typeProvider the type provider used to find known types
1701 * @param rightOperand the right-hand operand of the operation
1702 * @return the result of invoking the '&&' operator on this object with the gi ven argument
1703 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1704 */
1705 DartObjectImpl logicalAnd(TypeProvider typeProvider, DartObjectImpl rightOpera nd) => new DartObjectImpl(typeProvider.boolType, _state.logicalAnd(rightOperand. _state));
1706
1707 /**
1708 * Return the result of invoking the '!' operator on this object.
1709 *
1710 * @param typeProvider the type provider used to find known types
1711 * @return the result of invoking the '!' operator on this object
1712 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1713 */
1714 DartObjectImpl logicalNot(TypeProvider typeProvider) => new DartObjectImpl(typ eProvider.boolType, _state.logicalNot());
1715
1716 /**
1717 * Return the result of invoking the '||' operator on this object with the giv en argument.
1718 *
1719 * @param typeProvider the type provider used to find known types
1720 * @param rightOperand the right-hand operand of the operation
1721 * @return the result of invoking the '||' operator on this object with the gi ven argument
1722 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1723 */
1724 DartObjectImpl logicalOr(TypeProvider typeProvider, DartObjectImpl rightOperan d) => new DartObjectImpl(typeProvider.boolType, _state.logicalOr(rightOperand._s tate));
1725
1726 /**
1727 * Return the result of invoking the '-' operator on this object with the give n argument.
1728 *
1729 * @param typeProvider the type provider used to find known types
1730 * @param rightOperand the right-hand operand of the operation
1731 * @return the result of invoking the '-' operator on this object with the giv en argument
1732 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1733 */
1734 DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) {
1735 InstanceState result = _state.minus(rightOperand._state);
1736 if (result is IntState) {
1737 return new DartObjectImpl(typeProvider.intType, result);
1738 } else if (result is DoubleState) {
1739 return new DartObjectImpl(typeProvider.doubleType, result);
1740 } else if (result is NumState) {
1741 return new DartObjectImpl(typeProvider.numType, result);
1742 }
1743 // We should never get here.
1744 throw new IllegalStateException("minus returned a ${result.runtimeType.toStr ing()}");
1745 }
1746
1747 /**
1748 * Return the result of invoking the '-' operator on this object.
1749 *
1750 * @param typeProvider the type provider used to find known types
1751 * @return the result of invoking the '-' operator on this object
1752 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1753 */
1754 DartObjectImpl negated(TypeProvider typeProvider) {
1755 InstanceState result = _state.negated();
1756 if (result is IntState) {
1757 return new DartObjectImpl(typeProvider.intType, result);
1758 } else if (result is DoubleState) {
1759 return new DartObjectImpl(typeProvider.doubleType, result);
1760 } else if (result is NumState) {
1761 return new DartObjectImpl(typeProvider.numType, result);
1762 }
1763 // We should never get here.
1764 throw new IllegalStateException("negated returned a ${result.runtimeType.toS tring()}");
1765 }
1766
1767 /**
1768 * Return the result of invoking the '!=' operator on this object with the giv en argument.
1769 *
1770 * @param typeProvider the type provider used to find known types
1771 * @param rightOperand the right-hand operand of the operation
1772 * @return the result of invoking the '!=' operator on this object with the gi ven argument
1773 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1774 */
1775 DartObjectImpl notEqual(TypeProvider typeProvider, DartObjectImpl rightOperand ) {
1776 if (type != rightOperand.type) {
1777 String typeName = type.name;
1778 if (typeName != "bool" && typeName != "double" && typeName != "int" && typ eName != "num" && typeName != "String") {
1779 return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
1780 }
1781 }
1782 return new DartObjectImpl(typeProvider.boolType, _state.equalEqual(rightOper and._state).logicalNot());
1783 }
1784
1785 /**
1786 * Return the result of converting this object to a String.
1787 *
1788 * @param typeProvider the type provider used to find known types
1789 * @return the result of converting this object to a String
1790 * @throws EvaluationException if the object cannot be converted to a String
1791 */
1792 DartObjectImpl performToString(TypeProvider typeProvider) {
1793 InterfaceType stringType = typeProvider.stringType;
1794 if (identical(type, stringType)) {
1795 return this;
1796 }
1797 return new DartObjectImpl(stringType, _state.convertToString());
1798 }
1799
1800 /**
1801 * Return the result of invoking the '%' operator on this object with the give n argument.
1802 *
1803 * @param typeProvider the type provider used to find known types
1804 * @param rightOperand the right-hand operand of the operation
1805 * @return the result of invoking the '%' operator on this object with the giv en argument
1806 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1807 */
1808 DartObjectImpl remainder(TypeProvider typeProvider, DartObjectImpl rightOperan d) {
1809 InstanceState result = _state.remainder(rightOperand._state);
1810 if (result is IntState) {
1811 return new DartObjectImpl(typeProvider.intType, result);
1812 } else if (result is DoubleState) {
1813 return new DartObjectImpl(typeProvider.doubleType, result);
1814 } else if (result is NumState) {
1815 return new DartObjectImpl(typeProvider.numType, result);
1816 }
1817 // We should never get here.
1818 throw new IllegalStateException("remainder returned a ${result.runtimeType.t oString()}");
1819 }
1820
1821 /**
1822 * Return the result of invoking the '&lt;&lt;' operator on this object with t he given argument.
1823 *
1824 * @param typeProvider the type provider used to find known types
1825 * @param rightOperand the right-hand operand of the operation
1826 * @return the result of invoking the '&lt;&lt;' operator on this object with the given argument
1827 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1828 */
1829 DartObjectImpl shiftLeft(TypeProvider typeProvider, DartObjectImpl rightOperan d) => new DartObjectImpl(typeProvider.intType, _state.shiftLeft(rightOperand._st ate));
1830
1831 /**
1832 * Return the result of invoking the '&gt;&gt;' operator on this object with t he given argument.
1833 *
1834 * @param typeProvider the type provider used to find known types
1835 * @param rightOperand the right-hand operand of the operation
1836 * @return the result of invoking the '&gt;&gt;' operator on this object with the given argument
1837 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1838 */
1839 DartObjectImpl shiftRight(TypeProvider typeProvider, DartObjectImpl rightOpera nd) => new DartObjectImpl(typeProvider.intType, _state.shiftRight(rightOperand._ state));
1840
1841 /**
1842 * Return the result of invoking the '*' operator on this object with the give n argument.
1843 *
1844 * @param typeProvider the type provider used to find known types
1845 * @param rightOperand the right-hand operand of the operation
1846 * @return the result of invoking the '*' operator on this object with the giv en argument
1847 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
1848 */
1849 DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) {
1850 InstanceState result = _state.times(rightOperand._state);
1851 if (result is IntState) {
1852 return new DartObjectImpl(typeProvider.intType, result);
1853 } else if (result is DoubleState) {
1854 return new DartObjectImpl(typeProvider.doubleType, result);
1855 } else if (result is NumState) {
1856 return new DartObjectImpl(typeProvider.numType, result);
1857 }
1858 // We should never get here.
1859 throw new IllegalStateException("times returned a ${result.runtimeType.toStr ing()}");
1860 }
1861
1862 @override
1863 String toString() => "${type.displayName} (${_state.toString()})";
1864 }
1865
1866 /**
1867 * Instances of the class `DeclaredVariables` provide access to the values of va riables that
1868 * have been defined on the command line using the `-D` option.
1869 */
1870 class DeclaredVariables {
1871 /**
1872 * A table mapping the names of declared variables to their values.
1873 */
1874 HashMap<String, String> _declaredVariables = new HashMap<String, String>();
1875
1876 /**
1877 * Define a variable with the given name to have the given value.
1878 *
1879 * @param variableName the name of the variable being defined
1880 * @param value the value of the variable
1881 */
1882 void define(String variableName, String value) {
1883 _declaredVariables[variableName] = value;
1884 }
1885
1886 /**
1887 * Return the value of the variable with the given name interpreted as a boole an value. If the
1888 * variable is not defined (or [variableName] is null), a DartObject represent ing "unknown"
1889 * is returned. If the value can't be parsed as a boolean, a DartObject repres enting null is
1890 * returned.
1891 *
1892 * @param typeProvider the type provider used to find the type 'bool'
1893 * @param variableName the name of the variable whose value is to be returned
1894 */
1895 DartObject getBool(TypeProvider typeProvider, String variableName) {
1896 String value = _declaredVariables[variableName];
1897 if (value == null) {
1898 return new DartObjectImpl(typeProvider.boolType, BoolState.UNKNOWN_VALUE);
1899 }
1900 if (value == "true") {
1901 return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
1902 } else if (value == "false") {
1903 return new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE);
1904 }
1905 return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
1906 }
1907
1908 /**
1909 * Return the value of the variable with the given name interpreted as an inte ger value. If the
1910 * variable is not defined (or [variableName] is null), a DartObject represent ing "unknown"
1911 * is returned. If the value can't be parsed as an integer, a DartObject repre senting null is
1912 * returned.
1913 *
1914 * @param typeProvider the type provider used to find the type 'int'
1915 * @param variableName the name of the variable whose value is to be returned
1916 */
1917 DartObject getInt(TypeProvider typeProvider, String variableName) {
1918 String value = _declaredVariables[variableName];
1919 if (value == null) {
1920 return new DartObjectImpl(typeProvider.intType, IntState.UNKNOWN_VALUE);
1921 }
1922 int bigInteger;
1923 try {
1924 bigInteger = int.parse(value);
1925 } on FormatException catch (exception) {
1926 return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
1927 }
1928 return new DartObjectImpl(typeProvider.intType, new IntState(bigInteger));
1929 }
1930
1931 /**
1932 * Return the value of the variable with the given name interpreted as a Strin g value, or
1933 * `null` if the variable is not defined. Return the value of the variable wit h the given
1934 * name interpreted as a String value. If the variable is not defined (or [var iableName] is
1935 * null), a DartObject representing "unknown" is returned.
1936 *
1937 * @param typeProvider the type provider used to find the type 'String'
1938 * @param variableName the name of the variable whose value is to be returned
1939 */
1940 DartObject getString(TypeProvider typeProvider, String variableName) {
1941 String value = _declaredVariables[variableName];
1942 if (value == null) {
1943 return new DartObjectImpl(typeProvider.intType, IntState.UNKNOWN_VALUE);
1944 }
1945 return new DartObjectImpl(typeProvider.stringType, new StringState(value));
1946 }
1947 }
1948
1949 /**
1950 * Instances of the class `DoubleState` represent the state of an object represe nting a
1951 * double.
1952 */
1953 class DoubleState extends NumState {
1954 /**
1955 * The value of this instance.
1956 */
1957 final double value;
1958
1959 /**
1960 * A state that can be used to represent a double whose value is not known.
1961 */
1962 static DoubleState UNKNOWN_VALUE = new DoubleState(null);
1963
1964 /**
1965 * Initialize a newly created state to represent a double with the given value .
1966 *
1967 * @param value the value of this instance
1968 */
1969 DoubleState(this.value);
1970
1971 @override
1972 NumState add(InstanceState rightOperand) {
1973 assertNumOrNull(rightOperand);
1974 if (value == null) {
1975 return UNKNOWN_VALUE;
1976 }
1977 if (rightOperand is IntState) {
1978 int rightValue = rightOperand.value;
1979 if (rightValue == null) {
1980 return UNKNOWN_VALUE;
1981 }
1982 return new DoubleState(value + rightValue.toDouble());
1983 } else if (rightOperand is DoubleState) {
1984 double rightValue = rightOperand.value;
1985 if (rightValue == null) {
1986 return UNKNOWN_VALUE;
1987 }
1988 return new DoubleState(value + rightValue);
1989 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1990 return UNKNOWN_VALUE;
1991 }
1992 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
1993 }
1994
1995 @override
1996 StringState convertToString() {
1997 if (value == null) {
1998 return StringState.UNKNOWN_VALUE;
1999 }
2000 return new StringState(value.toString());
2001 }
2002
2003 @override
2004 NumState divide(InstanceState rightOperand) {
2005 assertNumOrNull(rightOperand);
2006 if (value == null) {
2007 return UNKNOWN_VALUE;
2008 }
2009 if (rightOperand is IntState) {
2010 int rightValue = rightOperand.value;
2011 if (rightValue == null) {
2012 return UNKNOWN_VALUE;
2013 }
2014 return new DoubleState(value / rightValue.toDouble());
2015 } else if (rightOperand is DoubleState) {
2016 double rightValue = rightOperand.value;
2017 if (rightValue == null) {
2018 return UNKNOWN_VALUE;
2019 }
2020 return new DoubleState(value / rightValue);
2021 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2022 return UNKNOWN_VALUE;
2023 }
2024 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2025 }
2026
2027 @override
2028 BoolState equalEqual(InstanceState rightOperand) {
2029 assertBoolNumStringOrNull(rightOperand);
2030 if (value == null) {
2031 return BoolState.UNKNOWN_VALUE;
2032 }
2033 if (rightOperand is DoubleState) {
2034 double rightValue = rightOperand.value;
2035 if (rightValue == null) {
2036 return BoolState.UNKNOWN_VALUE;
2037 }
2038 return BoolState.from(value == rightValue);
2039 } else if (rightOperand is IntState) {
2040 int rightValue = rightOperand.value;
2041 if (rightValue == null) {
2042 return BoolState.UNKNOWN_VALUE;
2043 }
2044 return BoolState.from(value == rightValue.toDouble());
2045 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2046 return BoolState.UNKNOWN_VALUE;
2047 }
2048 return BoolState.FALSE_STATE;
2049 }
2050
2051 @override
2052 bool operator ==(Object object) => object is DoubleState && (value == object.v alue);
2053
2054 @override
2055 String get typeName => "double";
2056
2057 @override
2058 BoolState greaterThan(InstanceState rightOperand) {
2059 assertNumOrNull(rightOperand);
2060 if (value == null) {
2061 return BoolState.UNKNOWN_VALUE;
2062 }
2063 if (rightOperand is IntState) {
2064 int rightValue = rightOperand.value;
2065 if (rightValue == null) {
2066 return BoolState.UNKNOWN_VALUE;
2067 }
2068 return BoolState.from(value > rightValue.toDouble());
2069 } else if (rightOperand is DoubleState) {
2070 double rightValue = rightOperand.value;
2071 if (rightValue == null) {
2072 return BoolState.UNKNOWN_VALUE;
2073 }
2074 return BoolState.from(value > rightValue);
2075 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2076 return BoolState.UNKNOWN_VALUE;
2077 }
2078 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2079 }
2080
2081 @override
2082 BoolState greaterThanOrEqual(InstanceState rightOperand) {
2083 assertNumOrNull(rightOperand);
2084 if (value == null) {
2085 return BoolState.UNKNOWN_VALUE;
2086 }
2087 if (rightOperand is IntState) {
2088 int rightValue = rightOperand.value;
2089 if (rightValue == null) {
2090 return BoolState.UNKNOWN_VALUE;
2091 }
2092 return BoolState.from(value >= rightValue.toDouble());
2093 } else if (rightOperand is DoubleState) {
2094 double rightValue = rightOperand.value;
2095 if (rightValue == null) {
2096 return BoolState.UNKNOWN_VALUE;
2097 }
2098 return BoolState.from(value >= rightValue);
2099 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2100 return BoolState.UNKNOWN_VALUE;
2101 }
2102 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2103 }
2104
2105 @override
2106 bool get hasExactValue => true;
2107
2108 @override
2109 int get hashCode => value == null ? 0 : value.hashCode;
2110
2111 @override
2112 IntState integerDivide(InstanceState rightOperand) {
2113 assertNumOrNull(rightOperand);
2114 if (value == null) {
2115 return IntState.UNKNOWN_VALUE;
2116 }
2117 if (rightOperand is IntState) {
2118 int rightValue = rightOperand.value;
2119 if (rightValue == null) {
2120 return IntState.UNKNOWN_VALUE;
2121 }
2122 double result = value / rightValue.toDouble();
2123 return new IntState(result.toInt());
2124 } else if (rightOperand is DoubleState) {
2125 double rightValue = rightOperand.value;
2126 if (rightValue == null) {
2127 return IntState.UNKNOWN_VALUE;
2128 }
2129 double result = value / rightValue;
2130 return new IntState(result.toInt());
2131 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2132 return IntState.UNKNOWN_VALUE;
2133 }
2134 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2135 }
2136
2137 @override
2138 bool get isBoolNumStringOrNull => true;
2139
2140 @override
2141 bool get isUnknown => value == null;
2142
2143 @override
2144 BoolState lessThan(InstanceState rightOperand) {
2145 assertNumOrNull(rightOperand);
2146 if (value == null) {
2147 return BoolState.UNKNOWN_VALUE;
2148 }
2149 if (rightOperand is IntState) {
2150 int rightValue = rightOperand.value;
2151 if (rightValue == null) {
2152 return BoolState.UNKNOWN_VALUE;
2153 }
2154 return BoolState.from(value < rightValue.toDouble());
2155 } else if (rightOperand is DoubleState) {
2156 double rightValue = rightOperand.value;
2157 if (rightValue == null) {
2158 return BoolState.UNKNOWN_VALUE;
2159 }
2160 return BoolState.from(value < rightValue);
2161 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2162 return BoolState.UNKNOWN_VALUE;
2163 }
2164 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2165 }
2166
2167 @override
2168 BoolState lessThanOrEqual(InstanceState rightOperand) {
2169 assertNumOrNull(rightOperand);
2170 if (value == null) {
2171 return BoolState.UNKNOWN_VALUE;
2172 }
2173 if (rightOperand is IntState) {
2174 int rightValue = rightOperand.value;
2175 if (rightValue == null) {
2176 return BoolState.UNKNOWN_VALUE;
2177 }
2178 return BoolState.from(value <= rightValue.toDouble());
2179 } else if (rightOperand is DoubleState) {
2180 double rightValue = rightOperand.value;
2181 if (rightValue == null) {
2182 return BoolState.UNKNOWN_VALUE;
2183 }
2184 return BoolState.from(value <= rightValue);
2185 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2186 return BoolState.UNKNOWN_VALUE;
2187 }
2188 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2189 }
2190
2191 @override
2192 NumState minus(InstanceState rightOperand) {
2193 assertNumOrNull(rightOperand);
2194 if (value == null) {
2195 return UNKNOWN_VALUE;
2196 }
2197 if (rightOperand is IntState) {
2198 int rightValue = rightOperand.value;
2199 if (rightValue == null) {
2200 return UNKNOWN_VALUE;
2201 }
2202 return new DoubleState(value - rightValue.toDouble());
2203 } else if (rightOperand is DoubleState) {
2204 double rightValue = rightOperand.value;
2205 if (rightValue == null) {
2206 return UNKNOWN_VALUE;
2207 }
2208 return new DoubleState(value - rightValue);
2209 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2210 return UNKNOWN_VALUE;
2211 }
2212 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2213 }
2214
2215 @override
2216 NumState negated() {
2217 if (value == null) {
2218 return UNKNOWN_VALUE;
2219 }
2220 return new DoubleState(-(value));
2221 }
2222
2223 @override
2224 NumState remainder(InstanceState rightOperand) {
2225 assertNumOrNull(rightOperand);
2226 if (value == null) {
2227 return UNKNOWN_VALUE;
2228 }
2229 if (rightOperand is IntState) {
2230 int rightValue = rightOperand.value;
2231 if (rightValue == null) {
2232 return UNKNOWN_VALUE;
2233 }
2234 return new DoubleState(value % rightValue.toDouble());
2235 } else if (rightOperand is DoubleState) {
2236 double rightValue = rightOperand.value;
2237 if (rightValue == null) {
2238 return UNKNOWN_VALUE;
2239 }
2240 return new DoubleState(value % rightValue);
2241 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2242 return UNKNOWN_VALUE;
2243 }
2244 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2245 }
2246
2247 @override
2248 NumState times(InstanceState rightOperand) {
2249 assertNumOrNull(rightOperand);
2250 if (value == null) {
2251 return UNKNOWN_VALUE;
2252 }
2253 if (rightOperand is IntState) {
2254 int rightValue = rightOperand.value;
2255 if (rightValue == null) {
2256 return UNKNOWN_VALUE;
2257 }
2258 return new DoubleState(value * rightValue.toDouble());
2259 } else if (rightOperand is DoubleState) {
2260 double rightValue = rightOperand.value;
2261 if (rightValue == null) {
2262 return UNKNOWN_VALUE;
2263 }
2264 return new DoubleState(value * rightValue);
2265 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2266 return UNKNOWN_VALUE;
2267 }
2268 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
2269 }
2270
2271 @override
2272 String toString() => value == null ? "-unknown-" : value.toString();
2273 }
2274
2275 /**
2276 * Instances of the class `DynamicState` represent the state of an object repres enting a Dart
2277 * object for which there is no type information.
2278 */
2279 class DynamicState extends InstanceState {
2280 /**
2281 * The unique instance of this class.
2282 */
2283 static DynamicState DYNAMIC_STATE = new DynamicState();
2284
2285 @override
2286 NumState add(InstanceState rightOperand) {
2287 assertNumOrNull(rightOperand);
2288 return _unknownNum(rightOperand);
2289 }
2290
2291 @override
2292 IntState bitAnd(InstanceState rightOperand) {
2293 assertIntOrNull(rightOperand);
2294 return IntState.UNKNOWN_VALUE;
2295 }
2296
2297 @override
2298 IntState bitNot() => IntState.UNKNOWN_VALUE;
2299
2300 @override
2301 IntState bitOr(InstanceState rightOperand) {
2302 assertIntOrNull(rightOperand);
2303 return IntState.UNKNOWN_VALUE;
2304 }
2305
2306 @override
2307 IntState bitXor(InstanceState rightOperand) {
2308 assertIntOrNull(rightOperand);
2309 return IntState.UNKNOWN_VALUE;
2310 }
2311
2312 @override
2313 StringState concatenate(InstanceState rightOperand) {
2314 assertString(rightOperand);
2315 return StringState.UNKNOWN_VALUE;
2316 }
2317
2318 @override
2319 BoolState convertToBool() => BoolState.UNKNOWN_VALUE;
2320
2321 @override
2322 StringState convertToString() => StringState.UNKNOWN_VALUE;
2323
2324 @override
2325 NumState divide(InstanceState rightOperand) {
2326 assertNumOrNull(rightOperand);
2327 return _unknownNum(rightOperand);
2328 }
2329
2330 @override
2331 BoolState equalEqual(InstanceState rightOperand) {
2332 assertBoolNumStringOrNull(rightOperand);
2333 return BoolState.UNKNOWN_VALUE;
2334 }
2335
2336 @override
2337 String get typeName => "dynamic";
2338
2339 @override
2340 BoolState greaterThan(InstanceState rightOperand) {
2341 assertNumOrNull(rightOperand);
2342 return BoolState.UNKNOWN_VALUE;
2343 }
2344
2345 @override
2346 BoolState greaterThanOrEqual(InstanceState rightOperand) {
2347 assertNumOrNull(rightOperand);
2348 return BoolState.UNKNOWN_VALUE;
2349 }
2350
2351 @override
2352 IntState integerDivide(InstanceState rightOperand) {
2353 assertNumOrNull(rightOperand);
2354 return IntState.UNKNOWN_VALUE;
2355 }
2356
2357 @override
2358 bool get isBool => true;
2359
2360 @override
2361 bool get isBoolNumStringOrNull => true;
2362
2363 @override
2364 BoolState lessThan(InstanceState rightOperand) {
2365 assertNumOrNull(rightOperand);
2366 return BoolState.UNKNOWN_VALUE;
2367 }
2368
2369 @override
2370 BoolState lessThanOrEqual(InstanceState rightOperand) {
2371 assertNumOrNull(rightOperand);
2372 return BoolState.UNKNOWN_VALUE;
2373 }
2374
2375 @override
2376 BoolState logicalAnd(InstanceState rightOperand) {
2377 assertBool(rightOperand);
2378 return BoolState.UNKNOWN_VALUE;
2379 }
2380
2381 @override
2382 BoolState logicalNot() => BoolState.UNKNOWN_VALUE;
2383
2384 @override
2385 BoolState logicalOr(InstanceState rightOperand) {
2386 assertBool(rightOperand);
2387 return rightOperand.convertToBool();
2388 }
2389
2390 @override
2391 NumState minus(InstanceState rightOperand) {
2392 assertNumOrNull(rightOperand);
2393 return _unknownNum(rightOperand);
2394 }
2395
2396 @override
2397 NumState negated() => NumState.UNKNOWN_VALUE;
2398
2399 @override
2400 NumState remainder(InstanceState rightOperand) {
2401 assertNumOrNull(rightOperand);
2402 return _unknownNum(rightOperand);
2403 }
2404
2405 @override
2406 IntState shiftLeft(InstanceState rightOperand) {
2407 assertIntOrNull(rightOperand);
2408 return IntState.UNKNOWN_VALUE;
2409 }
2410
2411 @override
2412 IntState shiftRight(InstanceState rightOperand) {
2413 assertIntOrNull(rightOperand);
2414 return IntState.UNKNOWN_VALUE;
2415 }
2416
2417 @override
2418 NumState times(InstanceState rightOperand) {
2419 assertNumOrNull(rightOperand);
2420 return _unknownNum(rightOperand);
2421 }
2422
2423 /**
2424 * Return an object representing an unknown numeric value whose type is based on the type of the
2425 * right-hand operand.
2426 *
2427 * @param rightOperand the operand whose type will determine the type of the r esult
2428 * @return an object representing an unknown numeric value
2429 */
2430 NumState _unknownNum(InstanceState rightOperand) {
2431 if (rightOperand is IntState) {
2432 return IntState.UNKNOWN_VALUE;
2433 } else if (rightOperand is DoubleState) {
2434 return DoubleState.UNKNOWN_VALUE;
2435 }
2436 return NumState.UNKNOWN_VALUE;
2437 }
2438 }
2439
2440 /**
2441 * Instances of the class `ErrorResult` represent the result of evaluating an ex pression that
2442 * is not a valid compile time constant.
2443 */
2444 class ErrorResult extends EvaluationResultImpl {
2445 /**
2446 * The errors that prevent the expression from being a valid compile time cons tant.
2447 */
2448 List<ErrorResult_ErrorData> _errors = new List<ErrorResult_ErrorData>();
2449
2450 /**
2451 * Initialize a newly created result representing the error with the given cod e reported against
2452 * the given node.
2453 *
2454 * @param node the node against which the error should be reported
2455 * @param errorCode the error code for the error to be generated
2456 */
2457 ErrorResult.con1(AstNode node, ErrorCode errorCode) {
2458 _errors.add(new ErrorResult_ErrorData(node, errorCode));
2459 }
2460
2461 /**
2462 * Initialize a newly created result to represent the union of the errors in t he given result
2463 * objects.
2464 *
2465 * @param firstResult the first set of results being merged
2466 * @param secondResult the second set of results being merged
2467 */
2468 ErrorResult.con2(ErrorResult firstResult, ErrorResult secondResult) {
2469 _errors.addAll(firstResult._errors);
2470 _errors.addAll(secondResult._errors);
2471 }
2472
2473 @override
2474 EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, Eva luationResultImpl rightOperand) => rightOperand.addToError(node, this);
2475
2476 @override
2477 EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode node) => this;
2478
2479 @override
2480 EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitAndError(node, this);
2481
2482 @override
2483 EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node) => thi s;
2484
2485 @override
2486 EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand) => rightOperand.bitOrError(node, this);
2487
2488 @override
2489 EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitXorError(node, this);
2490
2491 @override
2492 EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, E valuationResultImpl rightOperand) => rightOperand.concatenateError(node, this);
2493
2494 @override
2495 EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.divideError(node, this);
2496
2497 @override
2498 EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, Ev aluationResultImpl rightOperand) => rightOperand.equalEqualError(node, this);
2499
2500 @override
2501 bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) => fa lse;
2502
2503 List<ErrorResult_ErrorData> get errorData => _errors;
2504
2505 @override
2506 EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression n ode, EvaluationResultImpl rightOperand) => rightOperand.greaterThanError(node, t his);
2507
2508 @override
2509 EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpre ssion node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanOrEqua lError(node, this);
2510
2511 @override
2512 EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.integerDivideError(nod e, this);
2513
2514 @override
2515 EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpre ssion node, ValidResult leftOperand) => this;
2516
2517 @override
2518 EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node , EvaluationResultImpl rightOperand) => rightOperand.lessThanError(node, this);
2519
2520 @override
2521 EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpressi on node, EvaluationResultImpl rightOperand) => rightOperand.lessThanOrEqualError (node, this);
2522
2523 @override
2524 EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression no de, EvaluationResultImpl rightOperand) => rightOperand.logicalAndError(node, thi s);
2525
2526 @override
2527 EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node) => this;
2528
2529 @override
2530 EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand) => rightOperand.logicalOrError(node, this) ;
2531
2532 @override
2533 EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand) => rightOperand.minusError(node, this);
2534
2535 @override
2536 EvaluationResultImpl negated(TypeProvider typeProvider, Expression node) => th is;
2537
2538 @override
2539 EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node , EvaluationResultImpl rightOperand) => rightOperand.notEqualError(node, this);
2540
2541 @override
2542 EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node) => this;
2543
2544 @override
2545 EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand) => rightOperand.remainderError(node, this) ;
2546
2547 @override
2548 EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand) => rightOperand.shiftLeftError(node, this) ;
2549
2550 @override
2551 EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression no de, EvaluationResultImpl rightOperand) => rightOperand.shiftRightError(node, thi s);
2552
2553 @override
2554 EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand) => rightOperand.timesError(node, this);
2555
2556 @override
2557 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand ) => new ErrorResult.con2(this, leftOperand);
2558
2559 @override
2560 EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand) => this;
2561
2562 @override
2563 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan d) => new ErrorResult.con2(this, leftOperand);
2564
2565 @override
2566 EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand) => this;
2567
2568 @override
2569 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand ) => new ErrorResult.con2(this, leftOperand);
2570
2571 @override
2572 EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand) => this;
2573
2574 @override
2575 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan d) => new ErrorResult.con2(this, leftOperand);
2576
2577 @override
2578 EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand) => this;
2579
2580 @override
2581 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand ) => new ErrorResult.con2(this, leftOperand);
2582
2583 @override
2584 EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression no de, ValidResult leftOperand) => this;
2585
2586 @override
2587 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan d) => new ErrorResult.con2(this, leftOperand);
2588
2589 @override
2590 EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand) => this;
2591
2592 @override
2593 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand) => new ErrorResult.con2(this, leftOperand);
2594
2595 @override
2596 EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression nod e, ValidResult leftOperand) => this;
2597
2598 @override
2599 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO perand) => new ErrorResult.con2(this, leftOperand);
2600
2601 @override
2602 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul t leftOperand) => new ErrorResult.con2(this, leftOperand);
2603
2604 @override
2605 EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, Binary Expression node, ValidResult leftOperand) => this;
2606
2607 @override
2608 EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpress ion node, ValidResult leftOperand) => this;
2609
2610 @override
2611 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef tOperand) => new ErrorResult.con2(this, leftOperand);
2612
2613 @override
2614 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper and) => new ErrorResult.con2(this, leftOperand);
2615
2616 @override
2617 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l eftOperand) => new ErrorResult.con2(this, leftOperand);
2618
2619 @override
2620 EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExp ression node, ValidResult leftOperand) => this;
2621
2622 @override
2623 EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
2624
2625 @override
2626 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp erand) => new ErrorResult.con2(this, leftOperand);
2627
2628 @override
2629 EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpressi on node, ValidResult leftOperand) => this;
2630
2631 @override
2632 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe rand) => new ErrorResult.con2(this, leftOperand);
2633
2634 @override
2635 EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand) => this;
2636
2637 @override
2638 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand ) => new ErrorResult.con2(this, leftOperand);
2639
2640 @override
2641 EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand) => this;
2642
2643 @override
2644 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper and) => new ErrorResult.con2(this, leftOperand);
2645
2646 @override
2647 EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) => this;
2648
2649 @override
2650 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe rand) => new ErrorResult.con2(this, leftOperand);
2651
2652 @override
2653 EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand) => this;
2654
2655 @override
2656 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe rand) => new ErrorResult.con2(this, leftOperand);
2657
2658 @override
2659 EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand) => this;
2660
2661 @override
2662 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp erand) => new ErrorResult.con2(this, leftOperand);
2663
2664 @override
2665 EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpressi on node, ValidResult leftOperand) => this;
2666
2667 @override
2668 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand ) => new ErrorResult.con2(this, leftOperand);
2669
2670 @override
2671 EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand) => this;
2672 }
2673
2674 class ErrorResult_ErrorData {
2675 /**
2676 * The node against which the error should be reported.
2677 */
2678 final AstNode node;
2679
2680 /**
2681 * The error code for the error to be generated.
2682 */
2683 final ErrorCode errorCode;
2684
2685 /**
2686 * Initialize a newly created data holder to represent the error with the give n code reported
2687 * against the given node.
2688 *
2689 * @param node the node against which the error should be reported
2690 * @param errorCode the error code for the error to be generated
2691 */
2692 ErrorResult_ErrorData(this.node, this.errorCode);
2693 }
2694
2695 /**
2696 * Instances of the class `EvaluationException` represent a run-time exception t hat would be
2697 * thrown during the evaluation of Dart code.
2698 */
2699 class EvaluationException extends JavaException {
2700 /**
2701 * The error code associated with the exception.
2702 */
2703 final ErrorCode errorCode;
2704
2705 /**
2706 * Initialize a newly created exception to have the given error code.
2707 *
2708 * @param errorCode the error code associated with the exception
2709 */
2710 EvaluationException(this.errorCode);
2711 }
2712
2713 /**
2714 * Instances of the class `EvaluationResult` represent the result of attempting to evaluate an
2715 * expression.
2716 */
2717 class EvaluationResult {
2718 /**
2719 * Return an evaluation result representing the result of evaluating an expres sion that is not a
2720 * compile-time constant because of the given errors.
2721 *
2722 * @param errors the errors that should be reported for the expression(s) that were evaluated
2723 * @return the result of evaluating an expression that is not a compile-time c onstant
2724 */
2725 static EvaluationResult forErrors(List<AnalysisError> errors) => new Evaluatio nResult(null, errors);
2726
2727 /**
2728 * Return an evaluation result representing the result of evaluating an expres sion that is a
2729 * compile-time constant that evaluates to the given value.
2730 *
2731 * @param value the value of the expression
2732 * @return the result of evaluating an expression that is a compile-time const ant
2733 */
2734 static EvaluationResult forValue(DartObject value) => new EvaluationResult(val ue, null);
2735
2736 /**
2737 * The value of the expression.
2738 */
2739 final DartObject value;
2740
2741 /**
2742 * The errors that should be reported for the expression(s) that were evaluate d.
2743 */
2744 final List<AnalysisError> _errors;
2745
2746 /**
2747 * Initialize a newly created result object with the given state. Clients shou ld use one of the
2748 * factory methods: [forErrors] and [forValue].
2749 *
2750 * @param value the value of the expression
2751 * @param errors the errors that should be reported for the expression(s) that were evaluated
2752 */
2753 EvaluationResult(this.value, this._errors);
2754
2755 /**
2756 * Return an array containing the errors that should be reported for the expre ssion(s) that were
2757 * evaluated. If there are no such errors, the array will be empty. The array can be empty even if
2758 * the expression is not a valid compile time constant if the errors would hav e been reported by
2759 * other parts of the analysis engine.
2760 */
2761 List<AnalysisError> get errors => _errors == null ? AnalysisError.NO_ERRORS : _errors;
2762
2763 /**
2764 * Return `true` if the expression is a compile-time constant expression that would not
2765 * throw an exception when evaluated.
2766 *
2767 * @return `true` if the expression is a valid compile-time constant expressio n
2768 */
2769 bool get isValid => _errors == null;
2770 }
2771
2772 /**
2773 * Instances of the class `InternalResult` represent the result of attempting to evaluate a
2774 * expression.
2775 */
2776 abstract class EvaluationResultImpl {
2777 EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, Eva luationResultImpl rightOperand);
2778
2779 /**
2780 * Return the result of applying boolean conversion to this result.
2781 *
2782 * @param typeProvider the type provider used to access known types
2783 * @param node the node against which errors should be reported
2784 * @return the result of applying boolean conversion to the given value
2785 */
2786 EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode node);
2787
2788 EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
2789
2790 EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node);
2791
2792 EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand);
2793
2794 EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
2795
2796 EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, E valuationResultImpl rightOperand);
2797
2798 EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
2799
2800 EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, Ev aluationResultImpl rightOperand);
2801
2802 bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result);
2803
2804 EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression n ode, EvaluationResultImpl rightOperand);
2805
2806 EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpre ssion node, EvaluationResultImpl rightOperand);
2807
2808 EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand);
2809
2810 EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node , EvaluationResultImpl rightOperand);
2811
2812 EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpressi on node, EvaluationResultImpl rightOperand);
2813
2814 EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression no de, EvaluationResultImpl rightOperand);
2815
2816 EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node);
2817
2818 EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand);
2819
2820 EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand);
2821
2822 EvaluationResultImpl negated(TypeProvider typeProvider, Expression node);
2823
2824 EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node , EvaluationResultImpl rightOperand);
2825
2826 EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node);
2827
2828 EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand);
2829
2830 EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand);
2831
2832 EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression no de, EvaluationResultImpl rightOperand);
2833
2834 EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand);
2835
2836 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand );
2837
2838 EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand);
2839
2840 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan d);
2841
2842 EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand);
2843
2844 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand );
2845
2846 EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand);
2847
2848 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan d);
2849
2850 EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand);
2851
2852 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand );
2853
2854 EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression no de, ValidResult leftOperand);
2855
2856 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan d);
2857
2858 EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand);
2859
2860 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand) ;
2861
2862 EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression nod e, ValidResult leftOperand);
2863
2864 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO perand);
2865
2866 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul t leftOperand);
2867
2868 EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, Binary Expression node, ValidResult leftOperand);
2869
2870 EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpress ion node, ValidResult leftOperand);
2871
2872 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef tOperand);
2873
2874 EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpre ssion node, ValidResult leftOperand);
2875
2876 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper and);
2877
2878 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l eftOperand);
2879
2880 EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExp ression node, ValidResult leftOperand);
2881
2882 EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
2883
2884 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp erand);
2885
2886 EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpressi on node, ValidResult leftOperand);
2887
2888 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe rand);
2889
2890 EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand);
2891
2892 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand );
2893
2894 EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand);
2895
2896 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper and);
2897
2898 EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand);
2899
2900 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe rand);
2901
2902 EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand);
2903
2904 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe rand);
2905
2906 EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand);
2907
2908 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp erand);
2909
2910 EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpressi on node, ValidResult leftOperand);
2911
2912 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand );
2913
2914 EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand);
2915 }
2916
2917 /**
2918 * Instances of the class `FunctionState` represent the state of an object repre senting a
2919 * function.
2920 */
2921 class FunctionState extends InstanceState {
2922 /**
2923 * The element representing the function being modeled.
2924 */
2925 final ExecutableElement _element;
2926
2927 /**
2928 * Initialize a newly created state to represent the given function.
2929 *
2930 * @param element the element representing the function being modeled
2931 */
2932 FunctionState(this._element);
2933
2934 @override
2935 StringState convertToString() {
2936 if (_element == null) {
2937 return StringState.UNKNOWN_VALUE;
2938 }
2939 return new StringState(_element.name);
2940 }
2941
2942 @override
2943 bool operator ==(Object object) => object is FunctionState && (_element == obj ect._element);
2944
2945 @override
2946 BoolState equalEqual(InstanceState rightOperand) {
2947 if (_element == null) {
2948 return BoolState.UNKNOWN_VALUE;
2949 }
2950 if (rightOperand is FunctionState) {
2951 ExecutableElement rightElement = rightOperand._element;
2952 if (rightElement == null) {
2953 return BoolState.UNKNOWN_VALUE;
2954 }
2955 return BoolState.from(_element == rightElement);
2956 } else if (rightOperand is DynamicState) {
2957 return BoolState.UNKNOWN_VALUE;
2958 }
2959 return BoolState.FALSE_STATE;
2960 }
2961
2962 @override
2963 String get typeName => "Function";
2964
2965 @override
2966 int get hashCode => _element == null ? 0 : _element.hashCode;
2967
2968 @override
2969 String toString() => _element == null ? "-unknown-" : _element.name;
2970 }
2971
2972 /**
2973 * Instances of the class `GenericState` represent the state of an object repres enting a Dart
2974 * object for which there is no more specific state.
2975 */
2976 class GenericState extends InstanceState {
2977 /**
2978 * The values of the fields of this instance.
2979 */
2980 final HashMap<String, DartObjectImpl> _fieldMap;
2981
2982 /**
2983 * Pseudo-field that we use to represent fields in the superclass.
2984 */
2985 static String SUPERCLASS_FIELD = "(super)";
2986
2987 /**
2988 * A state that can be used to represent an object whose state is not known.
2989 */
2990 static GenericState UNKNOWN_VALUE = new GenericState(new HashMap<String, DartO bjectImpl>());
2991
2992 /**
2993 * Initialize a newly created state to represent a newly created object.
2994 *
2995 * @param fieldMap the values of the fields of this instance
2996 */
2997 GenericState(this._fieldMap);
2998
2999 @override
3000 StringState convertToString() => StringState.UNKNOWN_VALUE;
3001
3002 @override
3003 BoolState equalEqual(InstanceState rightOperand) {
3004 assertBoolNumStringOrNull(rightOperand);
3005 if (rightOperand is DynamicState) {
3006 return BoolState.UNKNOWN_VALUE;
3007 }
3008 return BoolState.from(this == rightOperand);
3009 }
3010
3011 @override
3012 bool operator ==(Object object) {
3013 if (object is! GenericState) {
3014 return false;
3015 }
3016 GenericState state = object as GenericState;
3017 HashSet<String> otherFields = new HashSet<String>.from(state._fieldMap.keys. toSet());
3018 for (String fieldName in _fieldMap.keys.toSet()) {
3019 if (_fieldMap[fieldName] != state._fieldMap[fieldName]) {
3020 return false;
3021 }
3022 otherFields.remove(fieldName);
3023 }
3024 for (String fieldName in otherFields) {
3025 if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
3026 return false;
3027 }
3028 }
3029 return true;
3030 }
3031
3032 @override
3033 HashMap<String, DartObjectImpl> get fields => _fieldMap;
3034
3035 @override
3036 String get typeName => "user defined type";
3037
3038 @override
3039 int get hashCode {
3040 int hashCode = 0;
3041 for (DartObjectImpl value in _fieldMap.values) {
3042 hashCode += value.hashCode;
3043 }
3044 return hashCode;
3045 }
3046
3047 @override
3048 bool get isUnknown => identical(this, UNKNOWN_VALUE);
3049 }
3050
3051 /**
3052 * The class `InstanceState` defines the behavior of objects representing the st ate of a Dart
3053 * object.
3054 */
3055 abstract class InstanceState {
3056 /**
3057 * Return the result of invoking the '+' operator on this object with the give n argument.
3058 *
3059 * @param rightOperand the right-hand operand of the operation
3060 * @return the result of invoking the '+' operator on this object with the giv en argument
3061 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3062 */
3063 NumState add(InstanceState rightOperand) {
3064 assertNumOrNull(this);
3065 assertNumOrNull(rightOperand);
3066 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3067 }
3068
3069 /**
3070 * Return the result of invoking the '&' operator on this object with the give n argument.
3071 *
3072 * @param rightOperand the right-hand operand of the operation
3073 * @return the result of invoking the '&' operator on this object with the giv en argument
3074 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3075 */
3076 IntState bitAnd(InstanceState rightOperand) {
3077 assertIntOrNull(this);
3078 assertIntOrNull(rightOperand);
3079 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3080 }
3081
3082 /**
3083 * Return the result of invoking the '~' operator on this object.
3084 *
3085 * @return the result of invoking the '~' operator on this object
3086 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3087 */
3088 IntState bitNot() {
3089 assertIntOrNull(this);
3090 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3091 }
3092
3093 /**
3094 * Return the result of invoking the '|' operator on this object with the give n argument.
3095 *
3096 * @param rightOperand the right-hand operand of the operation
3097 * @return the result of invoking the '|' operator on this object with the giv en argument
3098 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3099 */
3100 IntState bitOr(InstanceState rightOperand) {
3101 assertIntOrNull(this);
3102 assertIntOrNull(rightOperand);
3103 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3104 }
3105
3106 /**
3107 * Return the result of invoking the '^' operator on this object with the give n argument.
3108 *
3109 * @param rightOperand the right-hand operand of the operation
3110 * @return the result of invoking the '^' operator on this object with the giv en argument
3111 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3112 */
3113 IntState bitXor(InstanceState rightOperand) {
3114 assertIntOrNull(this);
3115 assertIntOrNull(rightOperand);
3116 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3117 }
3118
3119 /**
3120 * Return the result of invoking the ' ' operator on this object with the give n argument.
3121 *
3122 * @param rightOperand the right-hand operand of the operation
3123 * @return the result of invoking the ' ' operator on this object with the giv en argument
3124 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3125 */
3126 StringState concatenate(InstanceState rightOperand) {
3127 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3128 }
3129
3130 /**
3131 * Return the result of applying boolean conversion to this object.
3132 *
3133 * @param typeProvider the type provider used to find known types
3134 * @return the result of applying boolean conversion to this object
3135 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3136 */
3137 BoolState convertToBool() => BoolState.FALSE_STATE;
3138
3139 /**
3140 * Return the result of converting this object to a String.
3141 *
3142 * @return the result of converting this object to a String
3143 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3144 */
3145 StringState convertToString();
3146
3147 /**
3148 * Return the result of invoking the '/' operator on this object with the give n argument.
3149 *
3150 * @param rightOperand the right-hand operand of the operation
3151 * @return the result of invoking the '/' operator on this object with the giv en argument
3152 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3153 */
3154 NumState divide(InstanceState rightOperand) {
3155 assertNumOrNull(this);
3156 assertNumOrNull(rightOperand);
3157 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3158 }
3159
3160 /**
3161 * Return the result of invoking the '==' operator on this object with the giv en argument.
3162 *
3163 * @param rightOperand the right-hand operand of the operation
3164 * @return the result of invoking the '==' operator on this object with the gi ven argument
3165 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3166 */
3167 BoolState equalEqual(InstanceState rightOperand);
3168
3169 /**
3170 * If this represents a generic dart object, return a map from its fieldnames to their values.
3171 * Otherwise return null.
3172 */
3173 HashMap<String, DartObjectImpl> get fields => null;
3174
3175 /**
3176 * Return the name of the type of this value.
3177 *
3178 * @return the name of the type of this value
3179 */
3180 String get typeName;
3181
3182 /**
3183 * Return this object's value if it can be represented exactly, or `null` if e ither the
3184 * value cannot be represented exactly or if the value is `null`. Clients shou ld use
3185 * [hasExactValue] to distinguish between these two cases.
3186 *
3187 * @return this object's value
3188 */
3189 Object get value => null;
3190
3191 /**
3192 * Return the result of invoking the '&gt;' operator on this object with the g iven argument.
3193 *
3194 * @param rightOperand the right-hand operand of the operation
3195 * @return the result of invoking the '&gt;' operator on this object with the given argument
3196 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3197 */
3198 BoolState greaterThan(InstanceState rightOperand) {
3199 assertNumOrNull(this);
3200 assertNumOrNull(rightOperand);
3201 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3202 }
3203
3204 /**
3205 * Return the result of invoking the '&gt;=' operator on this object with the given argument.
3206 *
3207 * @param rightOperand the right-hand operand of the operation
3208 * @return the result of invoking the '&gt;=' operator on this object with the given argument
3209 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3210 */
3211 BoolState greaterThanOrEqual(InstanceState rightOperand) {
3212 assertNumOrNull(this);
3213 assertNumOrNull(rightOperand);
3214 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3215 }
3216
3217 /**
3218 * Return `true` if this object's value can be represented exactly.
3219 *
3220 * @return `true` if this object's value can be represented exactly
3221 */
3222 bool get hasExactValue => false;
3223
3224 /**
3225 * Return the result of invoking the '~/' operator on this object with the giv en argument.
3226 *
3227 * @param rightOperand the right-hand operand of the operation
3228 * @return the result of invoking the '~/' operator on this object with the gi ven argument
3229 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3230 */
3231 IntState integerDivide(InstanceState rightOperand) {
3232 assertNumOrNull(this);
3233 assertNumOrNull(rightOperand);
3234 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3235 }
3236
3237 /**
3238 * Return `true` if this object represents an object whose type is 'bool'.
3239 *
3240 * @return `true` if this object represents a boolean value
3241 */
3242 bool get isBool => false;
3243
3244 /**
3245 * Return `true` if this object represents an object whose type is either 'boo l', 'num',
3246 * 'String', or 'Null'.
3247 *
3248 * @return `true` if this object represents either a boolean, numeric, string or null value
3249 */
3250 bool get isBoolNumStringOrNull => false;
3251
3252 /**
3253 * Return true if this object represents an unknown value.
3254 */
3255 bool get isUnknown => false;
3256
3257 /**
3258 * Return the result of invoking the '&lt;' operator on this object with the g iven argument.
3259 *
3260 * @param rightOperand the right-hand operand of the operation
3261 * @return the result of invoking the '&lt;' operator on this object with the given argument
3262 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3263 */
3264 BoolState lessThan(InstanceState rightOperand) {
3265 assertNumOrNull(this);
3266 assertNumOrNull(rightOperand);
3267 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3268 }
3269
3270 /**
3271 * Return the result of invoking the '&lt;=' operator on this object with the given argument.
3272 *
3273 * @param rightOperand the right-hand operand of the operation
3274 * @return the result of invoking the '&lt;=' operator on this object with the given argument
3275 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3276 */
3277 BoolState lessThanOrEqual(InstanceState rightOperand) {
3278 assertNumOrNull(this);
3279 assertNumOrNull(rightOperand);
3280 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3281 }
3282
3283 /**
3284 * Return the result of invoking the '&&' operator on this object with the giv en argument.
3285 *
3286 * @param rightOperand the right-hand operand of the operation
3287 * @return the result of invoking the '&&' operator on this object with the gi ven argument
3288 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3289 */
3290 BoolState logicalAnd(InstanceState rightOperand) {
3291 assertBool(this);
3292 assertBool(rightOperand);
3293 return BoolState.FALSE_STATE;
3294 }
3295
3296 /**
3297 * Return the result of invoking the '!' operator on this object.
3298 *
3299 * @return the result of invoking the '!' operator on this object
3300 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3301 */
3302 BoolState logicalNot() {
3303 assertBool(this);
3304 return BoolState.TRUE_STATE;
3305 }
3306
3307 /**
3308 * Return the result of invoking the '||' operator on this object with the giv en argument.
3309 *
3310 * @param rightOperand the right-hand operand of the operation
3311 * @return the result of invoking the '||' operator on this object with the gi ven argument
3312 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3313 */
3314 BoolState logicalOr(InstanceState rightOperand) {
3315 assertBool(this);
3316 assertBool(rightOperand);
3317 return rightOperand.convertToBool();
3318 }
3319
3320 /**
3321 * Return the result of invoking the '-' operator on this object with the give n argument.
3322 *
3323 * @param rightOperand the right-hand operand of the operation
3324 * @return the result of invoking the '-' operator on this object with the giv en argument
3325 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3326 */
3327 NumState minus(InstanceState rightOperand) {
3328 assertNumOrNull(this);
3329 assertNumOrNull(rightOperand);
3330 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3331 }
3332
3333 /**
3334 * Return the result of invoking the '-' operator on this object.
3335 *
3336 * @return the result of invoking the '-' operator on this object
3337 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3338 */
3339 NumState negated() {
3340 assertNumOrNull(this);
3341 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3342 }
3343
3344 /**
3345 * Return the result of invoking the '%' operator on this object with the give n argument.
3346 *
3347 * @param rightOperand the right-hand operand of the operation
3348 * @return the result of invoking the '%' operator on this object with the giv en argument
3349 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3350 */
3351 NumState remainder(InstanceState rightOperand) {
3352 assertNumOrNull(this);
3353 assertNumOrNull(rightOperand);
3354 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3355 }
3356
3357 /**
3358 * Return the result of invoking the '&lt;&lt;' operator on this object with t he given argument.
3359 *
3360 * @param rightOperand the right-hand operand of the operation
3361 * @return the result of invoking the '&lt;&lt;' operator on this object with the given argument
3362 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3363 */
3364 IntState shiftLeft(InstanceState rightOperand) {
3365 assertIntOrNull(this);
3366 assertIntOrNull(rightOperand);
3367 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3368 }
3369
3370 /**
3371 * Return the result of invoking the '&gt;&gt;' operator on this object with t he given argument.
3372 *
3373 * @param rightOperand the right-hand operand of the operation
3374 * @return the result of invoking the '&gt;&gt;' operator on this object with the given argument
3375 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3376 */
3377 IntState shiftRight(InstanceState rightOperand) {
3378 assertIntOrNull(this);
3379 assertIntOrNull(rightOperand);
3380 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3381 }
3382
3383 /**
3384 * Return the result of invoking the '*' operator on this object with the give n argument.
3385 *
3386 * @param rightOperand the right-hand operand of the operation
3387 * @return the result of invoking the '*' operator on this object with the giv en argument
3388 * @throws EvaluationException if the operator is not appropriate for an objec t of this kind
3389 */
3390 NumState times(InstanceState rightOperand) {
3391 assertNumOrNull(this);
3392 assertNumOrNull(rightOperand);
3393 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
3394 }
3395
3396 /**
3397 * Throw an exception if the given state does not represent a boolean value.
3398 *
3399 * @param state the state being tested
3400 * @throws EvaluationException if the given state does not represent a boolean value
3401 */
3402 void assertBool(InstanceState state) {
3403 if (!(state is BoolState || state is DynamicState)) {
3404 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
3405 }
3406 }
3407
3408 /**
3409 * Throw an exception if the given state does not represent a boolean, numeric , string or null
3410 * value.
3411 *
3412 * @param state the state being tested
3413 * @throws EvaluationException if the given state does not represent a boolean , numeric, string or
3414 * null value
3415 */
3416 void assertBoolNumStringOrNull(InstanceState state) {
3417 if (!(state is BoolState || state is DoubleState || state is IntState || sta te is NumState || state is StringState || state is NullState || state is Dynamic State)) {
3418 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NU M_STRING);
3419 }
3420 }
3421
3422 /**
3423 * Throw an exception if the given state does not represent an integer or null value.
3424 *
3425 * @param state the state being tested
3426 * @throws EvaluationException if the given state does not represent an intege r or null value
3427 */
3428 void assertIntOrNull(InstanceState state) {
3429 if (!(state is IntState || state is NumState || state is NullState || state is DynamicState)) {
3430 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
3431 }
3432 }
3433
3434 /**
3435 * Throw an exception if the given state does not represent a boolean, numeric , string or null
3436 * value.
3437 *
3438 * @param state the state being tested
3439 * @throws EvaluationException if the given state does not represent a boolean , numeric, string or
3440 * null value
3441 */
3442 void assertNumOrNull(InstanceState state) {
3443 if (!(state is DoubleState || state is IntState || state is NumState || stat e is NullState || state is DynamicState)) {
3444 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
3445 }
3446 }
3447
3448 /**
3449 * Throw an exception if the given state does not represent a String value.
3450 *
3451 * @param state the state being tested
3452 * @throws EvaluationException if the given state does not represent a String value
3453 */
3454 void assertString(InstanceState state) {
3455 if (!(state is StringState || state is DynamicState)) {
3456 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
3457 }
3458 }
3459 }
3460
3461 /**
3462 * Instances of the class `IntState` represent the state of an object representi ng an int.
3463 */
3464 class IntState extends NumState {
3465 /**
3466 * The value of this instance.
3467 */
3468 final int value;
3469
3470 /**
3471 * A state that can be used to represent an int whose value is not known.
3472 */
3473 static IntState UNKNOWN_VALUE = new IntState(null);
3474
3475 /**
3476 * Initialize a newly created state to represent an int with the given value.
3477 *
3478 * @param value the value of this instance
3479 */
3480 IntState(this.value);
3481
3482 @override
3483 NumState add(InstanceState rightOperand) {
3484 assertNumOrNull(rightOperand);
3485 if (value == null) {
3486 if (rightOperand is DoubleState) {
3487 return DoubleState.UNKNOWN_VALUE;
3488 }
3489 return UNKNOWN_VALUE;
3490 }
3491 if (rightOperand is IntState) {
3492 int rightValue = rightOperand.value;
3493 if (rightValue == null) {
3494 return UNKNOWN_VALUE;
3495 }
3496 return new IntState(value + rightValue);
3497 } else if (rightOperand is DoubleState) {
3498 double rightValue = rightOperand.value;
3499 if (rightValue == null) {
3500 return DoubleState.UNKNOWN_VALUE;
3501 }
3502 return new DoubleState(value.toDouble() + rightValue);
3503 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3504 return UNKNOWN_VALUE;
3505 }
3506 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3507 }
3508
3509 @override
3510 IntState bitAnd(InstanceState rightOperand) {
3511 assertIntOrNull(rightOperand);
3512 if (value == null) {
3513 return UNKNOWN_VALUE;
3514 }
3515 if (rightOperand is IntState) {
3516 int rightValue = rightOperand.value;
3517 if (rightValue == null) {
3518 return UNKNOWN_VALUE;
3519 }
3520 return new IntState(value & rightValue);
3521 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3522 return UNKNOWN_VALUE;
3523 }
3524 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3525 }
3526
3527 @override
3528 IntState bitNot() {
3529 if (value == null) {
3530 return UNKNOWN_VALUE;
3531 }
3532 return new IntState(~value);
3533 }
3534
3535 @override
3536 IntState bitOr(InstanceState rightOperand) {
3537 assertIntOrNull(rightOperand);
3538 if (value == null) {
3539 return UNKNOWN_VALUE;
3540 }
3541 if (rightOperand is IntState) {
3542 int rightValue = rightOperand.value;
3543 if (rightValue == null) {
3544 return UNKNOWN_VALUE;
3545 }
3546 return new IntState(value | rightValue);
3547 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3548 return UNKNOWN_VALUE;
3549 }
3550 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3551 }
3552
3553 @override
3554 IntState bitXor(InstanceState rightOperand) {
3555 assertIntOrNull(rightOperand);
3556 if (value == null) {
3557 return UNKNOWN_VALUE;
3558 }
3559 if (rightOperand is IntState) {
3560 int rightValue = rightOperand.value;
3561 if (rightValue == null) {
3562 return UNKNOWN_VALUE;
3563 }
3564 return new IntState(value ^ rightValue);
3565 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3566 return UNKNOWN_VALUE;
3567 }
3568 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3569 }
3570
3571 @override
3572 StringState convertToString() {
3573 if (value == null) {
3574 return StringState.UNKNOWN_VALUE;
3575 }
3576 return new StringState(value.toString());
3577 }
3578
3579 @override
3580 NumState divide(InstanceState rightOperand) {
3581 assertNumOrNull(rightOperand);
3582 if (value == null) {
3583 if (rightOperand is DoubleState) {
3584 return DoubleState.UNKNOWN_VALUE;
3585 }
3586 return UNKNOWN_VALUE;
3587 }
3588 if (rightOperand is IntState) {
3589 int rightValue = rightOperand.value;
3590 if (rightValue == null) {
3591 return UNKNOWN_VALUE;
3592 } else if (rightValue == 0) {
3593 return new DoubleState(value.toDouble() / rightValue.toDouble());
3594 }
3595 return new IntState(value ~/ rightValue);
3596 } else if (rightOperand is DoubleState) {
3597 double rightValue = rightOperand.value;
3598 if (rightValue == null) {
3599 return DoubleState.UNKNOWN_VALUE;
3600 }
3601 return new DoubleState(value.toDouble() / rightValue);
3602 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3603 return UNKNOWN_VALUE;
3604 }
3605 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3606 }
3607
3608 @override
3609 BoolState equalEqual(InstanceState rightOperand) {
3610 assertBoolNumStringOrNull(rightOperand);
3611 if (value == null) {
3612 return BoolState.UNKNOWN_VALUE;
3613 }
3614 if (rightOperand is IntState) {
3615 int rightValue = rightOperand.value;
3616 if (rightValue == null) {
3617 return BoolState.UNKNOWN_VALUE;
3618 }
3619 return BoolState.from(value == rightValue);
3620 } else if (rightOperand is DoubleState) {
3621 double rightValue = rightOperand.value;
3622 if (rightValue == null) {
3623 return BoolState.UNKNOWN_VALUE;
3624 }
3625 return BoolState.from(rightValue == value.toDouble());
3626 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3627 return BoolState.UNKNOWN_VALUE;
3628 }
3629 return BoolState.FALSE_STATE;
3630 }
3631
3632 @override
3633 bool operator ==(Object object) => object is IntState && (value == object.valu e);
3634
3635 @override
3636 String get typeName => "int";
3637
3638 @override
3639 BoolState greaterThan(InstanceState rightOperand) {
3640 assertNumOrNull(rightOperand);
3641 if (value == null) {
3642 return BoolState.UNKNOWN_VALUE;
3643 }
3644 if (rightOperand is IntState) {
3645 int rightValue = rightOperand.value;
3646 if (rightValue == null) {
3647 return BoolState.UNKNOWN_VALUE;
3648 }
3649 return BoolState.from(value.compareTo(rightValue) > 0);
3650 } else if (rightOperand is DoubleState) {
3651 double rightValue = rightOperand.value;
3652 if (rightValue == null) {
3653 return BoolState.UNKNOWN_VALUE;
3654 }
3655 return BoolState.from(value.toDouble() > rightValue);
3656 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3657 return BoolState.UNKNOWN_VALUE;
3658 }
3659 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3660 }
3661
3662 @override
3663 BoolState greaterThanOrEqual(InstanceState rightOperand) {
3664 assertNumOrNull(rightOperand);
3665 if (value == null) {
3666 return BoolState.UNKNOWN_VALUE;
3667 }
3668 if (rightOperand is IntState) {
3669 int rightValue = rightOperand.value;
3670 if (rightValue == null) {
3671 return BoolState.UNKNOWN_VALUE;
3672 }
3673 return BoolState.from(value.compareTo(rightValue) >= 0);
3674 } else if (rightOperand is DoubleState) {
3675 double rightValue = rightOperand.value;
3676 if (rightValue == null) {
3677 return BoolState.UNKNOWN_VALUE;
3678 }
3679 return BoolState.from(value.toDouble() >= rightValue);
3680 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3681 return BoolState.UNKNOWN_VALUE;
3682 }
3683 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3684 }
3685
3686 @override
3687 bool get hasExactValue => true;
3688
3689 @override
3690 int get hashCode => value == null ? 0 : value.hashCode;
3691
3692 @override
3693 IntState integerDivide(InstanceState rightOperand) {
3694 assertNumOrNull(rightOperand);
3695 if (value == null) {
3696 return UNKNOWN_VALUE;
3697 }
3698 if (rightOperand is IntState) {
3699 int rightValue = rightOperand.value;
3700 if (rightValue == null) {
3701 return UNKNOWN_VALUE;
3702 } else if (rightValue == 0) {
3703 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_IDB ZE);
3704 }
3705 return new IntState(value ~/ rightValue);
3706 } else if (rightOperand is DoubleState) {
3707 double rightValue = rightOperand.value;
3708 if (rightValue == null) {
3709 return UNKNOWN_VALUE;
3710 }
3711 double result = value.toDouble() / rightValue;
3712 return new IntState(result.toInt());
3713 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3714 return UNKNOWN_VALUE;
3715 }
3716 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3717 }
3718
3719 @override
3720 bool get isBoolNumStringOrNull => true;
3721
3722 @override
3723 bool get isUnknown => value == null;
3724
3725 @override
3726 BoolState lessThan(InstanceState rightOperand) {
3727 assertNumOrNull(rightOperand);
3728 if (value == null) {
3729 return BoolState.UNKNOWN_VALUE;
3730 }
3731 if (rightOperand is IntState) {
3732 int rightValue = rightOperand.value;
3733 if (rightValue == null) {
3734 return BoolState.UNKNOWN_VALUE;
3735 }
3736 return BoolState.from(value.compareTo(rightValue) < 0);
3737 } else if (rightOperand is DoubleState) {
3738 double rightValue = rightOperand.value;
3739 if (rightValue == null) {
3740 return BoolState.UNKNOWN_VALUE;
3741 }
3742 return BoolState.from(value.toDouble() < rightValue);
3743 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3744 return BoolState.UNKNOWN_VALUE;
3745 }
3746 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3747 }
3748
3749 @override
3750 BoolState lessThanOrEqual(InstanceState rightOperand) {
3751 assertNumOrNull(rightOperand);
3752 if (value == null) {
3753 return BoolState.UNKNOWN_VALUE;
3754 }
3755 if (rightOperand is IntState) {
3756 int rightValue = rightOperand.value;
3757 if (rightValue == null) {
3758 return BoolState.UNKNOWN_VALUE;
3759 }
3760 return BoolState.from(value.compareTo(rightValue) <= 0);
3761 } else if (rightOperand is DoubleState) {
3762 double rightValue = rightOperand.value;
3763 if (rightValue == null) {
3764 return BoolState.UNKNOWN_VALUE;
3765 }
3766 return BoolState.from(value.toDouble() <= rightValue);
3767 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3768 return BoolState.UNKNOWN_VALUE;
3769 }
3770 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3771 }
3772
3773 @override
3774 NumState minus(InstanceState rightOperand) {
3775 assertNumOrNull(rightOperand);
3776 if (value == null) {
3777 if (rightOperand is DoubleState) {
3778 return DoubleState.UNKNOWN_VALUE;
3779 }
3780 return UNKNOWN_VALUE;
3781 }
3782 if (rightOperand is IntState) {
3783 int rightValue = rightOperand.value;
3784 if (rightValue == null) {
3785 return UNKNOWN_VALUE;
3786 }
3787 return new IntState(value - rightValue);
3788 } else if (rightOperand is DoubleState) {
3789 double rightValue = rightOperand.value;
3790 if (rightValue == null) {
3791 return DoubleState.UNKNOWN_VALUE;
3792 }
3793 return new DoubleState(value.toDouble() - rightValue);
3794 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3795 return UNKNOWN_VALUE;
3796 }
3797 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3798 }
3799
3800 @override
3801 NumState negated() {
3802 if (value == null) {
3803 return UNKNOWN_VALUE;
3804 }
3805 return new IntState(-value);
3806 }
3807
3808 @override
3809 NumState remainder(InstanceState rightOperand) {
3810 assertNumOrNull(rightOperand);
3811 if (value == null) {
3812 if (rightOperand is DoubleState) {
3813 return DoubleState.UNKNOWN_VALUE;
3814 }
3815 return UNKNOWN_VALUE;
3816 }
3817 if (rightOperand is IntState) {
3818 int rightValue = rightOperand.value;
3819 if (rightValue == null) {
3820 return UNKNOWN_VALUE;
3821 } else if (rightValue == 0) {
3822 return new DoubleState(value.toDouble() % rightValue.toDouble());
3823 }
3824 return new IntState(value.remainder(rightValue));
3825 } else if (rightOperand is DoubleState) {
3826 double rightValue = rightOperand.value;
3827 if (rightValue == null) {
3828 return DoubleState.UNKNOWN_VALUE;
3829 }
3830 return new DoubleState(value.toDouble() % rightValue);
3831 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3832 return UNKNOWN_VALUE;
3833 }
3834 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3835 }
3836
3837 @override
3838 IntState shiftLeft(InstanceState rightOperand) {
3839 assertIntOrNull(rightOperand);
3840 if (value == null) {
3841 return UNKNOWN_VALUE;
3842 }
3843 if (rightOperand is IntState) {
3844 int rightValue = rightOperand.value;
3845 if (rightValue == null) {
3846 return UNKNOWN_VALUE;
3847 } else if (rightValue.bitLength > 31) {
3848 return UNKNOWN_VALUE;
3849 }
3850 return new IntState(value << rightValue);
3851 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3852 return UNKNOWN_VALUE;
3853 }
3854 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3855 }
3856
3857 @override
3858 IntState shiftRight(InstanceState rightOperand) {
3859 assertIntOrNull(rightOperand);
3860 if (value == null) {
3861 return UNKNOWN_VALUE;
3862 }
3863 if (rightOperand is IntState) {
3864 int rightValue = rightOperand.value;
3865 if (rightValue == null) {
3866 return UNKNOWN_VALUE;
3867 } else if (rightValue.bitLength > 31) {
3868 return UNKNOWN_VALUE;
3869 }
3870 return new IntState(value >> rightValue);
3871 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3872 return UNKNOWN_VALUE;
3873 }
3874 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3875 }
3876
3877 @override
3878 NumState times(InstanceState rightOperand) {
3879 assertNumOrNull(rightOperand);
3880 if (value == null) {
3881 if (rightOperand is DoubleState) {
3882 return DoubleState.UNKNOWN_VALUE;
3883 }
3884 return UNKNOWN_VALUE;
3885 }
3886 if (rightOperand is IntState) {
3887 int rightValue = rightOperand.value;
3888 if (rightValue == null) {
3889 return UNKNOWN_VALUE;
3890 }
3891 return new IntState(value * rightValue);
3892 } else if (rightOperand is DoubleState) {
3893 double rightValue = rightOperand.value;
3894 if (rightValue == null) {
3895 return DoubleState.UNKNOWN_VALUE;
3896 }
3897 return new DoubleState(value.toDouble() * rightValue);
3898 } else if (rightOperand is DynamicState || rightOperand is NumState) {
3899 return UNKNOWN_VALUE;
3900 }
3901 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
3902 }
3903
3904 @override
3905 String toString() => value == null ? "-unknown-" : value.toString();
3906 }
3907
3908 /**
3909 * The unique instance of the class `ListState` represents the state of an objec t representing
3910 * a list.
3911 */
3912 class ListState extends InstanceState {
3913 /**
3914 * The elements of the list.
3915 */
3916 final List<DartObjectImpl> _elements;
3917
3918 /**
3919 * Initialize a newly created state to represent a list with the given element s.
3920 *
3921 * @param elements the elements of the list
3922 */
3923 ListState(this._elements);
3924
3925 @override
3926 StringState convertToString() => StringState.UNKNOWN_VALUE;
3927
3928 @override
3929 BoolState equalEqual(InstanceState rightOperand) {
3930 assertBoolNumStringOrNull(rightOperand);
3931 if (rightOperand is DynamicState) {
3932 return BoolState.UNKNOWN_VALUE;
3933 }
3934 return BoolState.from(this == rightOperand);
3935 }
3936
3937 @override
3938 bool operator ==(Object object) {
3939 if (object is! ListState) {
3940 return false;
3941 }
3942 List<DartObjectImpl> otherElements = (object as ListState)._elements;
3943 int count = _elements.length;
3944 if (otherElements.length != count) {
3945 return false;
3946 } else if (count == 0) {
3947 return true;
3948 }
3949 for (int i = 0; i < count; i++) {
3950 if (_elements[i] != otherElements[i]) {
3951 return false;
3952 }
3953 }
3954 return true;
3955 }
3956
3957 @override
3958 String get typeName => "List";
3959
3960 @override
3961 List<Object> get value {
3962 int count = _elements.length;
3963 List<Object> result = new List<Object>(count);
3964 for (int i = 0; i < count; i++) {
3965 DartObjectImpl element = _elements[i];
3966 if (!element.hasExactValue) {
3967 return null;
3968 }
3969 result[i] = element.value;
3970 }
3971 return result;
3972 }
3973
3974 @override
3975 bool get hasExactValue {
3976 int count = _elements.length;
3977 for (int i = 0; i < count; i++) {
3978 if (!_elements[i].hasExactValue) {
3979 return false;
3980 }
3981 }
3982 return true;
3983 }
3984
3985 @override
3986 int get hashCode {
3987 int value = 0;
3988 int count = _elements.length;
3989 for (int i = 0; i < count; i++) {
3990 value = (value << 3) ^ _elements[i].hashCode;
3991 }
3992 return value;
3993 }
3994 }
3995
3996 /**
3997 * The unique instance of the class `ListState` represents the state of an objec t representing
3998 * a map.
3999 */
4000 class MapState extends InstanceState {
4001 /**
4002 * The entries in the map.
4003 */
4004 final HashMap<DartObjectImpl, DartObjectImpl> _entries;
4005
4006 /**
4007 * Initialize a newly created state to represent a map with the given entries.
4008 *
4009 * @param entries the entries in the map
4010 */
4011 MapState(this._entries);
4012
4013 @override
4014 StringState convertToString() => StringState.UNKNOWN_VALUE;
4015
4016 @override
4017 BoolState equalEqual(InstanceState rightOperand) {
4018 assertBoolNumStringOrNull(rightOperand);
4019 if (rightOperand is DynamicState) {
4020 return BoolState.UNKNOWN_VALUE;
4021 }
4022 return BoolState.from(this == rightOperand);
4023 }
4024
4025 @override
4026 bool operator ==(Object object) {
4027 if (object is! MapState) {
4028 return false;
4029 }
4030 HashMap<DartObjectImpl, DartObjectImpl> otherElements = (object as MapState) ._entries;
4031 int count = _entries.length;
4032 if (otherElements.length != count) {
4033 return false;
4034 } else if (count == 0) {
4035 return true;
4036 }
4037 for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entri es)) {
4038 DartObjectImpl key = entry.getKey();
4039 DartObjectImpl value = entry.getValue();
4040 DartObjectImpl otherValue = otherElements[key];
4041 if (value != otherValue) {
4042 return false;
4043 }
4044 }
4045 return true;
4046 }
4047
4048 @override
4049 String get typeName => "Map";
4050
4051 @override
4052 Map<Object, Object> get value {
4053 HashMap<Object, Object> result = new HashMap<Object, Object>();
4054 for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entri es)) {
4055 DartObjectImpl key = entry.getKey();
4056 DartObjectImpl value = entry.getValue();
4057 if (!key.hasExactValue || !value.hasExactValue) {
4058 return null;
4059 }
4060 result[key.value] = value.value;
4061 }
4062 return result;
4063 }
4064
4065 @override
4066 bool get hasExactValue {
4067 for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entri es)) {
4068 if (!entry.getKey().hasExactValue || !entry.getValue().hasExactValue) {
4069 return false;
4070 }
4071 }
4072 return true;
4073 }
4074
4075 @override
4076 int get hashCode {
4077 int value = 0;
4078 for (DartObjectImpl key in _entries.keys.toSet()) {
4079 value = (value << 3) ^ key.hashCode;
4080 }
4081 return value;
4082 }
4083 }
4084
4085 /**
4086 * The unique instance of the class `NullState` represents the state of the valu e 'null'.
4087 */
4088 class NullState extends InstanceState {
4089 /**
4090 * An instance representing the boolean value 'true'.
4091 */
4092 static NullState NULL_STATE = new NullState();
4093
4094 @override
4095 BoolState convertToBool() {
4096 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
4097 }
4098
4099 @override
4100 StringState convertToString() => new StringState("null");
4101
4102 @override
4103 BoolState equalEqual(InstanceState rightOperand) {
4104 assertBoolNumStringOrNull(rightOperand);
4105 if (rightOperand is DynamicState) {
4106 return BoolState.UNKNOWN_VALUE;
4107 }
4108 return BoolState.from(rightOperand is NullState);
4109 }
4110
4111 @override
4112 bool operator ==(Object object) => object is NullState;
4113
4114 @override
4115 String get typeName => "Null";
4116
4117 @override
4118 bool get hasExactValue => true;
4119
4120 @override
4121 int get hashCode => 0;
4122
4123 @override
4124 bool get isBoolNumStringOrNull => true;
4125
4126 @override
4127 BoolState logicalNot() {
4128 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI ON);
4129 }
4130
4131 @override
4132 String toString() => "null";
4133 }
4134
4135 /**
4136 * Instances of the class `NumState` represent the state of an object representi ng a number of
4137 * an unknown type (a 'num').
4138 */
4139 class NumState extends InstanceState {
4140 /**
4141 * A state that can be used to represent a number whose value is not known.
4142 */
4143 static NumState UNKNOWN_VALUE = new NumState();
4144
4145 @override
4146 NumState add(InstanceState rightOperand) {
4147 assertNumOrNull(rightOperand);
4148 return UNKNOWN_VALUE;
4149 }
4150
4151 @override
4152 StringState convertToString() => StringState.UNKNOWN_VALUE;
4153
4154 @override
4155 NumState divide(InstanceState rightOperand) {
4156 assertNumOrNull(rightOperand);
4157 return UNKNOWN_VALUE;
4158 }
4159
4160 @override
4161 BoolState equalEqual(InstanceState rightOperand) {
4162 assertBoolNumStringOrNull(rightOperand);
4163 return BoolState.UNKNOWN_VALUE;
4164 }
4165
4166 @override
4167 bool operator ==(Object object) => object is NumState;
4168
4169 @override
4170 String get typeName => "num";
4171
4172 @override
4173 BoolState greaterThan(InstanceState rightOperand) {
4174 assertNumOrNull(rightOperand);
4175 return BoolState.UNKNOWN_VALUE;
4176 }
4177
4178 @override
4179 BoolState greaterThanOrEqual(InstanceState rightOperand) {
4180 assertNumOrNull(rightOperand);
4181 return BoolState.UNKNOWN_VALUE;
4182 }
4183
4184 @override
4185 int get hashCode => 7;
4186
4187 @override
4188 IntState integerDivide(InstanceState rightOperand) {
4189 assertNumOrNull(rightOperand);
4190 if (rightOperand is IntState) {
4191 int rightValue = rightOperand.value;
4192 if (rightValue == null) {
4193 return IntState.UNKNOWN_VALUE;
4194 } else if (rightValue == 0) {
4195 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_IDB ZE);
4196 }
4197 } else if (rightOperand is DynamicState) {
4198 return IntState.UNKNOWN_VALUE;
4199 }
4200 return IntState.UNKNOWN_VALUE;
4201 }
4202
4203 @override
4204 bool get isBoolNumStringOrNull => true;
4205
4206 @override
4207 bool get isUnknown => identical(this, UNKNOWN_VALUE);
4208
4209 @override
4210 BoolState lessThan(InstanceState rightOperand) {
4211 assertNumOrNull(rightOperand);
4212 return BoolState.UNKNOWN_VALUE;
4213 }
4214
4215 @override
4216 BoolState lessThanOrEqual(InstanceState rightOperand) {
4217 assertNumOrNull(rightOperand);
4218 return BoolState.UNKNOWN_VALUE;
4219 }
4220
4221 @override
4222 NumState minus(InstanceState rightOperand) {
4223 assertNumOrNull(rightOperand);
4224 return UNKNOWN_VALUE;
4225 }
4226
4227 @override
4228 NumState negated() => UNKNOWN_VALUE;
4229
4230 @override
4231 NumState remainder(InstanceState rightOperand) {
4232 assertNumOrNull(rightOperand);
4233 return UNKNOWN_VALUE;
4234 }
4235
4236 @override
4237 NumState times(InstanceState rightOperand) {
4238 assertNumOrNull(rightOperand);
4239 return UNKNOWN_VALUE;
4240 }
4241
4242 @override
4243 String toString() => "-unknown-";
4244 }
4245
4246 /**
4247 * Instances of the class `ReferenceFinder` add reference information for a give n variable to
4248 * the bi-directional mapping used to order the evaluation of constants.
4249 */
4250 class ReferenceFinder extends RecursiveAstVisitor<Object> {
4251 /**
4252 * The element representing the construct that will be visited.
4253 */
4254 final AstNode _source;
4255
4256 /**
4257 * A graph in which the nodes are the constant variables and the edges are fro m each variable to
4258 * the other constant variables that are referenced in the head's initializer.
4259 */
4260 final DirectedGraph<AstNode> _referenceGraph;
4261
4262 /**
4263 * A table mapping constant variables to the declarations of those variables.
4264 */
4265 final HashMap<VariableElement, VariableDeclaration> _variableDeclarationMap;
4266
4267 /**
4268 * A table mapping constant constructors to the declarations of those construc tors.
4269 */
4270 final HashMap<ConstructorElement, ConstructorDeclaration> _constructorDeclarat ionMap;
4271
4272 /**
4273 * Initialize a newly created reference finder to find references from the giv en variable to other
4274 * variables and to add those references to the given graph.
4275 *
4276 * @param source the element representing the variable whose initializer will be visited
4277 * @param referenceGraph a graph recording which variables (heads) reference w hich other variables
4278 * (tails) in their initializers
4279 * @param variableDeclarationMap A table mapping constant variables to the dec larations of those
4280 * variables.
4281 * @param constructorDeclarationMap A table mapping constant constructors to t he declarations of
4282 * those constructors.
4283 */
4284 ReferenceFinder(this._source, this._referenceGraph, this._variableDeclarationM ap, this._constructorDeclarationMap);
4285
4286 @override
4287 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
4288 if (node.isConst) {
4289 _referenceGraph.addEdge(_source, node);
4290 }
4291 return null;
4292 }
4293
4294 @override
4295 Object visitSimpleIdentifier(SimpleIdentifier node) {
4296 Element element = node.staticElement;
4297 if (element is PropertyAccessorElement) {
4298 element = (element as PropertyAccessorElement).variable;
4299 }
4300 if (element is VariableElement) {
4301 VariableElement variable = element as VariableElement;
4302 if (variable.isConst) {
4303 VariableDeclaration variableDeclaration = _variableDeclarationMap[variab le];
4304 // The declaration will be null when the variable is not defined in the compilation units
4305 // that were used to produce the variableDeclarationMap. In such cases, the variable should
4306 // already have a value associated with it, but we don't bother to check because there's
4307 // nothing we can do about it at this point.
4308 if (variableDeclaration != null) {
4309 _referenceGraph.addEdge(_source, variableDeclaration);
4310 }
4311 }
4312 }
4313 return null;
4314 }
4315
4316 @override
4317 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
4318 super.visitSuperConstructorInvocation(node);
4319 ConstructorElement constructor = node.staticElement;
4320 if (constructor != null && constructor.isConst) {
4321 ConstructorDeclaration constructorDeclaration = _constructorDeclarationMap [constructor];
4322 // The declaration will be null when the constructor is not defined in the compilation
4323 // units that were used to produce the constructorDeclarationMap. In such cases, the
4324 // constructor should already have its initializer AST's stored in it, but we don't bother
4325 // to check because there's nothing we can do about it at this point.
4326 if (constructorDeclaration != null) {
4327 _referenceGraph.addEdge(_source, constructorDeclaration);
4328 }
4329 }
4330 return null;
4331 }
4332 }
4333
4334 /**
4335 * Instances of the class `StringState` represent the state of an object represe nting a
4336 * string.
4337 */
4338 class StringState extends InstanceState {
4339 /**
4340 * The value of this instance.
4341 */
4342 final String value;
4343
4344 /**
4345 * A state that can be used to represent a double whose value is not known.
4346 */
4347 static StringState UNKNOWN_VALUE = new StringState(null);
4348
4349 /**
4350 * Initialize a newly created state to represent the given value.
4351 *
4352 * @param value the value of this instance
4353 */
4354 StringState(this.value);
4355
4356 @override
4357 StringState concatenate(InstanceState rightOperand) {
4358 if (value == null) {
4359 return UNKNOWN_VALUE;
4360 }
4361 if (rightOperand is StringState) {
4362 String rightValue = rightOperand.value;
4363 if (rightValue == null) {
4364 return UNKNOWN_VALUE;
4365 }
4366 return new StringState("${value}${rightValue}");
4367 } else if (rightOperand is DynamicState) {
4368 return UNKNOWN_VALUE;
4369 }
4370 return super.concatenate(rightOperand);
4371 }
4372
4373 @override
4374 StringState convertToString() => this;
4375
4376 @override
4377 BoolState equalEqual(InstanceState rightOperand) {
4378 assertBoolNumStringOrNull(rightOperand);
4379 if (value == null) {
4380 return BoolState.UNKNOWN_VALUE;
4381 }
4382 if (rightOperand is StringState) {
4383 String rightValue = rightOperand.value;
4384 if (rightValue == null) {
4385 return BoolState.UNKNOWN_VALUE;
4386 }
4387 return BoolState.from(value == rightValue);
4388 } else if (rightOperand is DynamicState) {
4389 return BoolState.UNKNOWN_VALUE;
4390 }
4391 return BoolState.FALSE_STATE;
4392 }
4393
4394 @override
4395 bool operator ==(Object object) => object is StringState && (value == object.v alue);
4396
4397 @override
4398 String get typeName => "String";
4399
4400 @override
4401 bool get hasExactValue => true;
4402
4403 @override
4404 int get hashCode => value == null ? 0 : value.hashCode;
4405
4406 @override
4407 bool get isBoolNumStringOrNull => true;
4408
4409 @override
4410 bool get isUnknown => value == null;
4411
4412 @override
4413 String toString() => value == null ? "-unknown-" : "'${value}'";
4414 }
4415
4416 /**
4417 * Instances of the class `StringState` represent the state of an object represe nting a
4418 * symbol.
4419 */
4420 class SymbolState extends InstanceState {
4421 /**
4422 * The value of this instance.
4423 */
4424 final String value;
4425
4426 /**
4427 * Initialize a newly created state to represent the given value.
4428 *
4429 * @param value the value of this instance
4430 */
4431 SymbolState(this.value);
4432
4433 @override
4434 StringState convertToString() {
4435 if (value == null) {
4436 return StringState.UNKNOWN_VALUE;
4437 }
4438 return new StringState(value);
4439 }
4440
4441 @override
4442 BoolState equalEqual(InstanceState rightOperand) {
4443 assertBoolNumStringOrNull(rightOperand);
4444 if (value == null) {
4445 return BoolState.UNKNOWN_VALUE;
4446 }
4447 if (rightOperand is SymbolState) {
4448 String rightValue = rightOperand.value;
4449 if (rightValue == null) {
4450 return BoolState.UNKNOWN_VALUE;
4451 }
4452 return BoolState.from(value == rightValue);
4453 } else if (rightOperand is DynamicState) {
4454 return BoolState.UNKNOWN_VALUE;
4455 }
4456 return BoolState.FALSE_STATE;
4457 }
4458
4459 @override
4460 bool operator ==(Object object) => object is SymbolState && (value == object.v alue);
4461
4462 @override
4463 String get typeName => "Symbol";
4464
4465 @override
4466 bool get hasExactValue => true;
4467
4468 @override
4469 int get hashCode => value == null ? 0 : value.hashCode;
4470
4471 @override
4472 String toString() => value == null ? "-unknown-" : "#${value}";
4473 }
4474
4475 /**
4476 * Instances of the class `TypeState` represent the state of an object represent ing a type.
4477 */
4478 class TypeState extends InstanceState {
4479 /**
4480 * The element representing the type being modeled.
4481 */
4482 final Element _element;
4483
4484 /**
4485 * Initialize a newly created state to represent the given value.
4486 *
4487 * @param element the element representing the type being modeled
4488 */
4489 TypeState(this._element);
4490
4491 @override
4492 StringState convertToString() {
4493 if (_element == null) {
4494 return StringState.UNKNOWN_VALUE;
4495 }
4496 return new StringState(_element.name);
4497 }
4498
4499 @override
4500 bool operator ==(Object object) => object is TypeState && (_element == object. _element);
4501
4502 @override
4503 BoolState equalEqual(InstanceState rightOperand) {
4504 assertBoolNumStringOrNull(rightOperand);
4505 if (_element == null) {
4506 return BoolState.UNKNOWN_VALUE;
4507 }
4508 if (rightOperand is TypeState) {
4509 Element rightElement = rightOperand._element;
4510 if (rightElement == null) {
4511 return BoolState.UNKNOWN_VALUE;
4512 }
4513 return BoolState.from(_element == rightElement);
4514 } else if (rightOperand is DynamicState) {
4515 return BoolState.UNKNOWN_VALUE;
4516 }
4517 return BoolState.FALSE_STATE;
4518 }
4519
4520 @override
4521 String get typeName => "Type";
4522
4523 @override
4524 int get hashCode => _element == null ? 0 : _element.hashCode;
4525
4526 @override
4527 String toString() => _element == null ? "-unknown-" : _element.name;
4528 }
4529
4530 /**
4531 * Instances of the class `ValidResult` represent the result of attempting to ev aluate a valid
4532 * compile time constant expression.
4533 */
4534 class ValidResult extends EvaluationResultImpl {
4535 /**
4536 * The value of the expression.
4537 */
4538 final DartObjectImpl value;
4539
4540 /**
4541 * Initialize a newly created result to represent the given value.
4542 *
4543 * @param value the value of the expression
4544 */
4545 ValidResult(this.value);
4546
4547 @override
4548 EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, Eva luationResultImpl rightOperand) => rightOperand.addToValid(typeProvider, node, t his);
4549
4550 /**
4551 * Return the result of applying boolean conversion to this result.
4552 *
4553 * @param node the node against which errors should be reported
4554 * @return the result of applying boolean conversion to the given value
4555 */
4556 @override
4557 EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode node) {
4558 try {
4559 return _valueOf(value.convertToBool(typeProvider));
4560 } on EvaluationException catch (exception) {
4561 return _error(node, exception.errorCode);
4562 }
4563 }
4564
4565 @override
4566 EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitAndValid(typeProvider, nod e, this);
4567
4568 @override
4569 EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node) {
4570 try {
4571 return _valueOf(value.bitNot(typeProvider));
4572 } on EvaluationException catch (exception) {
4573 return _error(node, exception.errorCode);
4574 }
4575 }
4576
4577 @override
4578 EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand) => rightOperand.bitOrValid(typeProvider, node, this);
4579
4580 @override
4581 EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitXorValid(typeProvider, nod e, this);
4582
4583 @override
4584 EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, E valuationResultImpl rightOperand) => rightOperand.concatenateValid(typeProvider, node, this);
4585
4586 @override
4587 EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.divideValid(typeProvider, nod e, this);
4588
4589 @override
4590 EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, Ev aluationResultImpl rightOperand) => rightOperand.equalEqualValid(typeProvider, n ode, this);
4591
4592 @override
4593 bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) {
4594 if (result is! ValidResult) {
4595 return false;
4596 }
4597 return value == (result as ValidResult).value;
4598 }
4599
4600 @override
4601 EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression n ode, EvaluationResultImpl rightOperand) => rightOperand.greaterThanValid(typePro vider, node, this);
4602
4603 @override
4604 EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpre ssion node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanOrEqua lValid(typeProvider, node, this);
4605
4606 @override
4607 EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.integerDivideValid(typ eProvider, node, this);
4608
4609 /**
4610 * Return `true` if this object represents an object whose type is 'bool'.
4611 *
4612 * @return `true` if this object represents a boolean value
4613 */
4614 bool get isBool => value.isBool;
4615
4616 /**
4617 * Return `true` if this object represents an object whose type is either 'boo l', 'num',
4618 * 'String', or 'Null'.
4619 *
4620 * @return `true` if this object represents either a boolean, numeric, string or null value
4621 */
4622 bool get isBoolNumStringOrNull => value.isBoolNumStringOrNull;
4623
4624 /**
4625 * Return `true` if this result represents the value 'false'.
4626 *
4627 * @return `true` if this result represents the value 'false'
4628 */
4629 bool get isFalse => value.isFalse;
4630
4631 /**
4632 * Return `true` if this result represents the value 'null'.
4633 *
4634 * @return `true` if this result represents the value 'null'
4635 */
4636 bool get isNull => value.isNull;
4637
4638 /**
4639 * Return `true` if this result represents the value 'true'.
4640 *
4641 * @return `true` if this result represents the value 'true'
4642 */
4643 bool get isTrue => value.isTrue;
4644
4645 /**
4646 * Return `true` if this object represents an instance of a user-defined class .
4647 *
4648 * @return `true` if this object represents an instance of a user-defined clas s
4649 */
4650 bool get isUserDefinedObject => value.isUserDefinedObject;
4651
4652 @override
4653 EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node , EvaluationResultImpl rightOperand) => rightOperand.lessThanValid(typeProvider, node, this);
4654
4655 @override
4656 EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpressi on node, EvaluationResultImpl rightOperand) => rightOperand.lessThanOrEqualValid (typeProvider, node, this);
4657
4658 @override
4659 EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression no de, EvaluationResultImpl rightOperand) => rightOperand.logicalAndValid(typeProvi der, node, this);
4660
4661 @override
4662 EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node) {
4663 try {
4664 return _valueOf(value.logicalNot(typeProvider));
4665 } on EvaluationException catch (exception) {
4666 return _error(node, exception.errorCode);
4667 }
4668 }
4669
4670 @override
4671 EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand) => rightOperand.logicalOrValid(typeProvide r, node, this);
4672
4673 @override
4674 EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand) => rightOperand.minusValid(typeProvider, node, this);
4675
4676 @override
4677 EvaluationResultImpl negated(TypeProvider typeProvider, Expression node) {
4678 try {
4679 return _valueOf(value.negated(typeProvider));
4680 } on EvaluationException catch (exception) {
4681 return _error(node, exception.errorCode);
4682 }
4683 }
4684
4685 @override
4686 EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node , EvaluationResultImpl rightOperand) => rightOperand.notEqualValid(typeProvider, node, this);
4687
4688 @override
4689 EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node) {
4690 try {
4691 return _valueOf(value.performToString(typeProvider));
4692 } on EvaluationException catch (exception) {
4693 return _error(node, exception.errorCode);
4694 }
4695 }
4696
4697 @override
4698 EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand) => rightOperand.remainderValid(typeProvide r, node, this);
4699
4700 @override
4701 EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression nod e, EvaluationResultImpl rightOperand) => rightOperand.shiftLeftValid(typeProvide r, node, this);
4702
4703 @override
4704 EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression no de, EvaluationResultImpl rightOperand) => rightOperand.shiftRightValid(typeProvi der, node, this);
4705
4706 @override
4707 EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, E valuationResultImpl rightOperand) => rightOperand.timesValid(typeProvider, node, this);
4708
4709 @override
4710 String toString() {
4711 if (value == null) {
4712 return "null";
4713 }
4714 return value.toString();
4715 }
4716
4717 @override
4718 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand ) => leftOperand;
4719
4720 @override
4721 EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand) {
4722 try {
4723 return _valueOf(leftOperand.value.add(typeProvider, value));
4724 } on EvaluationException catch (exception) {
4725 return _error(node, exception.errorCode);
4726 }
4727 }
4728
4729 @override
4730 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan d) => leftOperand;
4731
4732 @override
4733 EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand) {
4734 try {
4735 return _valueOf(leftOperand.value.bitAnd(typeProvider, value));
4736 } on EvaluationException catch (exception) {
4737 return _error(node, exception.errorCode);
4738 }
4739 }
4740
4741 @override
4742 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand ) => leftOperand;
4743
4744 @override
4745 EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand) {
4746 try {
4747 return _valueOf(leftOperand.value.bitOr(typeProvider, value));
4748 } on EvaluationException catch (exception) {
4749 return _error(node, exception.errorCode);
4750 }
4751 }
4752
4753 @override
4754 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan d) => leftOperand;
4755
4756 @override
4757 EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand) {
4758 try {
4759 return _valueOf(leftOperand.value.bitXor(typeProvider, value));
4760 } on EvaluationException catch (exception) {
4761 return _error(node, exception.errorCode);
4762 }
4763 }
4764
4765 @override
4766 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand ) => leftOperand;
4767
4768 @override
4769 EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression no de, ValidResult leftOperand) {
4770 try {
4771 return _valueOf(leftOperand.value.concatenate(typeProvider, value));
4772 } on EvaluationException catch (exception) {
4773 return _error(node, exception.errorCode);
4774 }
4775 }
4776
4777 @override
4778 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan d) => leftOperand;
4779
4780 @override
4781 EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression n ode, ValidResult leftOperand) {
4782 try {
4783 return _valueOf(leftOperand.value.divide(typeProvider, value));
4784 } on EvaluationException catch (exception) {
4785 return _error(node, exception.errorCode);
4786 }
4787 }
4788
4789 @override
4790 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand) => leftOperand;
4791
4792 @override
4793 EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression nod e, ValidResult leftOperand) {
4794 try {
4795 return _valueOf(leftOperand.value.equalEqual(typeProvider, value));
4796 } on EvaluationException catch (exception) {
4797 return _error(node, exception.errorCode);
4798 }
4799 }
4800
4801 @override
4802 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO perand) => leftOperand;
4803
4804 @override
4805 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul t leftOperand) => leftOperand;
4806
4807 @override
4808 EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, Binary Expression node, ValidResult leftOperand) {
4809 try {
4810 return _valueOf(leftOperand.value.greaterThanOrEqual(typeProvider, value)) ;
4811 } on EvaluationException catch (exception) {
4812 return _error(node, exception.errorCode);
4813 }
4814 }
4815
4816 @override
4817 EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpress ion node, ValidResult leftOperand) {
4818 try {
4819 return _valueOf(leftOperand.value.greaterThan(typeProvider, value));
4820 } on EvaluationException catch (exception) {
4821 return _error(node, exception.errorCode);
4822 }
4823 }
4824
4825 @override
4826 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef tOperand) => leftOperand;
4827
4828 @override
4829 EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpre ssion node, ValidResult leftOperand) {
4830 try {
4831 return _valueOf(leftOperand.value.integerDivide(typeProvider, value));
4832 } on EvaluationException catch (exception) {
4833 return _error(node, exception.errorCode);
4834 }
4835 }
4836
4837 @override
4838 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper and) => leftOperand;
4839
4840 @override
4841 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l eftOperand) => leftOperand;
4842
4843 @override
4844 EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExp ression node, ValidResult leftOperand) {
4845 try {
4846 return _valueOf(leftOperand.value.lessThanOrEqual(typeProvider, value));
4847 } on EvaluationException catch (exception) {
4848 return _error(node, exception.errorCode);
4849 }
4850 }
4851
4852 @override
4853 EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
4854 try {
4855 return _valueOf(leftOperand.value.lessThan(typeProvider, value));
4856 } on EvaluationException catch (exception) {
4857 return _error(node, exception.errorCode);
4858 }
4859 }
4860
4861 @override
4862 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp erand) => leftOperand;
4863
4864 @override
4865 EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpressi on node, ValidResult leftOperand) {
4866 try {
4867 return _valueOf(leftOperand.value.logicalAnd(typeProvider, value));
4868 } on EvaluationException catch (exception) {
4869 return _error(node, exception.errorCode);
4870 }
4871 }
4872
4873 @override
4874 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe rand) => leftOperand;
4875
4876 @override
4877 EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand) {
4878 try {
4879 return _valueOf(leftOperand.value.logicalOr(typeProvider, value));
4880 } on EvaluationException catch (exception) {
4881 return _error(node, exception.errorCode);
4882 }
4883 }
4884
4885 @override
4886 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand ) => leftOperand;
4887
4888 @override
4889 EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand) {
4890 try {
4891 return _valueOf(leftOperand.value.minus(typeProvider, value));
4892 } on EvaluationException catch (exception) {
4893 return _error(node, exception.errorCode);
4894 }
4895 }
4896
4897 @override
4898 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper and) => leftOperand;
4899
4900 @override
4901 EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression node, ValidResult leftOperand) {
4902 try {
4903 return _valueOf(leftOperand.value.notEqual(typeProvider, value));
4904 } on EvaluationException catch (exception) {
4905 return _error(node, exception.errorCode);
4906 }
4907 }
4908
4909 @override
4910 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe rand) => leftOperand;
4911
4912 @override
4913 EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand) {
4914 try {
4915 return _valueOf(leftOperand.value.remainder(typeProvider, value));
4916 } on EvaluationException catch (exception) {
4917 return _error(node, exception.errorCode);
4918 }
4919 }
4920
4921 @override
4922 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe rand) => leftOperand;
4923
4924 @override
4925 EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpressio n node, ValidResult leftOperand) {
4926 try {
4927 return _valueOf(leftOperand.value.shiftLeft(typeProvider, value));
4928 } on EvaluationException catch (exception) {
4929 return _error(node, exception.errorCode);
4930 }
4931 }
4932
4933 @override
4934 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp erand) => leftOperand;
4935
4936 @override
4937 EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpressi on node, ValidResult leftOperand) {
4938 try {
4939 return _valueOf(leftOperand.value.shiftRight(typeProvider, value));
4940 } on EvaluationException catch (exception) {
4941 return _error(node, exception.errorCode);
4942 }
4943 }
4944
4945 @override
4946 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand ) => leftOperand;
4947
4948 @override
4949 EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression no de, ValidResult leftOperand) {
4950 try {
4951 return _valueOf(leftOperand.value.times(typeProvider, value));
4952 } on EvaluationException catch (exception) {
4953 return _error(node, exception.errorCode);
4954 }
4955 }
4956
4957 /**
4958 * Return a result object representing an error associated with the given node .
4959 *
4960 * @param node the AST node associated with the error
4961 * @param code the error code indicating the nature of the error
4962 * @return a result object representing an error associated with the given nod e
4963 */
4964 ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node, code);
4965
4966 /**
4967 * Return a result object representing the given value.
4968 *
4969 * @param value the value to be represented as a result object
4970 * @return a result object representing the given value
4971 */
4972 ValidResult _valueOf(DartObjectImpl value) => new ValidResult(value);
4973 }
OLDNEW
« no previous file with comments | « observatory_pub_packages/analyzer/src/generated/ast.dart ('k') | observatory_pub_packages/analyzer/src/generated/element.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698