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

Side by Side Diff: pkg/compiler/lib/src/constants/constructors.dart

Issue 1282463002: Reorganize constants/* libraries. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.constants.expressions; 5 library dart2js.constants.constructors;
6 6
7 import '../constants/constant_system.dart';
8 import '../core_types.dart';
9 import '../dart2jslib.dart' show assertDebugMode, Compiler;
10 import '../dart_types.dart'; 7 import '../dart_types.dart';
11 import '../elements/elements.dart' show 8 import '../elements/elements.dart' show
12 ConstructorElement, 9 ConstructorElement,
13 Element, 10 FieldElement;
14 FieldElement,
15 FunctionElement,
16 PrefixElement,
17 VariableElement;
18 import '../resolution/operators.dart';
19 import '../tree/tree.dart' show DartString;
20 import '../universe/universe.dart' show CallStructure; 11 import '../universe/universe.dart' show CallStructure;
21 import '../util/util.dart'; 12 import '../util/util.dart';
22 import 'values.dart'; 13 import 'evaluation.dart';
23 14 import 'expressions.dart';
24 enum ConstantExpressionKind {
25 BINARY,
26 BOOL,
27 BOOL_FROM_ENVIRONMENT,
28 CONCATENATE,
29 CONDITIONAL,
30 CONSTRUCTED,
31 DEFERRED,
32 DOUBLE,
33 ERRONEOUS,
34 FUNCTION,
35 IDENTICAL,
36 INT,
37 INT_FROM_ENVIRONMENT,
38 LIST,
39 MAP,
40 NULL,
41 STRING,
42 STRING_FROM_ENVIRONMENT,
43 STRING_LENGTH,
44 SYMBOL,
45 SYNTHETIC,
46 TYPE,
47 UNARY,
48 VARIABLE,
49
50 POSITIONAL_REFERENCE,
51 NAMED_REFERENCE,
52 }
53
54 /// Environment used for evaluating constant expressions.
55 abstract class Environment {
56 // TODO(johnniwinther): Replace this with [CoreTypes] and maybe [Backend].
57 Compiler get compiler;
58
59 /// Read environments string passed in using the '-Dname=value' option.
60 String readFromEnvironment(String name);
61 }
62
63 /// The normalized arguments passed to a const constructor computed from the
64 /// actual [arguments] and the [defaultValues] of the called construrctor.
65 class NormalizedArguments {
66 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues;
67 final CallStructure callStructure;
68 final List<ConstantExpression> arguments;
69
70 NormalizedArguments(this.defaultValues, this.callStructure, this.arguments);
71
72 /// Returns the normalized named argument [name].
73 ConstantExpression getNamedArgument(String name) {
74 int index = callStructure.namedArguments.indexOf(name);
75 if (index == -1) {
76 // The named argument is not provided.
77 return defaultValues[name];
78 }
79 return arguments[index + callStructure.positionalArgumentCount];
80 }
81
82 /// Returns the normalized [index]th positional argument.
83 ConstantExpression getPositionalArgument(int index) {
84 if (index >= callStructure.positionalArgumentCount) {
85 // The positional argument is not provided.
86 return defaultValues[index];
87 }
88 return arguments[index];
89 }
90 }
91 15
92 enum ConstantConstructorKind { 16 enum ConstantConstructorKind {
93 GENERATIVE, 17 GENERATIVE,
94 REDIRECTING_GENERATIVE, 18 REDIRECTING_GENERATIVE,
95 REDIRECTING_FACTORY, 19 REDIRECTING_FACTORY,
96 } 20 }
97 21
98 /// Definition of a constant constructor. 22 /// Definition of a constant constructor.
99 abstract class ConstantConstructor { 23 abstract class ConstantConstructor {
100 ConstantConstructorKind get kind; 24 ConstantConstructorKind get kind;
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 } 245 }
322 246
323 String toString() { 247 String toString() {
324 StringBuffer sb = new StringBuffer(); 248 StringBuffer sb = new StringBuffer();
325 sb.write("{"); 249 sb.write("{");
326 sb.write("'constructor': ${targetConstructorInvocation.getText()}"); 250 sb.write("'constructor': ${targetConstructorInvocation.getText()}");
327 sb.write("}"); 251 sb.write("}");
328 return sb.toString(); 252 return sb.toString();
329 } 253 }
330 } 254 }
331
332 /// An expression that is a compile-time constant.
333 ///
334 /// Whereas [ConstantValue] represent a compile-time value, a
335 /// [ConstantExpression] represents an expression for creating a constant.
336 ///
337 /// There is no one-to-one mapping between [ConstantExpression] and
338 /// [ConstantValue], because different expressions can denote the same constant.
339 /// For instance, multiple `const` constructors may be used to create the same
340 /// object, and different `const` variables may hold the same value.
341 abstract class ConstantExpression {
342 int _hashCode;
343
344 ConstantExpressionKind get kind;
345
346 // TODO(johnniwinther): Unify precedence handled between constants, front-end
347 // and back-end.
348 int get precedence => 16;
349
350 accept(ConstantExpressionVisitor visitor, [context]);
351
352 /// Substitute free variables using arguments.
353 ConstantExpression apply(NormalizedArguments arguments) => this;
354
355 /// Compute the [ConstantValue] for this expression using the [environment]
356 /// and the [constantSystem].
357 ConstantValue evaluate(Environment environment,
358 ConstantSystem constantSystem);
359
360 /// Returns the type of this constant expression, if it is independent of the
361 /// environment values.
362 DartType getKnownType(CoreTypes coreTypes) => null;
363
364 String getText() {
365 ConstExpPrinter printer = new ConstExpPrinter();
366 accept(printer);
367 return printer.toString();
368 }
369
370 int _computeHashCode();
371
372 int get hashCode {
373 if (_hashCode == null) {
374 _hashCode = _computeHashCode();
375 }
376 return _hashCode;
377 }
378
379 bool _equals(ConstantExpression other);
380
381 bool operator ==(other) {
382 if (identical(this, other)) return true;
383 if (other is! ConstantExpression) return false;
384 if (kind != other.kind) return false;
385 if (hashCode != other.hashCode) return false;
386 return _equals(other);
387 }
388
389 String toString() {
390 assertDebugMode('Use ConstantExpression.getText() instead of '
391 'ConstantExpression.toString()');
392 return getText();
393 }
394 }
395
396 /// A synthetic constant used to recover from errors.
397 class ErroneousConstantExpression extends ConstantExpression {
398 ConstantExpressionKind get kind => ConstantExpressionKind.ERRONEOUS;
399
400 accept(ConstantExpressionVisitor visitor, [context]) {
401 // Do nothing. This is an error.
402 }
403
404 @override
405 ConstantValue evaluate(Environment environment,
406 ConstantSystem constantSystem) {
407 // TODO(johnniwinther): Use non-constant values for errors.
408 return new NonConstantValue();
409 }
410
411 @override
412 int _computeHashCode() => 13;
413
414 @override
415 bool _equals(ErroneousConstantExpression other) => true;
416 }
417
418 // TODO(johnniwinther): Avoid the need for this class.
419 class SyntheticConstantExpression extends ConstantExpression {
420 final SyntheticConstantValue value;
421
422 SyntheticConstantExpression(this.value);
423
424 @override
425 ConstantValue evaluate(Environment environment,
426 ConstantSystem constantSystem) {
427 return value;
428 }
429
430 @override
431 int _computeHashCode() => 13 * value.hashCode;
432
433 accept(ConstantExpressionVisitor visitor, [context]) {
434 throw "unsupported";
435 }
436
437 @override
438 bool _equals(SyntheticConstantExpression other) {
439 return value == other.value;
440 }
441
442 ConstantExpressionKind get kind => ConstantExpressionKind.SYNTHETIC;
443 }
444
445
446
447 /// A boolean, int, double, string, or null constant.
448 abstract class PrimitiveConstantExpression extends ConstantExpression {
449 /// The primitive value of this contant expression.
450 get primitiveValue;
451 }
452
453 /// Boolean literal constant.
454 class BoolConstantExpression extends PrimitiveConstantExpression {
455 final bool primitiveValue;
456
457 BoolConstantExpression(this.primitiveValue);
458
459 ConstantExpressionKind get kind => ConstantExpressionKind.BOOL;
460
461 accept(ConstantExpressionVisitor visitor, [context]) {
462 return visitor.visitBool(this, context);
463 }
464
465 @override
466 ConstantValue evaluate(Environment environment,
467 ConstantSystem constantSystem) {
468 return constantSystem.createBool(primitiveValue);
469 }
470
471 @override
472 int _computeHashCode() => 13 * primitiveValue.hashCode;
473
474 @override
475 bool _equals(BoolConstantExpression other) {
476 return primitiveValue == other.primitiveValue;
477 }
478
479 @override
480 DartType getKnownType(CoreTypes coreTypes) => coreTypes.boolType;
481 }
482
483 /// Integer literal constant.
484 class IntConstantExpression extends PrimitiveConstantExpression {
485 final int primitiveValue;
486
487 IntConstantExpression(this.primitiveValue);
488
489 ConstantExpressionKind get kind => ConstantExpressionKind.INT;
490
491 accept(ConstantExpressionVisitor visitor, [context]) {
492 return visitor.visitInt(this, context);
493 }
494
495 @override
496 ConstantValue evaluate(Environment environment,
497 ConstantSystem constantSystem) {
498 return constantSystem.createInt(primitiveValue);
499 }
500
501 @override
502 int _computeHashCode() => 17 * primitiveValue.hashCode;
503
504 @override
505 bool _equals(IntConstantExpression other) {
506 return primitiveValue == other.primitiveValue;
507 }
508
509 @override
510 DartType getKnownType(CoreTypes coreTypes) => coreTypes.intType;
511 }
512
513 /// Double literal constant.
514 class DoubleConstantExpression extends PrimitiveConstantExpression {
515 final double primitiveValue;
516
517 DoubleConstantExpression(this.primitiveValue);
518
519 ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE;
520
521 accept(ConstantExpressionVisitor visitor, [context]) {
522 return visitor.visitDouble(this, context);
523 }
524
525 @override
526 ConstantValue evaluate(Environment environment,
527 ConstantSystem constantSystem) {
528 return constantSystem.createDouble(primitiveValue);
529 }
530
531 @override
532 int _computeHashCode() => 19 * primitiveValue.hashCode;
533
534 @override
535 bool _equals(DoubleConstantExpression other) {
536 return primitiveValue == other.primitiveValue;
537 }
538
539 @override
540 DartType getKnownType(CoreTypes coreTypes) => coreTypes.doubleType;
541 }
542
543 /// String literal constant.
544 class StringConstantExpression extends PrimitiveConstantExpression {
545 final String primitiveValue;
546
547 StringConstantExpression(this.primitiveValue);
548
549 ConstantExpressionKind get kind => ConstantExpressionKind.STRING;
550
551 accept(ConstantExpressionVisitor visitor, [context]) {
552 return visitor.visitString(this, context);
553 }
554
555 @override
556 ConstantValue evaluate(Environment environment,
557 ConstantSystem constantSystem) {
558 return constantSystem.createString(new DartString.literal(primitiveValue));
559 }
560
561 @override
562 int _computeHashCode() => 23 * primitiveValue.hashCode;
563
564 @override
565 bool _equals(StringConstantExpression other) {
566 return primitiveValue == other.primitiveValue;
567 }
568
569 @override
570 DartType getKnownType(CoreTypes coreTypes) => coreTypes.stringType;
571 }
572
573 /// Null literal constant.
574 class NullConstantExpression extends PrimitiveConstantExpression {
575 NullConstantExpression();
576
577 ConstantExpressionKind get kind => ConstantExpressionKind.NULL;
578
579 accept(ConstantExpressionVisitor visitor, [context]) {
580 return visitor.visitNull(this, context);
581 }
582
583 @override
584 ConstantValue evaluate(Environment environment,
585 ConstantSystem constantSystem) {
586 return constantSystem.createNull();
587 }
588
589 get primitiveValue => null;
590
591 @override
592 int _computeHashCode() => 29;
593
594 @override
595 bool _equals(NullConstantExpression other) => true;
596
597 @override
598 DartType getKnownType(CoreTypes coreTypes) => coreTypes.nullType;
599 }
600
601 /// Literal list constant.
602 class ListConstantExpression extends ConstantExpression {
603 final InterfaceType type;
604 final List<ConstantExpression> values;
605
606 ListConstantExpression(this.type, this.values);
607
608 ConstantExpressionKind get kind => ConstantExpressionKind.LIST;
609
610 accept(ConstantExpressionVisitor visitor, [context]) {
611 return visitor.visitList(this, context);
612 }
613
614 @override
615 ConstantValue evaluate(Environment environment,
616 ConstantSystem constantSystem) {
617 return constantSystem.createList(type,
618 values.map((v) => v.evaluate(environment, constantSystem)).toList());
619 }
620
621 ConstantExpression apply(NormalizedArguments arguments) {
622 return new ListConstantExpression(
623 type, values.map((v) => v.apply(arguments)).toList());
624 }
625
626 @override
627 int _computeHashCode() {
628 int hashCode = 13 * type.hashCode + 17 * values.length;
629 for (ConstantExpression value in values) {
630 hashCode ^= 19 * value.hashCode;
631 }
632 return hashCode;
633 }
634
635 @override
636 bool _equals(ListConstantExpression other) {
637 if (type != other.type) return false;
638 if (values.length != other.values.length) return false;
639 for (int i = 0; i < values.length; i++) {
640 if (values[i] != other.values[i]) return false;
641 }
642 return true;
643 }
644
645 @override
646 DartType getKnownType(CoreTypes coreTypes) => type;
647 }
648
649 /// Literal map constant.
650 class MapConstantExpression extends ConstantExpression {
651 final InterfaceType type;
652 final List<ConstantExpression> keys;
653 final List<ConstantExpression> values;
654
655 MapConstantExpression(this.type, this.keys, this.values);
656
657 ConstantExpressionKind get kind => ConstantExpressionKind.MAP;
658
659 accept(ConstantExpressionVisitor visitor, [context]) {
660 return visitor.visitMap(this, context);
661 }
662
663 @override
664 ConstantValue evaluate(Environment environment,
665 ConstantSystem constantSystem) {
666 return constantSystem.createMap(environment.compiler,
667 type,
668 keys.map((k) => k.evaluate(environment, constantSystem)).toList(),
669 values.map((v) => v.evaluate(environment, constantSystem)).toList());
670 }
671
672 ConstantExpression apply(NormalizedArguments arguments) {
673 return new MapConstantExpression(
674 type,
675 keys.map((k) => k.apply(arguments)).toList(),
676 values.map((v) => v.apply(arguments)).toList());
677 }
678
679 @override
680 int _computeHashCode() {
681 int hashCode = 13 * type.hashCode + 17 * values.length;
682 for (ConstantExpression value in values) {
683 hashCode ^= 19 * value.hashCode;
684 }
685 return hashCode;
686 }
687
688 @override
689 bool _equals(MapConstantExpression other) {
690 if (type != other.type) return false;
691 if (values.length != other.values.length) return false;
692 for (int i = 0; i < values.length; i++) {
693 if (keys[i] != other.keys[i]) return false;
694 if (values[i] != other.values[i]) return false;
695 }
696 return true;
697 }
698
699 @override
700 DartType getKnownType(CoreTypes coreTypes) => type;
701 }
702
703 /// Invocation of a const constructor.
704 class ConstructedConstantExpression extends ConstantExpression {
705 final InterfaceType type;
706 final ConstructorElement target;
707 final CallStructure callStructure;
708 final List<ConstantExpression> arguments;
709
710 ConstructedConstantExpression(
711 this.type,
712 this.target,
713 this.callStructure,
714 this.arguments) {
715 assert(type.element == target.enclosingClass);
716 assert(!arguments.contains(null));
717 }
718
719 ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED;
720
721 accept(ConstantExpressionVisitor visitor, [context]) {
722 return visitor.visitConstructed(this, context);
723 }
724
725 Map<FieldElement, ConstantExpression> computeInstanceFields() {
726 return target.constantConstructor.computeInstanceFields(
727 arguments, callStructure);
728 }
729
730 InterfaceType computeInstanceType() {
731 return target.constantConstructor.computeInstanceType(type);
732 }
733
734 ConstructedConstantExpression apply(NormalizedArguments arguments) {
735 return new ConstructedConstantExpression(
736 type, target, callStructure,
737 this.arguments.map((a) => a.apply(arguments)).toList());
738 }
739
740 @override
741 ConstantValue evaluate(Environment environment,
742 ConstantSystem constantSystem) {
743 Map<FieldElement, ConstantValue> fieldValues =
744 <FieldElement, ConstantValue>{};
745 computeInstanceFields().forEach(
746 (FieldElement field, ConstantExpression constant) {
747 fieldValues[field] = constant.evaluate(environment, constantSystem);
748 });
749 return new ConstructedConstantValue(computeInstanceType(), fieldValues);
750 }
751
752 @override
753 int _computeHashCode() {
754 int hashCode =
755 13 * type.hashCode +
756 17 * target.hashCode +
757 19 * callStructure.hashCode;
758 for (ConstantExpression value in arguments) {
759 hashCode ^= 23 * value.hashCode;
760 }
761 return hashCode;
762 }
763
764 @override
765 bool _equals(ConstructedConstantExpression other) {
766 if (type != other.type) return false;
767 if (target != other.target) return false;
768 if (callStructure != other.callStructure) return false;
769 for (int i = 0; i < arguments.length; i++) {
770 if (arguments[i] != other.arguments[i]) return false;
771 }
772 return true;
773 }
774 }
775
776 /// String literal with juxtaposition and/or interpolations.
777 class ConcatenateConstantExpression extends ConstantExpression {
778 final List<ConstantExpression> expressions;
779
780 ConcatenateConstantExpression(this.expressions);
781
782 ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE;
783
784 accept(ConstantExpressionVisitor visitor, [context]) {
785 return visitor.visitConcatenate(this, context);
786 }
787
788 ConstantExpression apply(NormalizedArguments arguments) {
789 return new ConcatenateConstantExpression(
790 expressions.map((a) => a.apply(arguments)).toList());
791 }
792
793 @override
794 ConstantValue evaluate(Environment environment,
795 ConstantSystem constantSystem) {
796 DartString accumulator;
797 for (ConstantExpression expression in expressions) {
798 ConstantValue value = expression.evaluate(environment, constantSystem);
799 DartString valueString;
800 if (value.isNum || value.isBool) {
801 PrimitiveConstantValue primitive = value;
802 valueString =
803 new DartString.literal(primitive.primitiveValue.toString());
804 } else if (value.isString) {
805 PrimitiveConstantValue primitive = value;
806 valueString = primitive.primitiveValue;
807 } else {
808 // TODO(johnniwinther): Specialize message to indicated that the problem
809 // is not constness but the types of the const expressions.
810 return new NonConstantValue();
811 }
812 if (accumulator == null) {
813 accumulator = valueString;
814 } else {
815 accumulator = new DartString.concat(accumulator, valueString);
816 }
817 }
818 return constantSystem.createString(accumulator);
819 }
820
821 @override
822 int _computeHashCode() {
823 int hashCode = 17 * expressions.length;
824 for (ConstantExpression value in expressions) {
825 hashCode ^= 19 * value.hashCode;
826 }
827 return hashCode;
828 }
829
830 @override
831 bool _equals(ConcatenateConstantExpression other) {
832 if (expressions.length != other.expressions.length) return false;
833 for (int i = 0; i < expressions.length; i++) {
834 if (expressions[i] != other.expressions[i]) return false;
835 }
836 return true;
837 }
838
839 @override
840 DartType getKnownType(CoreTypes coreTypes) => coreTypes.stringType;
841 }
842
843 /// Symbol literal.
844 class SymbolConstantExpression extends ConstantExpression {
845 final String name;
846
847 SymbolConstantExpression(this.name);
848
849 ConstantExpressionKind get kind => ConstantExpressionKind.SYMBOL;
850
851 accept(ConstantExpressionVisitor visitor, [context]) {
852 return visitor.visitSymbol(this, context);
853 }
854
855 @override
856 int _computeHashCode() => 13 * name.hashCode;
857
858 @override
859 bool _equals(SymbolConstantExpression other) {
860 return name == other.name;
861 }
862
863 @override
864 ConstantValue evaluate(Environment environment,
865 ConstantSystem constantSystem) {
866 // TODO(johnniwinther): Implement this.
867 throw new UnsupportedError('SymbolConstantExpression.evaluate');
868 }
869
870 @override
871 DartType getKnownType(CoreTypes coreTypes) => coreTypes.symbolType;
872 }
873
874 /// Type literal.
875 class TypeConstantExpression extends ConstantExpression {
876 /// Either [DynamicType] or a raw [GenericType].
877 final DartType type;
878
879 TypeConstantExpression(this.type) {
880 assert(type is GenericType || type is DynamicType);
881 }
882
883 ConstantExpressionKind get kind => ConstantExpressionKind.TYPE;
884
885 accept(ConstantExpressionVisitor visitor, [context]) {
886 return visitor.visitType(this, context);
887 }
888
889 @override
890 ConstantValue evaluate(Environment environment,
891 ConstantSystem constantSystem) {
892 return constantSystem.createType(environment.compiler, type);
893 }
894
895 @override
896 int _computeHashCode() => 13 * type.hashCode;
897
898 @override
899 bool _equals(TypeConstantExpression other) {
900 return type == other.type;
901 }
902
903 @override
904 DartType getKnownType(CoreTypes coreTypes) => coreTypes.typeType;
905 }
906
907 /// Reference to a constant local, top-level, or static variable.
908 class VariableConstantExpression extends ConstantExpression {
909 final VariableElement element;
910
911 VariableConstantExpression(this.element);
912
913 ConstantExpressionKind get kind => ConstantExpressionKind.VARIABLE;
914
915 accept(ConstantExpressionVisitor visitor, [context]) {
916 return visitor.visitVariable(this, context);
917 }
918
919 @override
920 ConstantValue evaluate(Environment environment,
921 ConstantSystem constantSystem) {
922 return element.constant.evaluate(environment, constantSystem);
923 }
924
925 @override
926 int _computeHashCode() => 13 * element.hashCode;
927
928 @override
929 bool _equals(VariableConstantExpression other) {
930 return element == other.element;
931 }
932 }
933
934 /// Reference to a top-level or static function.
935 class FunctionConstantExpression extends ConstantExpression {
936 final FunctionElement element;
937
938 FunctionConstantExpression(this.element);
939
940 ConstantExpressionKind get kind => ConstantExpressionKind.FUNCTION;
941
942 accept(ConstantExpressionVisitor visitor, [context]) {
943 return visitor.visitFunction(this, context);
944 }
945
946 @override
947 ConstantValue evaluate(Environment environment,
948 ConstantSystem constantSystem) {
949 return new FunctionConstantValue(element);
950 }
951
952 @override
953 int _computeHashCode() => 13 * element.hashCode;
954
955 @override
956 bool _equals(FunctionConstantExpression other) {
957 return element == other.element;
958 }
959
960 @override
961 DartType getKnownType(CoreTypes coreTypes) => coreTypes.functionType;
962 }
963
964 /// A constant binary expression like `a * b`.
965 class BinaryConstantExpression extends ConstantExpression {
966 final ConstantExpression left;
967 final BinaryOperator operator;
968 final ConstantExpression right;
969
970 BinaryConstantExpression(this.left, this.operator, this.right) {
971 assert(PRECEDENCE_MAP[operator.kind] != null);
972 }
973
974 ConstantExpressionKind get kind => ConstantExpressionKind.BINARY;
975
976 accept(ConstantExpressionVisitor visitor, [context]) {
977 return visitor.visitBinary(this, context);
978 }
979
980 @override
981 ConstantValue evaluate(Environment environment,
982 ConstantSystem constantSystem) {
983 return constantSystem.lookupBinary(operator).fold(
984 left.evaluate(environment, constantSystem),
985 right.evaluate(environment, constantSystem));
986 }
987
988 ConstantExpression apply(NormalizedArguments arguments) {
989 return new BinaryConstantExpression(
990 left.apply(arguments),
991 operator,
992 right.apply(arguments));
993 }
994
995 DartType getKnownType(CoreTypes coreTypes) {
996 DartType knownLeftType = left.getKnownType(coreTypes);
997 DartType knownRightType = right.getKnownType(coreTypes);
998 switch (operator.kind) {
999 case BinaryOperatorKind.EQ:
1000 case BinaryOperatorKind.NOT_EQ:
1001 case BinaryOperatorKind.LOGICAL_AND:
1002 case BinaryOperatorKind.LOGICAL_OR:
1003 case BinaryOperatorKind.GT:
1004 case BinaryOperatorKind.LT:
1005 case BinaryOperatorKind.GTEQ:
1006 case BinaryOperatorKind.LTEQ:
1007 return coreTypes.boolType;
1008 case BinaryOperatorKind.ADD:
1009 if (knownLeftType == coreTypes.stringType) {
1010 assert(knownRightType == coreTypes.stringType);
1011 return coreTypes.stringType;
1012 } else if (knownLeftType == coreTypes.intType &&
1013 knownRightType == coreTypes.intType) {
1014 return coreTypes.intType;
1015 }
1016 assert(knownLeftType == coreTypes.doubleType ||
1017 knownRightType == coreTypes.doubleType);
1018 return coreTypes.doubleType;
1019 case BinaryOperatorKind.SUB:
1020 case BinaryOperatorKind.MUL:
1021 case BinaryOperatorKind.MOD:
1022 if (knownLeftType == coreTypes.intType &&
1023 knownRightType == coreTypes.intType) {
1024 return coreTypes.intType;
1025 }
1026 assert(knownLeftType == coreTypes.doubleType ||
1027 knownRightType == coreTypes.doubleType);
1028 return coreTypes.doubleType;
1029 case BinaryOperatorKind.DIV:
1030 return coreTypes.doubleType;
1031 case BinaryOperatorKind.IDIV:
1032 return coreTypes.intType;
1033 case BinaryOperatorKind.AND:
1034 case BinaryOperatorKind.OR:
1035 case BinaryOperatorKind.XOR:
1036 case BinaryOperatorKind.SHR:
1037 case BinaryOperatorKind.SHL:
1038 return coreTypes.intType;
1039 case BinaryOperatorKind.IF_NULL:
1040 case BinaryOperatorKind.INDEX:
1041 throw new UnsupportedError(
1042 'Unexpected constant binary operator: $operator');
1043 }
1044 }
1045
1046
1047 int get precedence => PRECEDENCE_MAP[operator.kind];
1048
1049 @override
1050 int _computeHashCode() {
1051 return 13 * operator.hashCode +
1052 17 * left.hashCode +
1053 19 * right.hashCode;
1054 }
1055
1056 @override
1057 bool _equals(BinaryConstantExpression other) {
1058 return operator == other.operator &&
1059 left == other.left &&
1060 right == other.right;
1061 }
1062
1063 static const Map<BinaryOperatorKind, int> PRECEDENCE_MAP = const {
1064 BinaryOperatorKind.EQ: 6,
1065 BinaryOperatorKind.NOT_EQ: 6,
1066 BinaryOperatorKind.LOGICAL_AND: 5,
1067 BinaryOperatorKind.LOGICAL_OR: 4,
1068 BinaryOperatorKind.XOR: 9,
1069 BinaryOperatorKind.AND: 10,
1070 BinaryOperatorKind.OR: 8,
1071 BinaryOperatorKind.SHR: 11,
1072 BinaryOperatorKind.SHL: 11,
1073 BinaryOperatorKind.ADD: 12,
1074 BinaryOperatorKind.SUB: 12,
1075 BinaryOperatorKind.MUL: 13,
1076 BinaryOperatorKind.DIV: 13,
1077 BinaryOperatorKind.IDIV: 13,
1078 BinaryOperatorKind.GT: 7,
1079 BinaryOperatorKind.LT: 7,
1080 BinaryOperatorKind.GTEQ: 7,
1081 BinaryOperatorKind.LTEQ: 7,
1082 BinaryOperatorKind.MOD: 13,
1083 };
1084 }
1085
1086 /// A constant identical invocation like `identical(a, b)`.
1087 class IdenticalConstantExpression extends ConstantExpression {
1088 final ConstantExpression left;
1089 final ConstantExpression right;
1090
1091 IdenticalConstantExpression(this.left, this.right);
1092
1093 ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL;
1094
1095 accept(ConstantExpressionVisitor visitor, [context]) {
1096 return visitor.visitIdentical(this, context);
1097 }
1098
1099 @override
1100 ConstantValue evaluate(Environment environment,
1101 ConstantSystem constantSystem) {
1102 return constantSystem.identity.fold(
1103 left.evaluate(environment, constantSystem),
1104 right.evaluate(environment, constantSystem));
1105 }
1106
1107 ConstantExpression apply(NormalizedArguments arguments) {
1108 return new IdenticalConstantExpression(
1109 left.apply(arguments),
1110 right.apply(arguments));
1111 }
1112
1113 int get precedence => 15;
1114
1115 @override
1116 int _computeHashCode() {
1117 return 17 * left.hashCode +
1118 19 * right.hashCode;
1119 }
1120
1121 @override
1122 bool _equals(IdenticalConstantExpression other) {
1123 return left == other.left &&
1124 right == other.right;
1125 }
1126
1127 @override
1128 DartType getKnownType(CoreTypes coreTypes) => coreTypes.boolType;
1129 }
1130
1131 /// A unary constant expression like `-a`.
1132 class UnaryConstantExpression extends ConstantExpression {
1133 final UnaryOperator operator;
1134 final ConstantExpression expression;
1135
1136 UnaryConstantExpression(this.operator, this.expression) {
1137 assert(PRECEDENCE_MAP[operator.kind] != null);
1138 }
1139
1140 ConstantExpressionKind get kind => ConstantExpressionKind.UNARY;
1141
1142 accept(ConstantExpressionVisitor visitor, [context]) {
1143 return visitor.visitUnary(this, context);
1144 }
1145
1146 @override
1147 ConstantValue evaluate(Environment environment,
1148 ConstantSystem constantSystem) {
1149 return constantSystem.lookupUnary(operator).fold(
1150 expression.evaluate(environment, constantSystem));
1151 }
1152
1153 ConstantExpression apply(NormalizedArguments arguments) {
1154 return new UnaryConstantExpression(
1155 operator,
1156 expression.apply(arguments));
1157 }
1158
1159 int get precedence => PRECEDENCE_MAP[operator.kind];
1160
1161 @override
1162 int _computeHashCode() {
1163 return 13 * operator.hashCode +
1164 17 * expression.hashCode;
1165 }
1166
1167 @override
1168 bool _equals(UnaryConstantExpression other) {
1169 return operator == other.operator &&
1170 expression == other.expression;
1171 }
1172
1173 @override
1174 DartType getKnownType(CoreTypes coreTypes) {
1175 return expression.getKnownType(coreTypes);
1176 }
1177
1178 static const Map<UnaryOperatorKind, int> PRECEDENCE_MAP = const {
1179 UnaryOperatorKind.NOT: 14,
1180 UnaryOperatorKind.COMPLEMENT: 14,
1181 UnaryOperatorKind.NEGATE: 14,
1182 };
1183 }
1184
1185
1186 /// A string length constant expression like `a.length`.
1187 class StringLengthConstantExpression extends ConstantExpression {
1188 final ConstantExpression expression;
1189
1190 StringLengthConstantExpression(this.expression);
1191
1192 ConstantExpressionKind get kind => ConstantExpressionKind.STRING_LENGTH;
1193
1194 accept(ConstantExpressionVisitor visitor, [context]) {
1195 return visitor.visitStringLength(this, context);
1196 }
1197
1198 @override
1199 ConstantValue evaluate(Environment environment,
1200 ConstantSystem constantSystem) {
1201 ConstantValue value = expression.evaluate(environment, constantSystem);
1202 if (value.isString) {
1203 StringConstantValue stringValue = value;
1204 return constantSystem.createInt(stringValue.primitiveValue.length);
1205 }
1206 return new NonConstantValue();
1207 }
1208
1209 ConstantExpression apply(NormalizedArguments arguments) {
1210 return new StringLengthConstantExpression(expression.apply(arguments));
1211 }
1212
1213 int get precedence => 15;
1214
1215 @override
1216 int _computeHashCode() {
1217 return 23 * expression.hashCode;
1218 }
1219
1220 @override
1221 bool _equals(StringLengthConstantExpression other) {
1222 return expression == other.expression;
1223 }
1224
1225 @override
1226 DartType getKnownType(CoreTypes coreTypes) => coreTypes.intType;
1227 }
1228
1229 /// A constant conditional expression like `a ? b : c`.
1230 class ConditionalConstantExpression extends ConstantExpression {
1231 final ConstantExpression condition;
1232 final ConstantExpression trueExp;
1233 final ConstantExpression falseExp;
1234
1235 ConditionalConstantExpression(this.condition,
1236 this.trueExp,
1237 this.falseExp);
1238
1239 ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL;
1240
1241 accept(ConstantExpressionVisitor visitor, [context]) {
1242 return visitor.visitConditional(this, context);
1243 }
1244
1245 ConstantExpression apply(NormalizedArguments arguments) {
1246 return new ConditionalConstantExpression(
1247 condition.apply(arguments),
1248 trueExp.apply(arguments),
1249 falseExp.apply(arguments));
1250 }
1251
1252 int get precedence => 3;
1253
1254 @override
1255 int _computeHashCode() {
1256 return 13 * condition.hashCode +
1257 17 * trueExp.hashCode +
1258 19 * falseExp.hashCode;
1259 }
1260
1261 @override
1262 bool _equals(ConditionalConstantExpression other) {
1263 return condition == other.condition &&
1264 trueExp == other.trueExp &&
1265 falseExp == other.falseExp;
1266 }
1267
1268 @override
1269 ConstantValue evaluate(Environment environment,
1270 ConstantSystem constantSystem) {
1271 ConstantValue conditionValue =
1272 condition.evaluate(environment, constantSystem);
1273 ConstantValue trueValue =
1274 trueExp.evaluate(environment, constantSystem);
1275 ConstantValue falseValue =
1276 falseExp.evaluate(environment, constantSystem);
1277 if (conditionValue.isTrue) {
1278 return trueValue;
1279 } else if (conditionValue.isFalse) {
1280 return falseValue;
1281 } else {
1282 return new NonConstantValue();
1283 }
1284 }
1285
1286 @override
1287 DartType getKnownType(CoreTypes coreTypes) {
1288 DartType trueType = trueExp.getKnownType(coreTypes);
1289 DartType falseType = falseExp.getKnownType(coreTypes);
1290 if (trueType == falseType) {
1291 return trueType;
1292 }
1293 return null;
1294 }
1295 }
1296
1297 /// A reference to a position parameter.
1298 class PositionalArgumentReference extends ConstantExpression {
1299 final int index;
1300
1301 PositionalArgumentReference(this.index);
1302
1303 ConstantExpressionKind get kind {
1304 return ConstantExpressionKind.POSITIONAL_REFERENCE;
1305 }
1306
1307 accept(ConstantExpressionVisitor visitor, [context]) {
1308 return visitor.visitPositional(this, context);
1309 }
1310
1311 ConstantExpression apply(NormalizedArguments arguments) {
1312 return arguments.getPositionalArgument(index);
1313 }
1314
1315 @override
1316 int _computeHashCode() => 13 * index.hashCode;
1317
1318 @override
1319 bool _equals(PositionalArgumentReference other) => index == other.index;
1320
1321 @override
1322 ConstantValue evaluate(Environment environment,
1323 ConstantSystem constantSystem) {
1324 throw new UnsupportedError('PositionalArgumentReference.evaluate');
1325 }
1326 }
1327
1328 /// A reference to a named parameter.
1329 class NamedArgumentReference extends ConstantExpression {
1330 final String name;
1331
1332 NamedArgumentReference(this.name);
1333
1334 ConstantExpressionKind get kind {
1335 return ConstantExpressionKind.NAMED_REFERENCE;
1336 }
1337
1338 accept(ConstantExpressionVisitor visitor, [context]) {
1339 return visitor.visitNamed(this, context);
1340 }
1341
1342 ConstantExpression apply(NormalizedArguments arguments) {
1343 return arguments.getNamedArgument(name);
1344 }
1345
1346 @override
1347 int _computeHashCode() => 13 * name.hashCode;
1348
1349 @override
1350 bool _equals(NamedArgumentReference other) => name == other.name;
1351
1352 @override
1353 ConstantValue evaluate(Environment environment,
1354 ConstantSystem constantSystem) {
1355 throw new UnsupportedError('NamedArgumentReference.evaluate');
1356 }
1357 }
1358
1359 abstract class FromEnvironmentConstantExpression extends ConstantExpression {
1360 final ConstantExpression name;
1361 final ConstantExpression defaultValue;
1362
1363 FromEnvironmentConstantExpression(this.name, this.defaultValue);
1364
1365 @override
1366 int _computeHashCode() {
1367 return 13 * name.hashCode +
1368 17 * defaultValue.hashCode;
1369 }
1370
1371 @override
1372 bool _equals(FromEnvironmentConstantExpression other) {
1373 return name == other.name &&
1374 defaultValue == other.defaultValue;
1375 }
1376 }
1377
1378 /// A `const bool.fromEnvironment` constant.
1379 class BoolFromEnvironmentConstantExpression
1380 extends FromEnvironmentConstantExpression {
1381
1382 BoolFromEnvironmentConstantExpression(
1383 ConstantExpression name,
1384 ConstantExpression defaultValue)
1385 : super(name, defaultValue);
1386
1387 ConstantExpressionKind get kind {
1388 return ConstantExpressionKind.BOOL_FROM_ENVIRONMENT;
1389 }
1390
1391 accept(ConstantExpressionVisitor visitor, [context]) {
1392 return visitor.visitBoolFromEnvironment(this, context);
1393 }
1394
1395 @override
1396 ConstantValue evaluate(Environment environment,
1397 ConstantSystem constantSystem) {
1398 ConstantValue nameConstantValue =
1399 name.evaluate(environment, constantSystem);
1400 ConstantValue defaultConstantValue;
1401 if (defaultValue != null) {
1402 defaultConstantValue =
1403 defaultValue.evaluate(environment, constantSystem);
1404 } else {
1405 defaultConstantValue = constantSystem.createBool(false);
1406 }
1407 if (!nameConstantValue.isString) {
1408 return new NonConstantValue();
1409 }
1410 StringConstantValue nameStringConstantValue = nameConstantValue;
1411 String text = environment.readFromEnvironment(
1412 nameStringConstantValue.primitiveValue.slowToString());
1413 if (text == 'true') {
1414 return constantSystem.createBool(true);
1415 } else if (text == 'false') {
1416 return constantSystem.createBool(false);
1417 } else {
1418 return defaultConstantValue;
1419 }
1420 }
1421
1422 ConstantExpression apply(NormalizedArguments arguments) {
1423 return new BoolFromEnvironmentConstantExpression(
1424 name.apply(arguments),
1425 defaultValue != null ? defaultValue.apply(arguments) : null);
1426 }
1427
1428 @override
1429 DartType getKnownType(CoreTypes coreTypes) => coreTypes.boolType;
1430 }
1431
1432 /// A `const int.fromEnvironment` constant.
1433 class IntFromEnvironmentConstantExpression
1434 extends FromEnvironmentConstantExpression {
1435
1436 IntFromEnvironmentConstantExpression(
1437 ConstantExpression name,
1438 ConstantExpression defaultValue)
1439 : super(name, defaultValue);
1440
1441 ConstantExpressionKind get kind {
1442 return ConstantExpressionKind.INT_FROM_ENVIRONMENT;
1443 }
1444
1445 accept(ConstantExpressionVisitor visitor, [context]) {
1446 return visitor.visitIntFromEnvironment(this, context);
1447 }
1448
1449 @override
1450 ConstantValue evaluate(Environment environment,
1451 ConstantSystem constantSystem) {
1452 ConstantValue nameConstantValue =
1453 name.evaluate(environment, constantSystem);
1454 ConstantValue defaultConstantValue;
1455 if (defaultValue != null) {
1456 defaultConstantValue =
1457 defaultValue.evaluate(environment, constantSystem);
1458 } else {
1459 defaultConstantValue = constantSystem.createNull();
1460 }
1461 if (!nameConstantValue.isString) {
1462 return new NonConstantValue();
1463 }
1464 StringConstantValue nameStringConstantValue = nameConstantValue;
1465 String text = environment.readFromEnvironment(
1466 nameStringConstantValue.primitiveValue.slowToString());
1467 int value;
1468 if (text != null) {
1469 value = int.parse(text, onError: (_) => null);
1470 }
1471 if (value == null) {
1472 return defaultConstantValue;
1473 } else {
1474 return constantSystem.createInt(value);
1475 }
1476 }
1477
1478 ConstantExpression apply(NormalizedArguments arguments) {
1479 return new IntFromEnvironmentConstantExpression(
1480 name.apply(arguments),
1481 defaultValue != null ? defaultValue.apply(arguments) : null);
1482 }
1483
1484 @override
1485 DartType getKnownType(CoreTypes coreTypes) => coreTypes.intType;
1486 }
1487
1488 /// A `const String.fromEnvironment` constant.
1489 class StringFromEnvironmentConstantExpression
1490 extends FromEnvironmentConstantExpression {
1491
1492 StringFromEnvironmentConstantExpression(
1493 ConstantExpression name,
1494 ConstantExpression defaultValue)
1495 : super(name, defaultValue);
1496
1497 ConstantExpressionKind get kind {
1498 return ConstantExpressionKind.STRING_FROM_ENVIRONMENT;
1499 }
1500
1501 accept(ConstantExpressionVisitor visitor, [context]) {
1502 return visitor.visitStringFromEnvironment(this, context);
1503 }
1504
1505 @override
1506 ConstantValue evaluate(Environment environment,
1507 ConstantSystem constantSystem) {
1508 ConstantValue nameConstantValue =
1509 name.evaluate(environment, constantSystem);
1510 ConstantValue defaultConstantValue;
1511 if (defaultValue != null) {
1512 defaultConstantValue =
1513 defaultValue.evaluate(environment, constantSystem);
1514 } else {
1515 defaultConstantValue = constantSystem.createNull();
1516 }
1517 if (!nameConstantValue.isString) {
1518 return new NonConstantValue();
1519 }
1520 StringConstantValue nameStringConstantValue = nameConstantValue;
1521 String text = environment.readFromEnvironment(
1522 nameStringConstantValue.primitiveValue.slowToString());
1523 if (text == null) {
1524 return defaultConstantValue;
1525 } else {
1526 return constantSystem.createString(new DartString.literal(text));
1527 }
1528 }
1529
1530 ConstantExpression apply(NormalizedArguments arguments) {
1531 return new StringFromEnvironmentConstantExpression(
1532 name.apply(arguments),
1533 defaultValue != null ? defaultValue.apply(arguments) : null);
1534 }
1535
1536 @override
1537 DartType getKnownType(CoreTypes coreTypes) => coreTypes.stringType;
1538 }
1539
1540 /// A constant expression referenced with a deferred prefix.
1541 /// For example `lib.C`.
1542 class DeferredConstantExpression extends ConstantExpression {
1543 final ConstantExpression expression;
1544 final PrefixElement prefix;
1545
1546 DeferredConstantExpression(this.expression, this.prefix);
1547
1548 ConstantExpressionKind get kind => ConstantExpressionKind.DEFERRED;
1549
1550 @override
1551 ConstantValue evaluate(Environment environment,
1552 ConstantSystem constantSystem) {
1553 return expression.evaluate(environment, constantSystem);
1554 }
1555
1556 @override
1557 int _computeHashCode() {
1558 return 13 * expression.hashCode;
1559 }
1560
1561 ConstantExpression apply(NormalizedArguments arguments) {
1562 return new DeferredConstantExpression(
1563 expression.apply(arguments), prefix);
1564 }
1565
1566 @override
1567 bool _equals(DeferredConstantExpression other) {
1568 return expression == other.expression;
1569 }
1570
1571 @override
1572 accept(ConstantExpressionVisitor visitor, [context]) {
1573 return visitor.visitDeferred(this, context);
1574 }
1575 }
1576
1577 abstract class ConstantExpressionVisitor<R, A> {
1578 const ConstantExpressionVisitor();
1579
1580 R visit(ConstantExpression constant, A context) {
1581 return constant.accept(this, context);
1582 }
1583
1584 R visitBool(BoolConstantExpression exp, A context);
1585 R visitInt(IntConstantExpression exp, A context);
1586 R visitDouble(DoubleConstantExpression exp, A context);
1587 R visitString(StringConstantExpression exp, A context);
1588 R visitNull(NullConstantExpression exp, A context);
1589 R visitList(ListConstantExpression exp, A context);
1590 R visitMap(MapConstantExpression exp, A context);
1591 R visitConstructed(ConstructedConstantExpression exp, A context);
1592 R visitConcatenate(ConcatenateConstantExpression exp, A context);
1593 R visitSymbol(SymbolConstantExpression exp, A context);
1594 R visitType(TypeConstantExpression exp, A context);
1595 R visitVariable(VariableConstantExpression exp, A context);
1596 R visitFunction(FunctionConstantExpression exp, A context);
1597 R visitBinary(BinaryConstantExpression exp, A context);
1598 R visitIdentical(IdenticalConstantExpression exp, A context);
1599 R visitUnary(UnaryConstantExpression exp, A context);
1600 R visitStringLength(StringLengthConstantExpression exp, A context);
1601 R visitConditional(ConditionalConstantExpression exp, A context);
1602 R visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
1603 A context);
1604 R visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp,
1605 A context);
1606 R visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp,
1607 A context);
1608 R visitDeferred(DeferredConstantExpression exp, A context);
1609
1610 R visitPositional(PositionalArgumentReference exp, A context);
1611 R visitNamed(NamedArgumentReference exp, A context);
1612 }
1613
1614 class ConstExpPrinter extends ConstantExpressionVisitor {
1615 final StringBuffer sb = new StringBuffer();
1616
1617 void write(ConstantExpression parent,
1618 ConstantExpression child,
1619 {bool leftAssociative: true}) {
1620 if (child.precedence < parent.precedence ||
1621 !leftAssociative && child.precedence == parent.precedence) {
1622 sb.write('(');
1623 child.accept(this);
1624 sb.write(')');
1625 } else {
1626 child.accept(this);
1627 }
1628 }
1629
1630 void writeTypeArguments(InterfaceType type) {
1631 if (type.treatAsRaw) return;
1632 sb.write('<');
1633 bool needsComma = false;
1634 for (DartType value in type.typeArguments) {
1635 if (needsComma) {
1636 sb.write(', ');
1637 }
1638 sb.write(value);
1639 needsComma = true;
1640 }
1641 sb.write('>');
1642 }
1643
1644 @override
1645 void visit(ConstantExpression constant, [_]) {
1646 return constant.accept(this, null);
1647 }
1648
1649 void visitPrimitive(PrimitiveConstantExpression exp) {
1650 sb.write(exp.primitiveValue);
1651 }
1652
1653 @override
1654 void visitBool(BoolConstantExpression exp, [_]) {
1655 visitPrimitive(exp);
1656 }
1657
1658 @override
1659 void visitDouble(DoubleConstantExpression exp, [_]) {
1660 visitPrimitive(exp);
1661 }
1662
1663 @override
1664 void visitInt(IntConstantExpression exp, [_]) {
1665 visitPrimitive(exp);
1666 }
1667
1668 @override
1669 void visitNull(NullConstantExpression exp, [_]) {
1670 visitPrimitive(exp);
1671 }
1672
1673 @override
1674 void visitString(StringConstantExpression exp, [_]) {
1675 // TODO(johnniwinther): Ensure correct escaping.
1676 sb.write('"${exp.primitiveValue}"');
1677 }
1678
1679 @override
1680 void visitList(ListConstantExpression exp, [_]) {
1681 sb.write('const ');
1682 writeTypeArguments(exp.type);
1683 sb.write('[');
1684 bool needsComma = false;
1685 for (ConstantExpression value in exp.values) {
1686 if (needsComma) {
1687 sb.write(', ');
1688 }
1689 visit(value);
1690 needsComma = true;
1691 }
1692 sb.write(']');
1693 }
1694
1695 @override
1696 void visitMap(MapConstantExpression exp, [_]) {
1697 sb.write('const ');
1698 writeTypeArguments(exp.type);
1699 sb.write('{');
1700 for (int index = 0; index < exp.keys.length; index++) {
1701 if (index > 0) {
1702 sb.write(', ');
1703 }
1704 visit(exp.keys[index]);
1705 sb.write(': ');
1706 visit(exp.values[index]);
1707 }
1708 sb.write('}');
1709 }
1710
1711 @override
1712 void visitConstructed(ConstructedConstantExpression exp, [_]) {
1713 sb.write('const ');
1714 sb.write(exp.target.enclosingClass.name);
1715 writeTypeArguments(exp.type);
1716 if (exp.target.name != '') {
1717 sb.write('.');
1718 sb.write(exp.target.name);
1719 }
1720 sb.write('(');
1721 bool needsComma = false;
1722
1723 int namedOffset = exp.callStructure.positionalArgumentCount;
1724 for (int index = 0; index < namedOffset; index++) {
1725 if (needsComma) {
1726 sb.write(', ');
1727 }
1728 visit(exp.arguments[index]);
1729 needsComma = true;
1730 }
1731 for (int index = 0; index < exp.callStructure.namedArgumentCount; index++) {
1732 if (needsComma) {
1733 sb.write(', ');
1734 }
1735 sb.write(exp.callStructure.namedArguments[index]);
1736 sb.write(': ');
1737 visit(exp.arguments[namedOffset + index]);
1738 needsComma = true;
1739 }
1740 sb.write(')');
1741 }
1742
1743 @override
1744 void visitConcatenate(ConcatenateConstantExpression exp, [_]) {
1745 sb.write('"');
1746 for (ConstantExpression expression in exp.expressions) {
1747 if (expression.kind == ConstantExpressionKind.STRING) {
1748 StringConstantExpression string = expression;
1749 // TODO(johnniwinther): Ensure correct escaping.
1750 sb.write('${string.primitiveValue}');
1751 } else {
1752 sb.write(r"${");
1753 visit(expression);
1754 sb.write("}");
1755 }
1756
1757 }
1758 sb.write('"');
1759 }
1760
1761 @override
1762 void visitSymbol(SymbolConstantExpression exp, [_]) {
1763 sb.write('#');
1764 sb.write(exp.name);
1765 }
1766
1767 @override
1768 void visitType(TypeConstantExpression exp, [_]) {
1769 sb.write(exp.type.name);
1770 }
1771
1772 @override
1773 void visitVariable(VariableConstantExpression exp, [_]) {
1774 if (exp.element.isStatic) {
1775 sb.write(exp.element.enclosingClass.name);
1776 sb.write('.');
1777 }
1778 sb.write(exp.element.name);
1779 }
1780
1781 @override
1782 void visitFunction(FunctionConstantExpression exp, [_]) {
1783 if (exp.element.isStatic) {
1784 sb.write(exp.element.enclosingClass.name);
1785 sb.write('.');
1786 }
1787 sb.write(exp.element.name);
1788 }
1789
1790 @override
1791 void visitBinary(BinaryConstantExpression exp, [_]) {
1792 write(exp, exp.left);
1793 sb.write(' ');
1794 sb.write(exp.operator.name);
1795 sb.write(' ');
1796 write(exp, exp.right);
1797 }
1798
1799 @override
1800 void visitIdentical(IdenticalConstantExpression exp, [_]) {
1801 sb.write('identical(');
1802 visit(exp.left);
1803 sb.write(', ');
1804 visit(exp.right);
1805 sb.write(')');
1806 }
1807
1808 @override
1809 void visitUnary(UnaryConstantExpression exp, [_]) {
1810 sb.write(exp.operator);
1811 write(exp, exp.expression);
1812 }
1813
1814 @override
1815 void visitStringLength(StringLengthConstantExpression exp, [_]) {
1816 write(exp, exp.expression, leftAssociative: false);
1817 sb.write('.length');
1818 }
1819
1820 @override
1821 void visitConditional(ConditionalConstantExpression exp, [_]) {
1822 write(exp, exp.condition, leftAssociative: false);
1823 sb.write(' ? ');
1824 write(exp, exp.trueExp);
1825 sb.write(' : ');
1826 write(exp, exp.falseExp);
1827 }
1828
1829 @override
1830 void visitPositional(PositionalArgumentReference exp, [_]) {
1831 // TODO(johnniwinther): Maybe this should throw.
1832 sb.write('args[${exp.index}]');
1833 }
1834
1835 @override
1836 void visitNamed(NamedArgumentReference exp, [_]) {
1837 // TODO(johnniwinther): Maybe this should throw.
1838 sb.write('args[${exp.name}]');
1839 }
1840
1841 @override
1842 void visitDeferred(DeferredConstantExpression exp, context) {
1843 sb.write(exp.prefix.deferredImport.prefix.source);
1844 sb.write('.');
1845 write(exp, exp.expression);
1846 }
1847
1848 @override
1849 void visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
1850 [_]) {
1851 sb.write('const bool.fromEnvironment(');
1852 visit(exp.name);
1853 if (exp.defaultValue != null) {
1854 sb.write(', defaultValue: ');
1855 visit(exp.defaultValue);
1856 }
1857 sb.write(')');
1858 }
1859
1860 @override
1861 void visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp, [_]) {
1862 sb.write('const int.fromEnvironment(');
1863 visit(exp.name);
1864 if (exp.defaultValue != null) {
1865 sb.write(', defaultValue: ');
1866 visit(exp.defaultValue);
1867 }
1868 sb.write(')');
1869 }
1870
1871 @override
1872 void visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp,
1873 [_]) {
1874 sb.write('const String.fromEnvironment(');
1875 visit(exp.name);
1876 if (exp.defaultValue != null) {
1877 sb.write(', defaultValue: ');
1878 visit(exp.defaultValue);
1879 }
1880 sb.write(')');
1881 }
1882
1883 String toString() => sb.toString();
1884 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/constants/constant_constructors.dart ('k') | pkg/compiler/lib/src/constants/evaluation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698