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

Side by Side Diff: pkg/analyzer/lib/src/dart/constant/value.dart

Issue 1816923002: Move constant implementation out of generated (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
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 /**
6 * The implementation of the class [DartObject].
7 */
8 library analyzer.src.dart.constant.value;
9
10 import 'dart:collection';
11
12 import 'package:analyzer/dart/constant/value.dart';
13 import 'package:analyzer/dart/element/element.dart';
14 import 'package:analyzer/dart/element/type.dart';
15 import 'package:analyzer/src/generated/error.dart';
16 import 'package:analyzer/src/generated/java_core.dart';
17 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
18 import 'package:analyzer/src/generated/utilities_general.dart';
19
20 /**
21 * The state of an object representing a boolean value.
22 */
23 class BoolState extends InstanceState {
24 /**
25 * An instance representing the boolean value 'false'.
26 */
27 static BoolState FALSE_STATE = new BoolState(false);
28
29 /**
30 * An instance representing the boolean value 'true'.
31 */
32 static BoolState TRUE_STATE = new BoolState(true);
33
34 /**
35 * A state that can be used to represent a boolean whose value is not known.
36 */
37 static BoolState UNKNOWN_VALUE = new BoolState(null);
38
39 /**
40 * The value of this instance.
41 */
42 final bool value;
43
44 /**
45 * Initialize a newly created state to represent the given [value].
46 */
47 BoolState(this.value);
48
49 @override
50 int get hashCode => value == null ? 0 : (value ? 2 : 3);
51
52 @override
53 bool get isBool => true;
54
55 @override
56 bool get isBoolNumStringOrNull => true;
57
58 @override
59 bool get isUnknown => value == null;
60
61 @override
62 String get typeName => "bool";
63
64 @override
65 bool operator ==(Object object) =>
66 object is BoolState && identical(value, object.value);
67
68 @override
69 BoolState convertToBool() => this;
70
71 @override
72 StringState convertToString() {
73 if (value == null) {
74 return StringState.UNKNOWN_VALUE;
75 }
76 return new StringState(value ? "true" : "false");
77 }
78
79 @override
80 BoolState equalEqual(InstanceState rightOperand) {
81 assertBoolNumStringOrNull(rightOperand);
82 return isIdentical(rightOperand);
83 }
84
85 @override
86 BoolState isIdentical(InstanceState rightOperand) {
87 if (value == null) {
88 return UNKNOWN_VALUE;
89 }
90 if (rightOperand is BoolState) {
91 bool rightValue = rightOperand.value;
92 if (rightValue == null) {
93 return UNKNOWN_VALUE;
94 }
95 return BoolState.from(identical(value, rightValue));
96 } else if (rightOperand is DynamicState) {
97 return UNKNOWN_VALUE;
98 }
99 return FALSE_STATE;
100 }
101
102 @override
103 BoolState logicalAnd(InstanceState rightOperand) {
104 assertBool(rightOperand);
105 if (value == null) {
106 return UNKNOWN_VALUE;
107 }
108 return value ? rightOperand.convertToBool() : FALSE_STATE;
109 }
110
111 @override
112 BoolState logicalNot() {
113 if (value == null) {
114 return UNKNOWN_VALUE;
115 }
116 return value ? FALSE_STATE : TRUE_STATE;
117 }
118
119 @override
120 BoolState logicalOr(InstanceState rightOperand) {
121 assertBool(rightOperand);
122 if (value == null) {
123 return UNKNOWN_VALUE;
124 }
125 return value ? TRUE_STATE : rightOperand.convertToBool();
126 }
127
128 @override
129 String toString() => value == null ? "-unknown-" : (value ? "true" : "false");
130
131 /**
132 * Return the boolean state representing the given boolean [value].
133 */
134 static BoolState from(bool value) =>
135 value ? BoolState.TRUE_STATE : BoolState.FALSE_STATE;
136 }
137
138 /**
139 * A representation of an instance of a Dart class.
140 */
141 class DartObjectImpl implements DartObject {
142 /**
143 * An empty list of objects.
144 */
145 static const List<DartObjectImpl> EMPTY_LIST = const <DartObjectImpl>[];
146
147 /**
148 * The run-time type of this object.
149 */
150 @override
151 final ParameterizedType type;
152
153 /**
154 * The state of the object.
155 */
156 final InstanceState _state;
157
158 /**
159 * Initialize a newly created object to have the given [type] and [_state].
160 */
161 DartObjectImpl(this.type, this._state);
162
163 /**
164 * Create an object to represent an unknown value.
165 */
166 factory DartObjectImpl.validWithUnknownValue(InterfaceType type) {
167 if (type.element.library.isDartCore) {
168 String typeName = type.name;
169 if (typeName == "bool") {
170 return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
171 } else if (typeName == "double") {
172 return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
173 } else if (typeName == "int") {
174 return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
175 } else if (typeName == "String") {
176 return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
177 }
178 }
179 return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
180 }
181
182 HashMap<String, DartObjectImpl> get fields => _state.fields;
183
184 @override
185 int get hashCode => JenkinsSmiHash.hash2(type.hashCode, _state.hashCode);
186
187 @override
188 bool get hasKnownValue => !_state.isUnknown;
189
190 /**
191 * Return `true` if this object represents an object whose type is 'bool'.
192 */
193 bool get isBool => _state.isBool;
194
195 /**
196 * Return `true` if this object represents an object whose type is either
197 * 'bool', 'num', 'String', or 'Null'.
198 */
199 bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
200
201 @override
202 bool get isNull => _state is NullState;
203
204 /**
205 * Return `true` if this object represents an unknown value.
206 */
207 bool get isUnknown => _state.isUnknown;
208
209 /**
210 * Return `true` if this object represents an instance of a user-defined
211 * class.
212 */
213 bool get isUserDefinedObject => _state is GenericState;
214
215 @override
216 bool operator ==(Object object) {
217 if (object is! DartObjectImpl) {
218 return false;
219 }
220 DartObjectImpl dartObject = object as DartObjectImpl;
221 return type == dartObject.type && _state == dartObject._state;
222 }
223
224 /**
225 * Return the result of invoking the '+' operator on this object with the
226 * given [rightOperand]. The [typeProvider] is the type provider used to find
227 * known types.
228 *
229 * Throws an [EvaluationException] if the operator is not appropriate for an
230 * object of this kind.
231 */
232 DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) {
233 InstanceState result = _state.add(rightOperand._state);
234 if (result is IntState) {
235 return new DartObjectImpl(typeProvider.intType, result);
236 } else if (result is DoubleState) {
237 return new DartObjectImpl(typeProvider.doubleType, result);
238 } else if (result is NumState) {
239 return new DartObjectImpl(typeProvider.numType, result);
240 } else if (result is StringState) {
241 return new DartObjectImpl(typeProvider.stringType, result);
242 }
243 // We should never get here.
244 throw new IllegalStateException("add returned a ${result.runtimeType}");
245 }
246
247 /**
248 * Return the result of invoking the '&' operator on this object with the
249 * [rightOperand]. The [typeProvider] is the type provider used to find known
250 * types.
251 *
252 * Throws an [EvaluationException] if the operator is not appropriate for an
253 * object of this kind.
254 */
255 DartObjectImpl bitAnd(
256 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
257 new DartObjectImpl(
258 typeProvider.intType, _state.bitAnd(rightOperand._state));
259
260 /**
261 * Return the result of invoking the '~' operator on this object. The
262 * [typeProvider] is the type provider used to find known types.
263 *
264 * Throws an [EvaluationException] if the operator is not appropriate for an
265 * object of this kind.
266 */
267 DartObjectImpl bitNot(TypeProvider typeProvider) =>
268 new DartObjectImpl(typeProvider.intType, _state.bitNot());
269
270 /**
271 * Return the result of invoking the '|' operator on this object with the
272 * [rightOperand]. The [typeProvider] is the type provider used to find known
273 * types.
274 *
275 * Throws an [EvaluationException] if the operator is not appropriate for an
276 * object of this kind.
277 */
278 DartObjectImpl bitOr(
279 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
280 new DartObjectImpl(
281 typeProvider.intType, _state.bitOr(rightOperand._state));
282
283 /**
284 * Return the result of invoking the '^' operator on this object with the
285 * [rightOperand]. The [typeProvider] is the type provider used to find known
286 * types.
287 *
288 * Throws an [EvaluationException] if the operator is not appropriate for an
289 * object of this kind.
290 */
291 DartObjectImpl bitXor(
292 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
293 new DartObjectImpl(
294 typeProvider.intType, _state.bitXor(rightOperand._state));
295
296 /**
297 * Return the result of invoking the ' ' operator on this object with the
298 * [rightOperand]. The [typeProvider] is the type provider used to find known
299 * types.
300 *
301 * Throws an [EvaluationException] if the operator is not appropriate for an
302 * object of this kind.
303 */
304 DartObjectImpl concatenate(
305 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
306 new DartObjectImpl(
307 typeProvider.stringType, _state.concatenate(rightOperand._state));
308
309 /**
310 * Return the result of applying boolean conversion to this object. The
311 * [typeProvider] is the type provider used to find known types.
312 *
313 * Throws an [EvaluationException] if the operator is not appropriate for an
314 * object of this kind.
315 */
316 DartObjectImpl convertToBool(TypeProvider typeProvider) {
317 InterfaceType boolType = typeProvider.boolType;
318 if (identical(type, boolType)) {
319 return this;
320 }
321 return new DartObjectImpl(boolType, _state.convertToBool());
322 }
323
324 /**
325 * Return the result of invoking the '/' operator on this object with the
326 * [rightOperand]. The [typeProvider] is the type provider used to find known
327 * types.
328 *
329 * Throws an [EvaluationException] if the operator is not appropriate for
330 * an object of this kind.
331 */
332 DartObjectImpl divide(
333 TypeProvider typeProvider, DartObjectImpl rightOperand) {
334 InstanceState result = _state.divide(rightOperand._state);
335 if (result is IntState) {
336 return new DartObjectImpl(typeProvider.intType, result);
337 } else if (result is DoubleState) {
338 return new DartObjectImpl(typeProvider.doubleType, result);
339 } else if (result is NumState) {
340 return new DartObjectImpl(typeProvider.numType, result);
341 }
342 // We should never get here.
343 throw new IllegalStateException("divide returned a ${result.runtimeType}");
344 }
345
346 /**
347 * Return the result of invoking the '==' operator on this object with the
348 * [rightOperand]. The [typeProvider] is the type provider used to find known
349 * types.
350 *
351 * Throws an [EvaluationException] if the operator is not appropriate for an
352 * object of this kind.
353 */
354 DartObjectImpl equalEqual(
355 TypeProvider typeProvider, DartObjectImpl rightOperand) {
356 if (type != rightOperand.type) {
357 String typeName = type.name;
358 if (!(typeName == "bool" ||
359 typeName == "double" ||
360 typeName == "int" ||
361 typeName == "num" ||
362 typeName == "String" ||
363 typeName == "Null" ||
364 type.isDynamic)) {
365 throw new EvaluationException(
366 CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
367 }
368 }
369 return new DartObjectImpl(
370 typeProvider.boolType, _state.equalEqual(rightOperand._state));
371 }
372
373 @override
374 DartObject getField(String name) {
375 if (_state is GenericState) {
376 return (_state as GenericState).fields[name];
377 }
378 return null;
379 }
380
381 /**
382 * Return the result of invoking the '&gt;' operator on this object with the
383 * [rightOperand]. The [typeProvider] is the type provider used to find known
384 * types.
385 *
386 * Throws an [EvaluationException] if the operator is not appropriate for an
387 * object of this kind.
388 */
389 DartObjectImpl greaterThan(
390 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
391 new DartObjectImpl(
392 typeProvider.boolType, _state.greaterThan(rightOperand._state));
393
394 /**
395 * Return the result of invoking the '&gt;=' operator on this object with the
396 * [rightOperand]. The [typeProvider] is the type provider used to find known
397 * types.
398 *
399 * Throws an [EvaluationException] if the operator is not appropriate for an
400 * object of this kind.
401 */
402 DartObjectImpl greaterThanOrEqual(
403 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
404 new DartObjectImpl(typeProvider.boolType,
405 _state.greaterThanOrEqual(rightOperand._state));
406
407 /**
408 * Return the result of invoking the '~/' operator on this object with the
409 * [rightOperand]. The [typeProvider] is the type provider used to find known
410 * types.
411 *
412 * Throws an [EvaluationException] if the operator is not appropriate for an
413 * object of this kind.
414 */
415 DartObjectImpl integerDivide(
416 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
417 new DartObjectImpl(
418 typeProvider.intType, _state.integerDivide(rightOperand._state));
419
420 /**
421 * Return the result of invoking the identical function on this object with
422 * the [rightOperand]. The [typeProvider] is the type provider used to find
423 * known types.
424 */
425 DartObjectImpl isIdentical(
426 TypeProvider typeProvider, DartObjectImpl rightOperand) {
427 return new DartObjectImpl(
428 typeProvider.boolType, _state.isIdentical(rightOperand._state));
429 }
430
431 /**
432 * Return the result of invoking the '&lt;' operator on this object with the
433 * [rightOperand]. The [typeProvider] is the type provider used to find known
434 * types.
435 *
436 * Throws an [EvaluationException] if the operator is not appropriate for an
437 * object of this kind.
438 */
439 DartObjectImpl lessThan(
440 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
441 new DartObjectImpl(
442 typeProvider.boolType, _state.lessThan(rightOperand._state));
443
444 /**
445 * Return the result of invoking the '&lt;=' operator on this object with the
446 * [rightOperand]. The [typeProvider] is the type provider used to find known
447 * types.
448 *
449 * Throws an [EvaluationException] if the operator is not appropriate for an
450 * object of this kind.
451 */
452 DartObjectImpl lessThanOrEqual(
453 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
454 new DartObjectImpl(
455 typeProvider.boolType, _state.lessThanOrEqual(rightOperand._state));
456
457 /**
458 * Return the result of invoking the '&&' operator on this object with the
459 * [rightOperand]. The [typeProvider] is the type provider used to find known
460 * types.
461 *
462 * Throws an [EvaluationException] if the operator is not appropriate for an
463 * object of this kind.
464 */
465 DartObjectImpl logicalAnd(
466 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
467 new DartObjectImpl(
468 typeProvider.boolType, _state.logicalAnd(rightOperand._state));
469
470 /**
471 * Return the result of invoking the '!' operator on this object. The
472 * [typeProvider] is the type provider used to find known types.
473 *
474 * Throws an [EvaluationException] if the operator is not appropriate for an
475 * object of this kind.
476 */
477 DartObjectImpl logicalNot(TypeProvider typeProvider) =>
478 new DartObjectImpl(typeProvider.boolType, _state.logicalNot());
479
480 /**
481 * Return the result of invoking the '||' operator on this object with the
482 * [rightOperand]. The [typeProvider] is the type provider used to find known
483 * types.
484 *
485 * Throws an [EvaluationException] if the operator is not appropriate for an
486 * object of this kind.
487 */
488 DartObjectImpl logicalOr(
489 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
490 new DartObjectImpl(
491 typeProvider.boolType, _state.logicalOr(rightOperand._state));
492
493 /**
494 * Return the result of invoking the '-' operator on this object with the
495 * [rightOperand]. The [typeProvider] is the type provider used to find known
496 * types.
497 *
498 * Throws an [EvaluationException] if the operator is not appropriate for an
499 * object of this kind.
500 */
501 DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) {
502 InstanceState result = _state.minus(rightOperand._state);
503 if (result is IntState) {
504 return new DartObjectImpl(typeProvider.intType, result);
505 } else if (result is DoubleState) {
506 return new DartObjectImpl(typeProvider.doubleType, result);
507 } else if (result is NumState) {
508 return new DartObjectImpl(typeProvider.numType, result);
509 }
510 // We should never get here.
511 throw new IllegalStateException("minus returned a ${result.runtimeType}");
512 }
513
514 /**
515 * Return the result of invoking the '-' operator on this object. The
516 * [typeProvider] is the type provider used to find known types.
517 *
518 * Throws an [EvaluationException] if the operator is not appropriate for an
519 * object of this kind.
520 */
521 DartObjectImpl negated(TypeProvider typeProvider) {
522 InstanceState result = _state.negated();
523 if (result is IntState) {
524 return new DartObjectImpl(typeProvider.intType, result);
525 } else if (result is DoubleState) {
526 return new DartObjectImpl(typeProvider.doubleType, result);
527 } else if (result is NumState) {
528 return new DartObjectImpl(typeProvider.numType, result);
529 }
530 // We should never get here.
531 throw new IllegalStateException("negated returned a ${result.runtimeType}");
532 }
533
534 /**
535 * Return the result of invoking the '!=' operator on this object with the
536 * [rightOperand]. The [typeProvider] is the type provider used to find known
537 * types.
538 *
539 * Throws an [EvaluationException] if the operator is not appropriate for an
540 * object of this kind.
541 */
542 DartObjectImpl notEqual(
543 TypeProvider typeProvider, DartObjectImpl rightOperand) {
544 if (type != rightOperand.type) {
545 String typeName = type.name;
546 if (typeName != "bool" &&
547 typeName != "double" &&
548 typeName != "int" &&
549 typeName != "num" &&
550 typeName != "String") {
551 return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
552 }
553 }
554 return new DartObjectImpl(typeProvider.boolType,
555 _state.equalEqual(rightOperand._state).logicalNot());
556 }
557
558 /**
559 * Return the result of converting this object to a 'String'. The
560 * [typeProvider] is the type provider used to find known types.
561 *
562 * Throws an [EvaluationException] if the object cannot be converted to a
563 * 'String'.
564 */
565 DartObjectImpl performToString(TypeProvider typeProvider) {
566 InterfaceType stringType = typeProvider.stringType;
567 if (identical(type, stringType)) {
568 return this;
569 }
570 return new DartObjectImpl(stringType, _state.convertToString());
571 }
572
573 /**
574 * Return the result of invoking the '%' operator on this object with the
575 * [rightOperand]. The [typeProvider] is the type provider used to find known
576 * types.
577 *
578 * Throws an [EvaluationException] if the operator is not appropriate for an
579 * object of this kind.
580 */
581 DartObjectImpl remainder(
582 TypeProvider typeProvider, DartObjectImpl rightOperand) {
583 InstanceState result = _state.remainder(rightOperand._state);
584 if (result is IntState) {
585 return new DartObjectImpl(typeProvider.intType, result);
586 } else if (result is DoubleState) {
587 return new DartObjectImpl(typeProvider.doubleType, result);
588 } else if (result is NumState) {
589 return new DartObjectImpl(typeProvider.numType, result);
590 }
591 // We should never get here.
592 throw new IllegalStateException(
593 "remainder returned a ${result.runtimeType}");
594 }
595
596 /**
597 * Return the result of invoking the '&lt;&lt;' operator on this object with
598 * the [rightOperand]. The [typeProvider] is the type provider used to find
599 * known types.
600 *
601 * Throws an [EvaluationException] if the operator is not appropriate for an
602 * object of this kind.
603 */
604 DartObjectImpl shiftLeft(
605 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
606 new DartObjectImpl(
607 typeProvider.intType, _state.shiftLeft(rightOperand._state));
608
609 /**
610 * Return the result of invoking the '&gt;&gt;' operator on this object with
611 * the [rightOperand]. The [typeProvider] is the type provider used to find
612 * known types.
613 *
614 * Throws an [EvaluationException] if the operator is not appropriate for an
615 * object of this kind.
616 */
617 DartObjectImpl shiftRight(
618 TypeProvider typeProvider, DartObjectImpl rightOperand) =>
619 new DartObjectImpl(
620 typeProvider.intType, _state.shiftRight(rightOperand._state));
621
622 /**
623 * Return the result of invoking the 'length' getter on this object. The
624 * [typeProvider] is the type provider used to find known types.
625 *
626 * Throws an [EvaluationException] if the operator is not appropriate for an
627 * object of this kind.
628 */
629 DartObjectImpl stringLength(TypeProvider typeProvider) =>
630 new DartObjectImpl(typeProvider.intType, _state.stringLength());
631
632 /**
633 * Return the result of invoking the '*' operator on this object with the
634 * [rightOperand]. The [typeProvider] is the type provider used to find known
635 * types.
636 *
637 * Throws an [EvaluationException] if the operator is not appropriate for an
638 * object of this kind.
639 */
640 DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) {
641 InstanceState result = _state.times(rightOperand._state);
642 if (result is IntState) {
643 return new DartObjectImpl(typeProvider.intType, result);
644 } else if (result is DoubleState) {
645 return new DartObjectImpl(typeProvider.doubleType, result);
646 } else if (result is NumState) {
647 return new DartObjectImpl(typeProvider.numType, result);
648 }
649 // We should never get here.
650 throw new IllegalStateException("times returned a ${result.runtimeType}");
651 }
652
653 @override
654 bool toBoolValue() {
655 if (_state is BoolState) {
656 return (_state as BoolState).value;
657 }
658 return null;
659 }
660
661 @override
662 double toDoubleValue() {
663 if (_state is DoubleState) {
664 return (_state as DoubleState).value;
665 }
666 return null;
667 }
668
669 @override
670 int toIntValue() {
671 if (_state is IntState) {
672 return (_state as IntState).value;
673 }
674 return null;
675 }
676
677 @override
678 List<DartObject> toListValue() {
679 if (_state is ListState) {
680 return (_state as ListState)._elements;
681 }
682 return null;
683 }
684
685 @override
686 Map<DartObject, DartObject> toMapValue() {
687 if (_state is MapState) {
688 return (_state as MapState)._entries;
689 }
690 return null;
691 }
692
693 @override
694 String toString() => "${type.displayName} ($_state)";
695
696 @override
697 String toStringValue() {
698 if (_state is StringState) {
699 return (_state as StringState).value;
700 }
701 return null;
702 }
703
704 @override
705 String toSymbolValue() {
706 if (_state is SymbolState) {
707 return (_state as SymbolState).value;
708 }
709 return null;
710 }
711
712 @override
713 DartType toTypeValue() {
714 if (_state is TypeState) {
715 Element element = (_state as TypeState)._element;
716 if (element is TypeDefiningElement) {
717 return element.type;
718 }
719 }
720 return null;
721 }
722 }
723
724 /**
725 * The state of an object representing a double.
726 */
727 class DoubleState extends NumState {
728 /**
729 * A state that can be used to represent a double whose value is not known.
730 */
731 static DoubleState UNKNOWN_VALUE = new DoubleState(null);
732
733 /**
734 * The value of this instance.
735 */
736 final double value;
737
738 /**
739 * Initialize a newly created state to represent a double with the given
740 * [value].
741 */
742 DoubleState(this.value);
743
744 @override
745 int get hashCode => value == null ? 0 : value.hashCode;
746
747 @override
748 bool get isBoolNumStringOrNull => true;
749
750 @override
751 bool get isUnknown => value == null;
752
753 @override
754 String get typeName => "double";
755
756 @override
757 bool operator ==(Object object) =>
758 object is DoubleState && (value == object.value);
759
760 @override
761 NumState add(InstanceState rightOperand) {
762 assertNumOrNull(rightOperand);
763 if (value == null) {
764 return UNKNOWN_VALUE;
765 }
766 if (rightOperand is IntState) {
767 int rightValue = rightOperand.value;
768 if (rightValue == null) {
769 return UNKNOWN_VALUE;
770 }
771 return new DoubleState(value + rightValue.toDouble());
772 } else if (rightOperand is DoubleState) {
773 double rightValue = rightOperand.value;
774 if (rightValue == null) {
775 return UNKNOWN_VALUE;
776 }
777 return new DoubleState(value + rightValue);
778 } else if (rightOperand is DynamicState || rightOperand is NumState) {
779 return UNKNOWN_VALUE;
780 }
781 throw new EvaluationException(
782 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
783 }
784
785 @override
786 StringState convertToString() {
787 if (value == null) {
788 return StringState.UNKNOWN_VALUE;
789 }
790 return new StringState(value.toString());
791 }
792
793 @override
794 NumState divide(InstanceState rightOperand) {
795 assertNumOrNull(rightOperand);
796 if (value == null) {
797 return UNKNOWN_VALUE;
798 }
799 if (rightOperand is IntState) {
800 int rightValue = rightOperand.value;
801 if (rightValue == null) {
802 return UNKNOWN_VALUE;
803 }
804 return new DoubleState(value / rightValue.toDouble());
805 } else if (rightOperand is DoubleState) {
806 double rightValue = rightOperand.value;
807 if (rightValue == null) {
808 return UNKNOWN_VALUE;
809 }
810 return new DoubleState(value / rightValue);
811 } else if (rightOperand is DynamicState || rightOperand is NumState) {
812 return UNKNOWN_VALUE;
813 }
814 throw new EvaluationException(
815 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
816 }
817
818 @override
819 BoolState equalEqual(InstanceState rightOperand) {
820 assertBoolNumStringOrNull(rightOperand);
821 return isIdentical(rightOperand);
822 }
823
824 @override
825 BoolState greaterThan(InstanceState rightOperand) {
826 assertNumOrNull(rightOperand);
827 if (value == null) {
828 return BoolState.UNKNOWN_VALUE;
829 }
830 if (rightOperand is IntState) {
831 int rightValue = rightOperand.value;
832 if (rightValue == null) {
833 return BoolState.UNKNOWN_VALUE;
834 }
835 return BoolState.from(value > rightValue.toDouble());
836 } else if (rightOperand is DoubleState) {
837 double rightValue = rightOperand.value;
838 if (rightValue == null) {
839 return BoolState.UNKNOWN_VALUE;
840 }
841 return BoolState.from(value > rightValue);
842 } else if (rightOperand is DynamicState || rightOperand is NumState) {
843 return BoolState.UNKNOWN_VALUE;
844 }
845 throw new EvaluationException(
846 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
847 }
848
849 @override
850 BoolState greaterThanOrEqual(InstanceState rightOperand) {
851 assertNumOrNull(rightOperand);
852 if (value == null) {
853 return BoolState.UNKNOWN_VALUE;
854 }
855 if (rightOperand is IntState) {
856 int rightValue = rightOperand.value;
857 if (rightValue == null) {
858 return BoolState.UNKNOWN_VALUE;
859 }
860 return BoolState.from(value >= rightValue.toDouble());
861 } else if (rightOperand is DoubleState) {
862 double rightValue = rightOperand.value;
863 if (rightValue == null) {
864 return BoolState.UNKNOWN_VALUE;
865 }
866 return BoolState.from(value >= rightValue);
867 } else if (rightOperand is DynamicState || rightOperand is NumState) {
868 return BoolState.UNKNOWN_VALUE;
869 }
870 throw new EvaluationException(
871 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
872 }
873
874 @override
875 IntState integerDivide(InstanceState rightOperand) {
876 assertNumOrNull(rightOperand);
877 if (value == null) {
878 return IntState.UNKNOWN_VALUE;
879 }
880 if (rightOperand is IntState) {
881 int rightValue = rightOperand.value;
882 if (rightValue == null) {
883 return IntState.UNKNOWN_VALUE;
884 }
885 double result = value / rightValue.toDouble();
886 return new IntState(result.toInt());
887 } else if (rightOperand is DoubleState) {
888 double rightValue = rightOperand.value;
889 if (rightValue == null) {
890 return IntState.UNKNOWN_VALUE;
891 }
892 double result = value / rightValue;
893 return new IntState(result.toInt());
894 } else if (rightOperand is DynamicState || rightOperand is NumState) {
895 return IntState.UNKNOWN_VALUE;
896 }
897 throw new EvaluationException(
898 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
899 }
900
901 @override
902 BoolState isIdentical(InstanceState rightOperand) {
903 if (value == null) {
904 return BoolState.UNKNOWN_VALUE;
905 }
906 if (rightOperand is DoubleState) {
907 double rightValue = rightOperand.value;
908 if (rightValue == null) {
909 return BoolState.UNKNOWN_VALUE;
910 }
911 return BoolState.from(value == rightValue);
912 } else if (rightOperand is IntState) {
913 int rightValue = rightOperand.value;
914 if (rightValue == null) {
915 return BoolState.UNKNOWN_VALUE;
916 }
917 return BoolState.from(value == rightValue.toDouble());
918 } else if (rightOperand is DynamicState || rightOperand is NumState) {
919 return BoolState.UNKNOWN_VALUE;
920 }
921 return BoolState.FALSE_STATE;
922 }
923
924 @override
925 BoolState lessThan(InstanceState rightOperand) {
926 assertNumOrNull(rightOperand);
927 if (value == null) {
928 return BoolState.UNKNOWN_VALUE;
929 }
930 if (rightOperand is IntState) {
931 int rightValue = rightOperand.value;
932 if (rightValue == null) {
933 return BoolState.UNKNOWN_VALUE;
934 }
935 return BoolState.from(value < rightValue.toDouble());
936 } else if (rightOperand is DoubleState) {
937 double rightValue = rightOperand.value;
938 if (rightValue == null) {
939 return BoolState.UNKNOWN_VALUE;
940 }
941 return BoolState.from(value < rightValue);
942 } else if (rightOperand is DynamicState || rightOperand is NumState) {
943 return BoolState.UNKNOWN_VALUE;
944 }
945 throw new EvaluationException(
946 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
947 }
948
949 @override
950 BoolState lessThanOrEqual(InstanceState rightOperand) {
951 assertNumOrNull(rightOperand);
952 if (value == null) {
953 return BoolState.UNKNOWN_VALUE;
954 }
955 if (rightOperand is IntState) {
956 int rightValue = rightOperand.value;
957 if (rightValue == null) {
958 return BoolState.UNKNOWN_VALUE;
959 }
960 return BoolState.from(value <= rightValue.toDouble());
961 } else if (rightOperand is DoubleState) {
962 double rightValue = rightOperand.value;
963 if (rightValue == null) {
964 return BoolState.UNKNOWN_VALUE;
965 }
966 return BoolState.from(value <= rightValue);
967 } else if (rightOperand is DynamicState || rightOperand is NumState) {
968 return BoolState.UNKNOWN_VALUE;
969 }
970 throw new EvaluationException(
971 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
972 }
973
974 @override
975 NumState minus(InstanceState rightOperand) {
976 assertNumOrNull(rightOperand);
977 if (value == null) {
978 return UNKNOWN_VALUE;
979 }
980 if (rightOperand is IntState) {
981 int rightValue = rightOperand.value;
982 if (rightValue == null) {
983 return UNKNOWN_VALUE;
984 }
985 return new DoubleState(value - rightValue.toDouble());
986 } else if (rightOperand is DoubleState) {
987 double rightValue = rightOperand.value;
988 if (rightValue == null) {
989 return UNKNOWN_VALUE;
990 }
991 return new DoubleState(value - rightValue);
992 } else if (rightOperand is DynamicState || rightOperand is NumState) {
993 return UNKNOWN_VALUE;
994 }
995 throw new EvaluationException(
996 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
997 }
998
999 @override
1000 NumState negated() {
1001 if (value == null) {
1002 return UNKNOWN_VALUE;
1003 }
1004 return new DoubleState(-(value));
1005 }
1006
1007 @override
1008 NumState remainder(InstanceState rightOperand) {
1009 assertNumOrNull(rightOperand);
1010 if (value == null) {
1011 return UNKNOWN_VALUE;
1012 }
1013 if (rightOperand is IntState) {
1014 int rightValue = rightOperand.value;
1015 if (rightValue == null) {
1016 return UNKNOWN_VALUE;
1017 }
1018 return new DoubleState(value % rightValue.toDouble());
1019 } else if (rightOperand is DoubleState) {
1020 double rightValue = rightOperand.value;
1021 if (rightValue == null) {
1022 return UNKNOWN_VALUE;
1023 }
1024 return new DoubleState(value % rightValue);
1025 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1026 return UNKNOWN_VALUE;
1027 }
1028 throw new EvaluationException(
1029 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
1030 }
1031
1032 @override
1033 NumState times(InstanceState rightOperand) {
1034 assertNumOrNull(rightOperand);
1035 if (value == null) {
1036 return UNKNOWN_VALUE;
1037 }
1038 if (rightOperand is IntState) {
1039 int rightValue = rightOperand.value;
1040 if (rightValue == null) {
1041 return UNKNOWN_VALUE;
1042 }
1043 return new DoubleState(value * rightValue.toDouble());
1044 } else if (rightOperand is DoubleState) {
1045 double rightValue = rightOperand.value;
1046 if (rightValue == null) {
1047 return UNKNOWN_VALUE;
1048 }
1049 return new DoubleState(value * rightValue);
1050 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1051 return UNKNOWN_VALUE;
1052 }
1053 throw new EvaluationException(
1054 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
1055 }
1056
1057 @override
1058 String toString() => value == null ? "-unknown-" : value.toString();
1059 }
1060
1061 /**
1062 * The state of an object representing a Dart object for which there is no type
1063 * information.
1064 */
1065 class DynamicState extends InstanceState {
1066 /**
1067 * The unique instance of this class.
1068 */
1069 static DynamicState DYNAMIC_STATE = new DynamicState();
1070
1071 @override
1072 bool get isBool => true;
1073
1074 @override
1075 bool get isBoolNumStringOrNull => true;
1076
1077 @override
1078 String get typeName => "dynamic";
1079
1080 @override
1081 NumState add(InstanceState rightOperand) {
1082 assertNumOrNull(rightOperand);
1083 return _unknownNum(rightOperand);
1084 }
1085
1086 @override
1087 IntState bitAnd(InstanceState rightOperand) {
1088 assertIntOrNull(rightOperand);
1089 return IntState.UNKNOWN_VALUE;
1090 }
1091
1092 @override
1093 IntState bitNot() => IntState.UNKNOWN_VALUE;
1094
1095 @override
1096 IntState bitOr(InstanceState rightOperand) {
1097 assertIntOrNull(rightOperand);
1098 return IntState.UNKNOWN_VALUE;
1099 }
1100
1101 @override
1102 IntState bitXor(InstanceState rightOperand) {
1103 assertIntOrNull(rightOperand);
1104 return IntState.UNKNOWN_VALUE;
1105 }
1106
1107 @override
1108 StringState concatenate(InstanceState rightOperand) {
1109 assertString(rightOperand);
1110 return StringState.UNKNOWN_VALUE;
1111 }
1112
1113 @override
1114 BoolState convertToBool() => BoolState.UNKNOWN_VALUE;
1115
1116 @override
1117 StringState convertToString() => StringState.UNKNOWN_VALUE;
1118
1119 @override
1120 NumState divide(InstanceState rightOperand) {
1121 assertNumOrNull(rightOperand);
1122 return _unknownNum(rightOperand);
1123 }
1124
1125 @override
1126 BoolState equalEqual(InstanceState rightOperand) {
1127 assertBoolNumStringOrNull(rightOperand);
1128 return BoolState.UNKNOWN_VALUE;
1129 }
1130
1131 @override
1132 BoolState greaterThan(InstanceState rightOperand) {
1133 assertNumOrNull(rightOperand);
1134 return BoolState.UNKNOWN_VALUE;
1135 }
1136
1137 @override
1138 BoolState greaterThanOrEqual(InstanceState rightOperand) {
1139 assertNumOrNull(rightOperand);
1140 return BoolState.UNKNOWN_VALUE;
1141 }
1142
1143 @override
1144 IntState integerDivide(InstanceState rightOperand) {
1145 assertNumOrNull(rightOperand);
1146 return IntState.UNKNOWN_VALUE;
1147 }
1148
1149 @override
1150 BoolState isIdentical(InstanceState rightOperand) {
1151 return BoolState.UNKNOWN_VALUE;
1152 }
1153
1154 @override
1155 BoolState lessThan(InstanceState rightOperand) {
1156 assertNumOrNull(rightOperand);
1157 return BoolState.UNKNOWN_VALUE;
1158 }
1159
1160 @override
1161 BoolState lessThanOrEqual(InstanceState rightOperand) {
1162 assertNumOrNull(rightOperand);
1163 return BoolState.UNKNOWN_VALUE;
1164 }
1165
1166 @override
1167 BoolState logicalAnd(InstanceState rightOperand) {
1168 assertBool(rightOperand);
1169 return BoolState.UNKNOWN_VALUE;
1170 }
1171
1172 @override
1173 BoolState logicalNot() => BoolState.UNKNOWN_VALUE;
1174
1175 @override
1176 BoolState logicalOr(InstanceState rightOperand) {
1177 assertBool(rightOperand);
1178 return rightOperand.convertToBool();
1179 }
1180
1181 @override
1182 NumState minus(InstanceState rightOperand) {
1183 assertNumOrNull(rightOperand);
1184 return _unknownNum(rightOperand);
1185 }
1186
1187 @override
1188 NumState negated() => NumState.UNKNOWN_VALUE;
1189
1190 @override
1191 NumState remainder(InstanceState rightOperand) {
1192 assertNumOrNull(rightOperand);
1193 return _unknownNum(rightOperand);
1194 }
1195
1196 @override
1197 IntState shiftLeft(InstanceState rightOperand) {
1198 assertIntOrNull(rightOperand);
1199 return IntState.UNKNOWN_VALUE;
1200 }
1201
1202 @override
1203 IntState shiftRight(InstanceState rightOperand) {
1204 assertIntOrNull(rightOperand);
1205 return IntState.UNKNOWN_VALUE;
1206 }
1207
1208 @override
1209 NumState times(InstanceState rightOperand) {
1210 assertNumOrNull(rightOperand);
1211 return _unknownNum(rightOperand);
1212 }
1213
1214 /**
1215 * Return an object representing an unknown numeric value whose type is based
1216 * on the type of the [rightOperand].
1217 */
1218 NumState _unknownNum(InstanceState rightOperand) {
1219 if (rightOperand is IntState) {
1220 return IntState.UNKNOWN_VALUE;
1221 } else if (rightOperand is DoubleState) {
1222 return DoubleState.UNKNOWN_VALUE;
1223 }
1224 return NumState.UNKNOWN_VALUE;
1225 }
1226 }
1227
1228 /**
1229 * A run-time exception that would be thrown during the evaluation of Dart code.
1230 */
1231 class EvaluationException extends JavaException {
1232 /**
1233 * The error code associated with the exception.
1234 */
1235 final ErrorCode errorCode;
1236
1237 /**
1238 * Initialize a newly created exception to have the given [errorCode].
1239 */
1240 EvaluationException(this.errorCode);
1241 }
1242
1243 /**
1244 * The state of an object representing a function.
1245 */
1246 class FunctionState extends InstanceState {
1247 /**
1248 * The element representing the function being modeled.
1249 */
1250 final ExecutableElement _element;
1251
1252 /**
1253 * Initialize a newly created state to represent the function with the given
1254 * [element].
1255 */
1256 FunctionState(this._element);
1257
1258 @override
1259 int get hashCode => _element == null ? 0 : _element.hashCode;
1260
1261 @override
1262 String get typeName => "Function";
1263
1264 @override
1265 bool operator ==(Object object) =>
1266 object is FunctionState && (_element == object._element);
1267
1268 @override
1269 StringState convertToString() {
1270 if (_element == null) {
1271 return StringState.UNKNOWN_VALUE;
1272 }
1273 return new StringState(_element.name);
1274 }
1275
1276 @override
1277 BoolState equalEqual(InstanceState rightOperand) {
1278 return isIdentical(rightOperand);
1279 }
1280
1281 @override
1282 BoolState isIdentical(InstanceState rightOperand) {
1283 if (_element == null) {
1284 return BoolState.UNKNOWN_VALUE;
1285 }
1286 if (rightOperand is FunctionState) {
1287 ExecutableElement rightElement = rightOperand._element;
1288 if (rightElement == null) {
1289 return BoolState.UNKNOWN_VALUE;
1290 }
1291 return BoolState.from(_element == rightElement);
1292 } else if (rightOperand is DynamicState) {
1293 return BoolState.UNKNOWN_VALUE;
1294 }
1295 return BoolState.FALSE_STATE;
1296 }
1297
1298 @override
1299 String toString() => _element == null ? "-unknown-" : _element.name;
1300 }
1301
1302 /**
1303 * The state of an object representing a Dart object for which there is no more
1304 * specific state.
1305 */
1306 class GenericState extends InstanceState {
1307 /**
1308 * Pseudo-field that we use to represent fields in the superclass.
1309 */
1310 static String SUPERCLASS_FIELD = "(super)";
1311
1312 /**
1313 * A state that can be used to represent an object whose state is not known.
1314 */
1315 static GenericState UNKNOWN_VALUE =
1316 new GenericState(new HashMap<String, DartObjectImpl>());
1317
1318 /**
1319 * The values of the fields of this instance.
1320 */
1321 final HashMap<String, DartObjectImpl> _fieldMap;
1322
1323 /**
1324 * Initialize a newly created state to represent a newly created object. The
1325 * [fieldMap] contains the values of the fields of the instance.
1326 */
1327 GenericState(this._fieldMap);
1328
1329 @override
1330 HashMap<String, DartObjectImpl> get fields => _fieldMap;
1331
1332 @override
1333 int get hashCode {
1334 int hashCode = 0;
1335 for (DartObjectImpl value in _fieldMap.values) {
1336 hashCode += value.hashCode;
1337 }
1338 return hashCode;
1339 }
1340
1341 @override
1342 bool get isUnknown => identical(this, UNKNOWN_VALUE);
1343
1344 @override
1345 String get typeName => "user defined type";
1346
1347 @override
1348 bool operator ==(Object object) {
1349 if (object is! GenericState) {
1350 return false;
1351 }
1352 GenericState state = object as GenericState;
1353 HashSet<String> otherFields =
1354 new HashSet<String>.from(state._fieldMap.keys.toSet());
1355 for (String fieldName in _fieldMap.keys.toSet()) {
1356 if (_fieldMap[fieldName] != state._fieldMap[fieldName]) {
1357 return false;
1358 }
1359 otherFields.remove(fieldName);
1360 }
1361 for (String fieldName in otherFields) {
1362 if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
1363 return false;
1364 }
1365 }
1366 return true;
1367 }
1368
1369 @override
1370 StringState convertToString() => StringState.UNKNOWN_VALUE;
1371
1372 @override
1373 BoolState equalEqual(InstanceState rightOperand) {
1374 assertBoolNumStringOrNull(rightOperand);
1375 return isIdentical(rightOperand);
1376 }
1377
1378 @override
1379 BoolState isIdentical(InstanceState rightOperand) {
1380 if (rightOperand is DynamicState) {
1381 return BoolState.UNKNOWN_VALUE;
1382 }
1383 return BoolState.from(this == rightOperand);
1384 }
1385
1386 @override
1387 String toString() {
1388 StringBuffer buffer = new StringBuffer();
1389 List<String> fieldNames = _fieldMap.keys.toList();
1390 fieldNames.sort();
1391 bool first = true;
1392 for (String fieldName in fieldNames) {
1393 if (first) {
1394 first = false;
1395 } else {
1396 buffer.write('; ');
1397 }
1398 buffer.write(fieldName);
1399 buffer.write(' = ');
1400 buffer.write(_fieldMap[fieldName]);
1401 }
1402 return buffer.toString();
1403 }
1404 }
1405
1406 /**
1407 * The state of an object representing a Dart object.
1408 */
1409 abstract class InstanceState {
1410 /**
1411 * If this represents a generic dart object, return a map from its field names
1412 * to their values. Otherwise return null.
1413 */
1414 HashMap<String, DartObjectImpl> get fields => null;
1415
1416 /**
1417 * Return `true` if this object represents an object whose type is 'bool'.
1418 */
1419 bool get isBool => false;
1420
1421 /**
1422 * Return `true` if this object represents an object whose type is either
1423 * 'bool', 'num', 'String', or 'Null'.
1424 */
1425 bool get isBoolNumStringOrNull => false;
1426
1427 /**
1428 * Return `true` if this object represents an unknown value.
1429 */
1430 bool get isUnknown => false;
1431
1432 /**
1433 * Return the name of the type of this value.
1434 */
1435 String get typeName;
1436
1437 /**
1438 * Return the result of invoking the '+' operator on this object with the
1439 * [rightOperand].
1440 *
1441 * Throws an [EvaluationException] if the operator is not appropriate for an
1442 * object of this kind.
1443 */
1444 InstanceState add(InstanceState rightOperand) {
1445 if (this is StringState && rightOperand is StringState) {
1446 return concatenate(rightOperand);
1447 }
1448 assertNumOrNull(this);
1449 assertNumOrNull(rightOperand);
1450 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1451 }
1452
1453 /**
1454 * Throw an exception if the given [state] does not represent a boolean value.
1455 */
1456 void assertBool(InstanceState state) {
1457 if (!(state is BoolState || state is DynamicState)) {
1458 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
1459 }
1460 }
1461
1462 /**
1463 * Throw an exception if the given [state] does not represent a boolean,
1464 * numeric, string or null value.
1465 */
1466 void assertBoolNumStringOrNull(InstanceState state) {
1467 if (!(state is BoolState ||
1468 state is DoubleState ||
1469 state is IntState ||
1470 state is NumState ||
1471 state is StringState ||
1472 state is NullState ||
1473 state is DynamicState)) {
1474 throw new EvaluationException(
1475 CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
1476 }
1477 }
1478
1479 /**
1480 * Throw an exception if the given [state] does not represent an integer or
1481 * null value.
1482 */
1483 void assertIntOrNull(InstanceState state) {
1484 if (!(state is IntState ||
1485 state is NumState ||
1486 state is NullState ||
1487 state is DynamicState)) {
1488 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
1489 }
1490 }
1491
1492 /**
1493 * Throw an exception if the given [state] does not represent a boolean,
1494 * numeric, string or null value.
1495 */
1496 void assertNumOrNull(InstanceState state) {
1497 if (!(state is DoubleState ||
1498 state is IntState ||
1499 state is NumState ||
1500 state is NullState ||
1501 state is DynamicState)) {
1502 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
1503 }
1504 }
1505
1506 /**
1507 * Throw an exception if the given [state] does not represent a String value.
1508 */
1509 void assertString(InstanceState state) {
1510 if (!(state is StringState || state is DynamicState)) {
1511 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
1512 }
1513 }
1514
1515 /**
1516 * Return the result of invoking the '&' operator on this object with the
1517 * [rightOperand].
1518 *
1519 * Throws an [EvaluationException] if the operator is not appropriate for an
1520 * object of this kind.
1521 */
1522 IntState bitAnd(InstanceState rightOperand) {
1523 assertIntOrNull(this);
1524 assertIntOrNull(rightOperand);
1525 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1526 }
1527
1528 /**
1529 * Return the result of invoking the '~' operator on this object.
1530 *
1531 * Throws an [EvaluationException] if the operator is not appropriate for an
1532 * object of this kind.
1533 */
1534 IntState bitNot() {
1535 assertIntOrNull(this);
1536 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1537 }
1538
1539 /**
1540 * Return the result of invoking the '|' operator on this object with the
1541 * [rightOperand].
1542 *
1543 * Throws an [EvaluationException] if the operator is not appropriate for an
1544 * object of this kind.
1545 */
1546 IntState bitOr(InstanceState rightOperand) {
1547 assertIntOrNull(this);
1548 assertIntOrNull(rightOperand);
1549 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1550 }
1551
1552 /**
1553 * Return the result of invoking the '^' operator on this object with the
1554 * [rightOperand].
1555 *
1556 * Throws an [EvaluationException] if the operator is not appropriate for an
1557 * object of this kind.
1558 */
1559 IntState bitXor(InstanceState rightOperand) {
1560 assertIntOrNull(this);
1561 assertIntOrNull(rightOperand);
1562 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1563 }
1564
1565 /**
1566 * Return the result of invoking the ' ' operator on this object with the
1567 * [rightOperand].
1568 *
1569 * Throws an [EvaluationException] if the operator is not appropriate for an
1570 * object of this kind.
1571 */
1572 StringState concatenate(InstanceState rightOperand) {
1573 assertString(rightOperand);
1574 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1575 }
1576
1577 /**
1578 * Return the result of applying boolean conversion to this object.
1579 *
1580 * Throws an [EvaluationException] if the operator is not appropriate for an
1581 * object of this kind.
1582 */
1583 BoolState convertToBool() => BoolState.FALSE_STATE;
1584
1585 /**
1586 * Return the result of converting this object to a String.
1587 *
1588 * Throws an [EvaluationException] if the operator is not appropriate for an
1589 * object of this kind.
1590 */
1591 StringState convertToString();
1592
1593 /**
1594 * Return the result of invoking the '/' operator on this object with the
1595 * [rightOperand].
1596 *
1597 * Throws an [EvaluationException] if the operator is not appropriate for an
1598 * object of this kind.
1599 */
1600 NumState divide(InstanceState rightOperand) {
1601 assertNumOrNull(this);
1602 assertNumOrNull(rightOperand);
1603 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1604 }
1605
1606 /**
1607 * Return the result of invoking the '==' operator on this object with the
1608 * [rightOperand].
1609 *
1610 * Throws an [EvaluationException] if the operator is not appropriate for an
1611 * object of this kind.
1612 */
1613 BoolState equalEqual(InstanceState rightOperand);
1614
1615 /**
1616 * Return the result of invoking the '&gt;' operator on this object with the
1617 * [rightOperand].
1618 *
1619 * Throws an [EvaluationException] if the operator is not appropriate for an
1620 * object of this kind.
1621 */
1622 BoolState greaterThan(InstanceState rightOperand) {
1623 assertNumOrNull(this);
1624 assertNumOrNull(rightOperand);
1625 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1626 }
1627
1628 /**
1629 * Return the result of invoking the '&gt;=' operator on this object with the
1630 * [rightOperand].
1631 *
1632 * Throws an [EvaluationException] if the operator is not appropriate for an
1633 * object of this kind.
1634 */
1635 BoolState greaterThanOrEqual(InstanceState rightOperand) {
1636 assertNumOrNull(this);
1637 assertNumOrNull(rightOperand);
1638 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1639 }
1640
1641 /**
1642 * Return the result of invoking the '~/' operator on this object with the
1643 * [rightOperand].
1644 *
1645 * Throws an [EvaluationException] if the operator is not appropriate for an
1646 * object of this kind.
1647 */
1648 IntState integerDivide(InstanceState rightOperand) {
1649 assertNumOrNull(this);
1650 assertNumOrNull(rightOperand);
1651 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1652 }
1653
1654 /**
1655 * Return the result of invoking the identical function on this object with
1656 * the [rightOperand].
1657 */
1658 BoolState isIdentical(InstanceState rightOperand);
1659
1660 /**
1661 * Return the result of invoking the '&lt;' operator on this object with the
1662 * [rightOperand].
1663 *
1664 * Throws an [EvaluationException] if the operator is not appropriate for an
1665 * object of this kind.
1666 */
1667 BoolState lessThan(InstanceState rightOperand) {
1668 assertNumOrNull(this);
1669 assertNumOrNull(rightOperand);
1670 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1671 }
1672
1673 /**
1674 * Return the result of invoking the '&lt;=' operator on this object with the
1675 * [rightOperand].
1676 *
1677 * Throws an [EvaluationException] if the operator is not appropriate for an
1678 * object of this kind.
1679 */
1680 BoolState lessThanOrEqual(InstanceState rightOperand) {
1681 assertNumOrNull(this);
1682 assertNumOrNull(rightOperand);
1683 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1684 }
1685
1686 /**
1687 * Return the result of invoking the '&&' operator on this object with the
1688 * [rightOperand].
1689 *
1690 * Throws an [EvaluationException] if the operator is not appropriate for an
1691 * object of this kind.
1692 */
1693 BoolState logicalAnd(InstanceState rightOperand) {
1694 assertBool(this);
1695 assertBool(rightOperand);
1696 return BoolState.FALSE_STATE;
1697 }
1698
1699 /**
1700 * Return the result of invoking the '!' operator on this object.
1701 *
1702 * Throws an [EvaluationException] if the operator is not appropriate for an
1703 * object of this kind.
1704 */
1705 BoolState logicalNot() {
1706 assertBool(this);
1707 return BoolState.TRUE_STATE;
1708 }
1709
1710 /**
1711 * Return the result of invoking the '||' operator on this object with the
1712 * [rightOperand].
1713 *
1714 * Throws an [EvaluationException] if the operator is not appropriate for an
1715 * object of this kind.
1716 */
1717 BoolState logicalOr(InstanceState rightOperand) {
1718 assertBool(this);
1719 assertBool(rightOperand);
1720 return rightOperand.convertToBool();
1721 }
1722
1723 /**
1724 * Return the result of invoking the '-' operator on this object with the
1725 * [rightOperand].
1726 *
1727 * Throws an [EvaluationException] if the operator is not appropriate for an
1728 * object of this kind.
1729 */
1730 NumState minus(InstanceState rightOperand) {
1731 assertNumOrNull(this);
1732 assertNumOrNull(rightOperand);
1733 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1734 }
1735
1736 /**
1737 * Return the result of invoking the '-' operator on this object.
1738 *
1739 * Throws an [EvaluationException] if the operator is not appropriate for an
1740 * object of this kind.
1741 */
1742 NumState negated() {
1743 assertNumOrNull(this);
1744 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1745 }
1746
1747 /**
1748 * Return the result of invoking the '%' operator on this object with the
1749 * [rightOperand].
1750 *
1751 * Throws an [EvaluationException] if the operator is not appropriate for an
1752 * object of this kind.
1753 */
1754 NumState remainder(InstanceState rightOperand) {
1755 assertNumOrNull(this);
1756 assertNumOrNull(rightOperand);
1757 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1758 }
1759
1760 /**
1761 * Return the result of invoking the '&lt;&lt;' operator on this object with
1762 * the [rightOperand].
1763 *
1764 * Throws an [EvaluationException] if the operator is not appropriate for an
1765 * object of this kind.
1766 */
1767 IntState shiftLeft(InstanceState rightOperand) {
1768 assertIntOrNull(this);
1769 assertIntOrNull(rightOperand);
1770 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1771 }
1772
1773 /**
1774 * Return the result of invoking the '&gt;&gt;' operator on this object with
1775 * the [rightOperand].
1776 *
1777 * Throws an [EvaluationException] if the operator is not appropriate for an
1778 * object of this kind.
1779 */
1780 IntState shiftRight(InstanceState rightOperand) {
1781 assertIntOrNull(this);
1782 assertIntOrNull(rightOperand);
1783 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1784 }
1785
1786 /**
1787 * Return the result of invoking the 'length' getter on this object.
1788 *
1789 * Throws an [EvaluationException] if the operator is not appropriate for an
1790 * object of this kind.
1791 */
1792 IntState stringLength() {
1793 assertString(this);
1794 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1795 }
1796
1797 /**
1798 * Return the result of invoking the '*' operator on this object with the
1799 * [rightOperand].
1800 *
1801 * Throws an [EvaluationException] if the operator is not appropriate for an
1802 * object of this kind.
1803 */
1804 NumState times(InstanceState rightOperand) {
1805 assertNumOrNull(this);
1806 assertNumOrNull(rightOperand);
1807 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
1808 }
1809 }
1810
1811 /**
1812 * The state of an object representing an int.
1813 */
1814 class IntState extends NumState {
1815 /**
1816 * A state that can be used to represent an int whose value is not known.
1817 */
1818 static IntState UNKNOWN_VALUE = new IntState(null);
1819
1820 /**
1821 * The value of this instance.
1822 */
1823 final int value;
1824
1825 /**
1826 * Initialize a newly created state to represent an int with the given
1827 * [value].
1828 */
1829 IntState(this.value);
1830
1831 @override
1832 int get hashCode => value == null ? 0 : value.hashCode;
1833
1834 @override
1835 bool get isBoolNumStringOrNull => true;
1836
1837 @override
1838 bool get isUnknown => value == null;
1839
1840 @override
1841 String get typeName => "int";
1842
1843 @override
1844 bool operator ==(Object object) =>
1845 object is IntState && (value == object.value);
1846
1847 @override
1848 NumState add(InstanceState rightOperand) {
1849 assertNumOrNull(rightOperand);
1850 if (value == null) {
1851 if (rightOperand is DoubleState) {
1852 return DoubleState.UNKNOWN_VALUE;
1853 }
1854 return UNKNOWN_VALUE;
1855 }
1856 if (rightOperand is IntState) {
1857 int rightValue = rightOperand.value;
1858 if (rightValue == null) {
1859 return UNKNOWN_VALUE;
1860 }
1861 return new IntState(value + rightValue);
1862 } else if (rightOperand is DoubleState) {
1863 double rightValue = rightOperand.value;
1864 if (rightValue == null) {
1865 return DoubleState.UNKNOWN_VALUE;
1866 }
1867 return new DoubleState(value.toDouble() + rightValue);
1868 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1869 return UNKNOWN_VALUE;
1870 }
1871 throw new EvaluationException(
1872 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
1873 }
1874
1875 @override
1876 IntState bitAnd(InstanceState rightOperand) {
1877 assertIntOrNull(rightOperand);
1878 if (value == null) {
1879 return UNKNOWN_VALUE;
1880 }
1881 if (rightOperand is IntState) {
1882 int rightValue = rightOperand.value;
1883 if (rightValue == null) {
1884 return UNKNOWN_VALUE;
1885 }
1886 return new IntState(value & rightValue);
1887 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1888 return UNKNOWN_VALUE;
1889 }
1890 throw new EvaluationException(
1891 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
1892 }
1893
1894 @override
1895 IntState bitNot() {
1896 if (value == null) {
1897 return UNKNOWN_VALUE;
1898 }
1899 return new IntState(~value);
1900 }
1901
1902 @override
1903 IntState bitOr(InstanceState rightOperand) {
1904 assertIntOrNull(rightOperand);
1905 if (value == null) {
1906 return UNKNOWN_VALUE;
1907 }
1908 if (rightOperand is IntState) {
1909 int rightValue = rightOperand.value;
1910 if (rightValue == null) {
1911 return UNKNOWN_VALUE;
1912 }
1913 return new IntState(value | rightValue);
1914 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1915 return UNKNOWN_VALUE;
1916 }
1917 throw new EvaluationException(
1918 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
1919 }
1920
1921 @override
1922 IntState bitXor(InstanceState rightOperand) {
1923 assertIntOrNull(rightOperand);
1924 if (value == null) {
1925 return UNKNOWN_VALUE;
1926 }
1927 if (rightOperand is IntState) {
1928 int rightValue = rightOperand.value;
1929 if (rightValue == null) {
1930 return UNKNOWN_VALUE;
1931 }
1932 return new IntState(value ^ rightValue);
1933 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1934 return UNKNOWN_VALUE;
1935 }
1936 throw new EvaluationException(
1937 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
1938 }
1939
1940 @override
1941 StringState convertToString() {
1942 if (value == null) {
1943 return StringState.UNKNOWN_VALUE;
1944 }
1945 return new StringState(value.toString());
1946 }
1947
1948 @override
1949 NumState divide(InstanceState rightOperand) {
1950 assertNumOrNull(rightOperand);
1951 if (value == null) {
1952 return DoubleState.UNKNOWN_VALUE;
1953 }
1954 if (rightOperand is IntState) {
1955 int rightValue = rightOperand.value;
1956 if (rightValue == null) {
1957 return DoubleState.UNKNOWN_VALUE;
1958 } else {
1959 return new DoubleState(value.toDouble() / rightValue.toDouble());
1960 }
1961 } else if (rightOperand is DoubleState) {
1962 double rightValue = rightOperand.value;
1963 if (rightValue == null) {
1964 return DoubleState.UNKNOWN_VALUE;
1965 }
1966 return new DoubleState(value.toDouble() / rightValue);
1967 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1968 return DoubleState.UNKNOWN_VALUE;
1969 }
1970 throw new EvaluationException(
1971 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
1972 }
1973
1974 @override
1975 BoolState equalEqual(InstanceState rightOperand) {
1976 assertBoolNumStringOrNull(rightOperand);
1977 return isIdentical(rightOperand);
1978 }
1979
1980 @override
1981 BoolState greaterThan(InstanceState rightOperand) {
1982 assertNumOrNull(rightOperand);
1983 if (value == null) {
1984 return BoolState.UNKNOWN_VALUE;
1985 }
1986 if (rightOperand is IntState) {
1987 int rightValue = rightOperand.value;
1988 if (rightValue == null) {
1989 return BoolState.UNKNOWN_VALUE;
1990 }
1991 return BoolState.from(value.compareTo(rightValue) > 0);
1992 } else if (rightOperand is DoubleState) {
1993 double rightValue = rightOperand.value;
1994 if (rightValue == null) {
1995 return BoolState.UNKNOWN_VALUE;
1996 }
1997 return BoolState.from(value.toDouble() > rightValue);
1998 } else if (rightOperand is DynamicState || rightOperand is NumState) {
1999 return BoolState.UNKNOWN_VALUE;
2000 }
2001 throw new EvaluationException(
2002 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2003 }
2004
2005 @override
2006 BoolState greaterThanOrEqual(InstanceState rightOperand) {
2007 assertNumOrNull(rightOperand);
2008 if (value == null) {
2009 return BoolState.UNKNOWN_VALUE;
2010 }
2011 if (rightOperand is IntState) {
2012 int rightValue = rightOperand.value;
2013 if (rightValue == null) {
2014 return BoolState.UNKNOWN_VALUE;
2015 }
2016 return BoolState.from(value.compareTo(rightValue) >= 0);
2017 } else if (rightOperand is DoubleState) {
2018 double rightValue = rightOperand.value;
2019 if (rightValue == null) {
2020 return BoolState.UNKNOWN_VALUE;
2021 }
2022 return BoolState.from(value.toDouble() >= rightValue);
2023 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2024 return BoolState.UNKNOWN_VALUE;
2025 }
2026 throw new EvaluationException(
2027 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2028 }
2029
2030 @override
2031 IntState integerDivide(InstanceState rightOperand) {
2032 assertNumOrNull(rightOperand);
2033 if (value == null) {
2034 return UNKNOWN_VALUE;
2035 }
2036 if (rightOperand is IntState) {
2037 int rightValue = rightOperand.value;
2038 if (rightValue == null) {
2039 return UNKNOWN_VALUE;
2040 } else if (rightValue == 0) {
2041 throw new EvaluationException(
2042 CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
2043 }
2044 return new IntState(value ~/ rightValue);
2045 } else if (rightOperand is DoubleState) {
2046 double rightValue = rightOperand.value;
2047 if (rightValue == null) {
2048 return UNKNOWN_VALUE;
2049 }
2050 double result = value.toDouble() / rightValue;
2051 return new IntState(result.toInt());
2052 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2053 return UNKNOWN_VALUE;
2054 }
2055 throw new EvaluationException(
2056 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2057 }
2058
2059 @override
2060 BoolState isIdentical(InstanceState rightOperand) {
2061 if (value == null) {
2062 return BoolState.UNKNOWN_VALUE;
2063 }
2064 if (rightOperand is IntState) {
2065 int rightValue = rightOperand.value;
2066 if (rightValue == null) {
2067 return BoolState.UNKNOWN_VALUE;
2068 }
2069 return BoolState.from(value == rightValue);
2070 } else if (rightOperand is DoubleState) {
2071 double rightValue = rightOperand.value;
2072 if (rightValue == null) {
2073 return BoolState.UNKNOWN_VALUE;
2074 }
2075 return BoolState.from(rightValue == value.toDouble());
2076 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2077 return BoolState.UNKNOWN_VALUE;
2078 }
2079 return BoolState.FALSE_STATE;
2080 }
2081
2082 @override
2083 BoolState lessThan(InstanceState rightOperand) {
2084 assertNumOrNull(rightOperand);
2085 if (value == null) {
2086 return BoolState.UNKNOWN_VALUE;
2087 }
2088 if (rightOperand is IntState) {
2089 int rightValue = rightOperand.value;
2090 if (rightValue == null) {
2091 return BoolState.UNKNOWN_VALUE;
2092 }
2093 return BoolState.from(value.compareTo(rightValue) < 0);
2094 } else if (rightOperand is DoubleState) {
2095 double rightValue = rightOperand.value;
2096 if (rightValue == null) {
2097 return BoolState.UNKNOWN_VALUE;
2098 }
2099 return BoolState.from(value.toDouble() < rightValue);
2100 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2101 return BoolState.UNKNOWN_VALUE;
2102 }
2103 throw new EvaluationException(
2104 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2105 }
2106
2107 @override
2108 BoolState lessThanOrEqual(InstanceState rightOperand) {
2109 assertNumOrNull(rightOperand);
2110 if (value == null) {
2111 return BoolState.UNKNOWN_VALUE;
2112 }
2113 if (rightOperand is IntState) {
2114 int rightValue = rightOperand.value;
2115 if (rightValue == null) {
2116 return BoolState.UNKNOWN_VALUE;
2117 }
2118 return BoolState.from(value.compareTo(rightValue) <= 0);
2119 } else if (rightOperand is DoubleState) {
2120 double rightValue = rightOperand.value;
2121 if (rightValue == null) {
2122 return BoolState.UNKNOWN_VALUE;
2123 }
2124 return BoolState.from(value.toDouble() <= rightValue);
2125 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2126 return BoolState.UNKNOWN_VALUE;
2127 }
2128 throw new EvaluationException(
2129 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2130 }
2131
2132 @override
2133 NumState minus(InstanceState rightOperand) {
2134 assertNumOrNull(rightOperand);
2135 if (value == null) {
2136 if (rightOperand is DoubleState) {
2137 return DoubleState.UNKNOWN_VALUE;
2138 }
2139 return UNKNOWN_VALUE;
2140 }
2141 if (rightOperand is IntState) {
2142 int rightValue = rightOperand.value;
2143 if (rightValue == null) {
2144 return UNKNOWN_VALUE;
2145 }
2146 return new IntState(value - rightValue);
2147 } else if (rightOperand is DoubleState) {
2148 double rightValue = rightOperand.value;
2149 if (rightValue == null) {
2150 return DoubleState.UNKNOWN_VALUE;
2151 }
2152 return new DoubleState(value.toDouble() - rightValue);
2153 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2154 return UNKNOWN_VALUE;
2155 }
2156 throw new EvaluationException(
2157 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2158 }
2159
2160 @override
2161 NumState negated() {
2162 if (value == null) {
2163 return UNKNOWN_VALUE;
2164 }
2165 return new IntState(-value);
2166 }
2167
2168 @override
2169 NumState remainder(InstanceState rightOperand) {
2170 assertNumOrNull(rightOperand);
2171 if (value == null) {
2172 if (rightOperand is DoubleState) {
2173 return DoubleState.UNKNOWN_VALUE;
2174 }
2175 return UNKNOWN_VALUE;
2176 }
2177 if (rightOperand is IntState) {
2178 int rightValue = rightOperand.value;
2179 if (rightValue == null) {
2180 return UNKNOWN_VALUE;
2181 } else if (rightValue == 0) {
2182 return new DoubleState(value.toDouble() % rightValue.toDouble());
2183 }
2184 return new IntState(value.remainder(rightValue));
2185 } else if (rightOperand is DoubleState) {
2186 double rightValue = rightOperand.value;
2187 if (rightValue == null) {
2188 return DoubleState.UNKNOWN_VALUE;
2189 }
2190 return new DoubleState(value.toDouble() % rightValue);
2191 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2192 return UNKNOWN_VALUE;
2193 }
2194 throw new EvaluationException(
2195 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2196 }
2197
2198 @override
2199 IntState shiftLeft(InstanceState rightOperand) {
2200 assertIntOrNull(rightOperand);
2201 if (value == null) {
2202 return UNKNOWN_VALUE;
2203 }
2204 if (rightOperand is IntState) {
2205 int rightValue = rightOperand.value;
2206 if (rightValue == null) {
2207 return UNKNOWN_VALUE;
2208 } else if (rightValue.bitLength > 31) {
2209 return UNKNOWN_VALUE;
2210 }
2211 return new IntState(value << rightValue);
2212 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2213 return UNKNOWN_VALUE;
2214 }
2215 throw new EvaluationException(
2216 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2217 }
2218
2219 @override
2220 IntState shiftRight(InstanceState rightOperand) {
2221 assertIntOrNull(rightOperand);
2222 if (value == null) {
2223 return UNKNOWN_VALUE;
2224 }
2225 if (rightOperand is IntState) {
2226 int rightValue = rightOperand.value;
2227 if (rightValue == null) {
2228 return UNKNOWN_VALUE;
2229 } else if (rightValue.bitLength > 31) {
2230 return UNKNOWN_VALUE;
2231 }
2232 return new IntState(value >> rightValue);
2233 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2234 return UNKNOWN_VALUE;
2235 }
2236 throw new EvaluationException(
2237 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2238 }
2239
2240 @override
2241 NumState times(InstanceState rightOperand) {
2242 assertNumOrNull(rightOperand);
2243 if (value == null) {
2244 if (rightOperand is DoubleState) {
2245 return DoubleState.UNKNOWN_VALUE;
2246 }
2247 return UNKNOWN_VALUE;
2248 }
2249 if (rightOperand is IntState) {
2250 int rightValue = rightOperand.value;
2251 if (rightValue == null) {
2252 return UNKNOWN_VALUE;
2253 }
2254 return new IntState(value * rightValue);
2255 } else if (rightOperand is DoubleState) {
2256 double rightValue = rightOperand.value;
2257 if (rightValue == null) {
2258 return DoubleState.UNKNOWN_VALUE;
2259 }
2260 return new DoubleState(value.toDouble() * rightValue);
2261 } else if (rightOperand is DynamicState || rightOperand is NumState) {
2262 return UNKNOWN_VALUE;
2263 }
2264 throw new EvaluationException(
2265 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2266 }
2267
2268 @override
2269 String toString() => value == null ? "-unknown-" : value.toString();
2270 }
2271
2272 /**
2273 * The state of an object representing a list.
2274 */
2275 class ListState extends InstanceState {
2276 /**
2277 * The elements of the list.
2278 */
2279 final List<DartObjectImpl> _elements;
2280
2281 /**
2282 * Initialize a newly created state to represent a list with the given
2283 * [elements].
2284 */
2285 ListState(this._elements);
2286
2287 @override
2288 int get hashCode {
2289 int value = 0;
2290 int count = _elements.length;
2291 for (int i = 0; i < count; i++) {
2292 value = (value << 3) ^ _elements[i].hashCode;
2293 }
2294 return value;
2295 }
2296
2297 @override
2298 String get typeName => "List";
2299
2300 @override
2301 bool operator ==(Object object) {
2302 if (object is! ListState) {
2303 return false;
2304 }
2305 List<DartObjectImpl> otherElements = (object as ListState)._elements;
2306 int count = _elements.length;
2307 if (otherElements.length != count) {
2308 return false;
2309 } else if (count == 0) {
2310 return true;
2311 }
2312 for (int i = 0; i < count; i++) {
2313 if (_elements[i] != otherElements[i]) {
2314 return false;
2315 }
2316 }
2317 return true;
2318 }
2319
2320 @override
2321 StringState convertToString() => StringState.UNKNOWN_VALUE;
2322
2323 @override
2324 BoolState equalEqual(InstanceState rightOperand) {
2325 assertBoolNumStringOrNull(rightOperand);
2326 return isIdentical(rightOperand);
2327 }
2328
2329 @override
2330 BoolState isIdentical(InstanceState rightOperand) {
2331 if (rightOperand is DynamicState) {
2332 return BoolState.UNKNOWN_VALUE;
2333 }
2334 return BoolState.from(this == rightOperand);
2335 }
2336
2337 @override
2338 String toString() {
2339 StringBuffer buffer = new StringBuffer();
2340 buffer.write('[');
2341 bool first = true;
2342 _elements.forEach((DartObjectImpl element) {
2343 if (first) {
2344 first = false;
2345 } else {
2346 buffer.write(', ');
2347 }
2348 buffer.write(element);
2349 });
2350 buffer.write(']');
2351 return buffer.toString();
2352 }
2353 }
2354
2355 /**
2356 * The state of an object representing a map.
2357 */
2358 class MapState extends InstanceState {
2359 /**
2360 * The entries in the map.
2361 */
2362 final HashMap<DartObjectImpl, DartObjectImpl> _entries;
2363
2364 /**
2365 * Initialize a newly created state to represent a map with the given
2366 * [entries].
2367 */
2368 MapState(this._entries);
2369
2370 @override
2371 int get hashCode {
2372 int value = 0;
2373 for (DartObjectImpl key in _entries.keys.toSet()) {
2374 value = (value << 3) ^ key.hashCode;
2375 }
2376 return value;
2377 }
2378
2379 @override
2380 String get typeName => "Map";
2381
2382 @override
2383 bool operator ==(Object object) {
2384 if (object is! MapState) {
2385 return false;
2386 }
2387 HashMap<DartObjectImpl, DartObjectImpl> otherElements =
2388 (object as MapState)._entries;
2389 int count = _entries.length;
2390 if (otherElements.length != count) {
2391 return false;
2392 } else if (count == 0) {
2393 return true;
2394 }
2395 for (DartObjectImpl key in _entries.keys) {
2396 DartObjectImpl value = _entries[key];
2397 DartObjectImpl otherValue = otherElements[key];
2398 if (value != otherValue) {
2399 return false;
2400 }
2401 }
2402 return true;
2403 }
2404
2405 @override
2406 StringState convertToString() => StringState.UNKNOWN_VALUE;
2407
2408 @override
2409 BoolState equalEqual(InstanceState rightOperand) {
2410 assertBoolNumStringOrNull(rightOperand);
2411 return isIdentical(rightOperand);
2412 }
2413
2414 @override
2415 BoolState isIdentical(InstanceState rightOperand) {
2416 if (rightOperand is DynamicState) {
2417 return BoolState.UNKNOWN_VALUE;
2418 }
2419 return BoolState.from(this == rightOperand);
2420 }
2421
2422 @override
2423 String toString() {
2424 StringBuffer buffer = new StringBuffer();
2425 buffer.write('{');
2426 bool first = true;
2427 _entries.forEach((DartObjectImpl key, DartObjectImpl value) {
2428 if (first) {
2429 first = false;
2430 } else {
2431 buffer.write(', ');
2432 }
2433 buffer.write(key);
2434 buffer.write(' = ');
2435 buffer.write(value);
2436 });
2437 buffer.write('}');
2438 return buffer.toString();
2439 }
2440 }
2441
2442 /**
2443 * The state of an object representing the value 'null'.
2444 */
2445 class NullState extends InstanceState {
2446 /**
2447 * An instance representing the boolean value 'null'.
2448 */
2449 static NullState NULL_STATE = new NullState();
2450
2451 @override
2452 int get hashCode => 0;
2453
2454 @override
2455 bool get isBoolNumStringOrNull => true;
2456
2457 @override
2458 String get typeName => "Null";
2459
2460 @override
2461 bool operator ==(Object object) => object is NullState;
2462
2463 @override
2464 BoolState convertToBool() {
2465 throw new EvaluationException(
2466 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2467 }
2468
2469 @override
2470 StringState convertToString() => new StringState("null");
2471
2472 @override
2473 BoolState equalEqual(InstanceState rightOperand) {
2474 assertBoolNumStringOrNull(rightOperand);
2475 return isIdentical(rightOperand);
2476 }
2477
2478 @override
2479 BoolState isIdentical(InstanceState rightOperand) {
2480 if (rightOperand is DynamicState) {
2481 return BoolState.UNKNOWN_VALUE;
2482 }
2483 return BoolState.from(rightOperand is NullState);
2484 }
2485
2486 @override
2487 BoolState logicalNot() {
2488 throw new EvaluationException(
2489 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
2490 }
2491
2492 @override
2493 String toString() => "null";
2494 }
2495
2496 /**
2497 * The state of an object representing a number of an unknown type (a 'num').
2498 */
2499 class NumState extends InstanceState {
2500 /**
2501 * A state that can be used to represent a number whose value is not known.
2502 */
2503 static NumState UNKNOWN_VALUE = new NumState();
2504
2505 @override
2506 int get hashCode => 7;
2507
2508 @override
2509 bool get isBoolNumStringOrNull => true;
2510
2511 @override
2512 bool get isUnknown => identical(this, UNKNOWN_VALUE);
2513
2514 @override
2515 String get typeName => "num";
2516
2517 @override
2518 bool operator ==(Object object) => object is NumState;
2519
2520 @override
2521 NumState add(InstanceState rightOperand) {
2522 assertNumOrNull(rightOperand);
2523 return UNKNOWN_VALUE;
2524 }
2525
2526 @override
2527 StringState convertToString() => StringState.UNKNOWN_VALUE;
2528
2529 @override
2530 NumState divide(InstanceState rightOperand) {
2531 assertNumOrNull(rightOperand);
2532 return DoubleState.UNKNOWN_VALUE;
2533 }
2534
2535 @override
2536 BoolState equalEqual(InstanceState rightOperand) {
2537 assertBoolNumStringOrNull(rightOperand);
2538 return BoolState.UNKNOWN_VALUE;
2539 }
2540
2541 @override
2542 BoolState greaterThan(InstanceState rightOperand) {
2543 assertNumOrNull(rightOperand);
2544 return BoolState.UNKNOWN_VALUE;
2545 }
2546
2547 @override
2548 BoolState greaterThanOrEqual(InstanceState rightOperand) {
2549 assertNumOrNull(rightOperand);
2550 return BoolState.UNKNOWN_VALUE;
2551 }
2552
2553 @override
2554 IntState integerDivide(InstanceState rightOperand) {
2555 assertNumOrNull(rightOperand);
2556 if (rightOperand is IntState) {
2557 int rightValue = rightOperand.value;
2558 if (rightValue == null) {
2559 return IntState.UNKNOWN_VALUE;
2560 } else if (rightValue == 0) {
2561 throw new EvaluationException(
2562 CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
2563 }
2564 } else if (rightOperand is DynamicState) {
2565 return IntState.UNKNOWN_VALUE;
2566 }
2567 return IntState.UNKNOWN_VALUE;
2568 }
2569
2570 @override
2571 BoolState isIdentical(InstanceState rightOperand) {
2572 return BoolState.UNKNOWN_VALUE;
2573 }
2574
2575 @override
2576 BoolState lessThan(InstanceState rightOperand) {
2577 assertNumOrNull(rightOperand);
2578 return BoolState.UNKNOWN_VALUE;
2579 }
2580
2581 @override
2582 BoolState lessThanOrEqual(InstanceState rightOperand) {
2583 assertNumOrNull(rightOperand);
2584 return BoolState.UNKNOWN_VALUE;
2585 }
2586
2587 @override
2588 NumState minus(InstanceState rightOperand) {
2589 assertNumOrNull(rightOperand);
2590 return UNKNOWN_VALUE;
2591 }
2592
2593 @override
2594 NumState negated() => UNKNOWN_VALUE;
2595
2596 @override
2597 NumState remainder(InstanceState rightOperand) {
2598 assertNumOrNull(rightOperand);
2599 return UNKNOWN_VALUE;
2600 }
2601
2602 @override
2603 NumState times(InstanceState rightOperand) {
2604 assertNumOrNull(rightOperand);
2605 return UNKNOWN_VALUE;
2606 }
2607
2608 @override
2609 String toString() => "-unknown-";
2610 }
2611
2612 /**
2613 * The state of an object representing a string.
2614 */
2615 class StringState extends InstanceState {
2616 /**
2617 * A state that can be used to represent a double whose value is not known.
2618 */
2619 static StringState UNKNOWN_VALUE = new StringState(null);
2620
2621 /**
2622 * The value of this instance.
2623 */
2624 final String value;
2625
2626 /**
2627 * Initialize a newly created state to represent the given [value].
2628 */
2629 StringState(this.value);
2630
2631 @override
2632 int get hashCode => value == null ? 0 : value.hashCode;
2633
2634 @override
2635 bool get isBoolNumStringOrNull => true;
2636
2637 @override
2638 bool get isUnknown => value == null;
2639
2640 @override
2641 String get typeName => "String";
2642
2643 @override
2644 bool operator ==(Object object) =>
2645 object is StringState && (value == object.value);
2646
2647 @override
2648 StringState concatenate(InstanceState rightOperand) {
2649 if (value == null) {
2650 return UNKNOWN_VALUE;
2651 }
2652 if (rightOperand is StringState) {
2653 String rightValue = rightOperand.value;
2654 if (rightValue == null) {
2655 return UNKNOWN_VALUE;
2656 }
2657 return new StringState("$value$rightValue");
2658 } else if (rightOperand is DynamicState) {
2659 return UNKNOWN_VALUE;
2660 }
2661 return super.concatenate(rightOperand);
2662 }
2663
2664 @override
2665 StringState convertToString() => this;
2666
2667 @override
2668 BoolState equalEqual(InstanceState rightOperand) {
2669 assertBoolNumStringOrNull(rightOperand);
2670 return isIdentical(rightOperand);
2671 }
2672
2673 @override
2674 BoolState isIdentical(InstanceState rightOperand) {
2675 if (value == null) {
2676 return BoolState.UNKNOWN_VALUE;
2677 }
2678 if (rightOperand is StringState) {
2679 String rightValue = rightOperand.value;
2680 if (rightValue == null) {
2681 return BoolState.UNKNOWN_VALUE;
2682 }
2683 return BoolState.from(value == rightValue);
2684 } else if (rightOperand is DynamicState) {
2685 return BoolState.UNKNOWN_VALUE;
2686 }
2687 return BoolState.FALSE_STATE;
2688 }
2689
2690 @override
2691 IntState stringLength() {
2692 if (value == null) {
2693 return IntState.UNKNOWN_VALUE;
2694 }
2695 return new IntState(value.length);
2696 }
2697
2698 @override
2699 String toString() => value == null ? "-unknown-" : "'$value'";
2700 }
2701
2702 /**
2703 * The state of an object representing a symbol.
2704 */
2705 class SymbolState extends InstanceState {
2706 /**
2707 * The value of this instance.
2708 */
2709 final String value;
2710
2711 /**
2712 * Initialize a newly created state to represent the given [value].
2713 */
2714 SymbolState(this.value);
2715
2716 @override
2717 int get hashCode => value == null ? 0 : value.hashCode;
2718
2719 @override
2720 String get typeName => "Symbol";
2721
2722 @override
2723 bool operator ==(Object object) =>
2724 object is SymbolState && (value == object.value);
2725
2726 @override
2727 StringState convertToString() {
2728 if (value == null) {
2729 return StringState.UNKNOWN_VALUE;
2730 }
2731 return new StringState(value);
2732 }
2733
2734 @override
2735 BoolState equalEqual(InstanceState rightOperand) {
2736 assertBoolNumStringOrNull(rightOperand);
2737 return isIdentical(rightOperand);
2738 }
2739
2740 @override
2741 BoolState isIdentical(InstanceState rightOperand) {
2742 if (value == null) {
2743 return BoolState.UNKNOWN_VALUE;
2744 }
2745 if (rightOperand is SymbolState) {
2746 String rightValue = rightOperand.value;
2747 if (rightValue == null) {
2748 return BoolState.UNKNOWN_VALUE;
2749 }
2750 return BoolState.from(value == rightValue);
2751 } else if (rightOperand is DynamicState) {
2752 return BoolState.UNKNOWN_VALUE;
2753 }
2754 return BoolState.FALSE_STATE;
2755 }
2756
2757 @override
2758 String toString() => value == null ? "-unknown-" : "#$value";
2759 }
2760
2761 /**
2762 * The state of an object representing a type.
2763 */
2764 class TypeState extends InstanceState {
2765 /**
2766 * The element representing the type being modeled.
2767 */
2768 final Element _element;
2769
2770 /**
2771 * Initialize a newly created state to represent the given [value].
2772 */
2773 TypeState(this._element);
2774
2775 @override
2776 int get hashCode => _element == null ? 0 : _element.hashCode;
2777
2778 @override
2779 String get typeName => "Type";
2780
2781 @override
2782 bool operator ==(Object object) =>
2783 object is TypeState && (_element == object._element);
2784
2785 @override
2786 StringState convertToString() {
2787 if (_element == null) {
2788 return StringState.UNKNOWN_VALUE;
2789 }
2790 return new StringState(_element.name);
2791 }
2792
2793 @override
2794 BoolState equalEqual(InstanceState rightOperand) {
2795 assertBoolNumStringOrNull(rightOperand);
2796 return isIdentical(rightOperand);
2797 }
2798
2799 @override
2800 BoolState isIdentical(InstanceState rightOperand) {
2801 if (_element == null) {
2802 return BoolState.UNKNOWN_VALUE;
2803 }
2804 if (rightOperand is TypeState) {
2805 Element rightElement = rightOperand._element;
2806 if (rightElement == null) {
2807 return BoolState.UNKNOWN_VALUE;
2808 }
2809 return BoolState.from(_element == rightElement);
2810 } else if (rightOperand is DynamicState) {
2811 return BoolState.UNKNOWN_VALUE;
2812 }
2813 return BoolState.FALSE_STATE;
2814 }
2815
2816 @override
2817 String toString() => _element == null ? "-unknown-" : _element.name;
2818 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/constant/utilities.dart ('k') | pkg/analyzer/lib/src/generated/constant.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698