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

Side by Side Diff: frog/value.dart

Issue 9146001: continued cleanup of initialization and Value (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: touchups to comments Created 8 years, 11 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** 5 /**
6 * Represents a meta-value for code generation. 6 * Represents a meta-value for code generation.
7 */ 7 */
8 class Value { 8 class Value {
9 Type _type; 9 Type _type;
10 10
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 Value(this._type, this.code, this.span, [this.needsTemp = true]) { 49 Value(this._type, this.code, this.span, [this.needsTemp = true]) {
50 if (_type == null) world.internalError('type passed as null', span); 50 if (_type == null) world.internalError('type passed as null', span);
51 } 51 }
52 52
53 // TODO(jimhug): Replace with TypeValue. 53 // TODO(jimhug): Replace with TypeValue.
54 Value.type(this._type, this.span) 54 Value.type(this._type, this.span)
55 : code = null, needsTemp = false, isType = true { 55 : code = null, needsTemp = false, isType = true {
56 if (_type == null) world.internalError('type passed as null', span); 56 if (_type == null) world.internalError('type passed as null', span);
57 } 57 }
58 58
59 Value union(Value other) {
60 // TODO(jimhug): What the hell is right here?
61 if (this == other) return this;
62 world.internalError('not yet ready for union');
63 }
64
59 /** Is this value a constant expression? */ 65 /** Is this value a constant expression? */
60 bool get isConst() => false; 66 bool get isConst() => false;
61 67
62 /** If [isConst], the [EvaluatedValue] that defines this value. */ 68 /** If [isConst], the [EvaluatedValue] that defines this value. */
63 EvaluatedValue get constValue() => null; 69 EvaluatedValue get constValue() => null;
64 70
71 // TODO(jimhug): remove once type system works better.
72 setField(Member field, Value value, [bool duringInit = false]) { }
73
74 // Nothing to do in general?
75 validateInitialized(SourceSpan span) { }
76
65 // TODO(jimhug): Fix these names once get/set are truly pseudo-keywords. 77 // TODO(jimhug): Fix these names once get/set are truly pseudo-keywords.
66 // See issue #379. 78 // See issue #379.
67 Value get_(MethodGenerator context, String name, Node node) { 79 Value get_(MethodGenerator context, String name, Node node) {
68 final member = _resolveMember(context, name, node); 80 final member = _resolveMember(context, name, node);
69 if (member != null) { 81 if (member != null) {
70 return member._get(context, node, this); 82 return member._get(context, node, this);
71 } else { 83 } else {
72 return invokeNoSuchMethod(context, 'get:$name', node); 84 return invokeNoSuchMethod(context, 'get:$name', node);
73 } 85 }
74 } 86 }
75 87
76 Value set_(MethodGenerator context, String name, Node node, Value value, 88 Value set_(MethodGenerator context, String name, Node node, Value value,
77 [bool isDynamic=false]) { 89 [bool isDynamic=false]) {
78 90
79 final member = _resolveMember(context, name, node, isDynamic); 91 final member = _resolveMember(context, name, node, isDynamic);
80 if (member != null) { 92 if (member != null) {
81 return member._set(context, node, this, value, isDynamic); 93 return member._set(context, node, this, value, isDynamic);
82 } else { 94 } else {
83 return invokeNoSuchMethod(context, 'set:$name', node, 95 return invokeNoSuchMethod(context, 'set:$name', node,
84 new Arguments(null, [value])); 96 new Arguments(null, [value]));
85 } 97 }
86 } 98 }
87 99
100 Value unop(int kind, MethodGenerator context, var node) {
101 switch (kind) {
102 case TokenKind.NOT:
103 // TODO(jimhug): Issue #359 seeks to clarify this behavior.
104 var newVal = convertTo(context, world.nonNullBool);
105 return new Value(newVal.type, '!${newVal.code}', node.span);
106 case TokenKind.ADD:
107 world.error('no unary add operator in dart', node.span);
108 break;
109 case TokenKind.SUB:
110 return invoke(context, ':negate', node, Arguments.EMPTY);
111 case TokenKind.BIT_NOT:
112 return invoke(context, ':bit_not', node, Arguments.EMPTY);
113 }
114 world.internalError('unimplemented: ${node.op}', node.span);
115 }
116
88 Value binop(int kind, Value other, MethodGenerator context, var node) { 117 Value binop(int kind, Value other, MethodGenerator context, var node) {
89 switch (kind) { 118 switch (kind) {
90 case TokenKind.AND: 119 case TokenKind.AND:
91 case TokenKind.OR: 120 case TokenKind.OR:
92 final code = '${code} ${node.op} ${other.code}'; 121 final code = '${code} ${node.op} ${other.code}';
93 return new Value(world.nonNullBool, code, node.span); 122 return new Value(world.nonNullBool, code, node.span);
94 // TODO(jimhug): Lot's to resolve here. 123 // TODO(jimhug): Lot's to resolve here.
95 case TokenKind.EQ_STRICT: 124 case TokenKind.EQ_STRICT:
96 return new Value(world.nonNullBool, '${code} == ${other.code}', 125 return new Value(world.nonNullBool, '${code} == ${other.code}',
97 node.span); 126 node.span);
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 static Value fromString(String value, SourceSpan span) { 566 static Value fromString(String value, SourceSpan span) {
538 return new StringValue(value, true, span); 567 return new StringValue(value, true, span);
539 } 568 }
540 569
541 static Value fromNull(SourceSpan span) { 570 static Value fromNull(SourceSpan span) {
542 return new NullValue(true, span); 571 return new NullValue(true, span);
543 } 572 }
544 } 573 }
545 574
546 575
547 // rename to PrimitiveValue 576 // TODO(jimhug): rename to PrimitiveValue and refactor further
548 class EvaluatedValue extends Value implements Hashable { 577 class EvaluatedValue extends Value implements Hashable {
549 /** Is this value treated as const by dart language? */ 578 /** Is this value treated as const by dart language? */
550 bool isConst; 579 bool isConst;
551 580
552 EvaluatedValue(this.isConst, Type type, SourceSpan span): 581 EvaluatedValue(this.isConst, Type type, SourceSpan span):
553 super(type, '@@@', span, false); 582 super(type, '@@@', span, false);
554 583
555 String get code() => '@@@'; 584 String get code() => '@@@';
556 585
557 EvaluatedValue get constValue() => this; 586 EvaluatedValue get constValue() => this;
558 587
559 // TODO(jimhug): Using computed code here with caching is major perf fear. 588 // TODO(jimhug): Using computed code here without caching is major fear.
560 int hashCode() => code.hashCode(); 589 int hashCode() => code.hashCode();
561 590
562 bool operator ==(var other) { 591 bool operator ==(var other) {
563 return other is EvaluatedValue && other.type == this.type && 592 return other is EvaluatedValue && other.type == this.type &&
564 other.code == this.code; 593 other.code == this.code;
565 } 594 }
566 } 595 }
567 596
597
568 class NullValue extends EvaluatedValue { 598 class NullValue extends EvaluatedValue {
569 NullValue(bool isConst, SourceSpan span): 599 NullValue(bool isConst, SourceSpan span):
570 super(isConst, world.varType, span); 600 super(isConst, world.varType, span);
571 601
572 get actualValue() => null; 602 get actualValue() => null;
573 603
574 String get code() => 'null'; 604 String get code() => 'null';
575 605
576 Value binop(int kind, var other, MethodGenerator context, var node) { 606 Value binop(int kind, var other, MethodGenerator context, var node) {
577 // TODO(jimhug): Support int/double better 607 if (other is! NullValue) return super.binop(kind, other, context, node);
578 if (other is! ListValue) return super.binop(kind, other, context, node);
579 608
609 final c = isConst && other.isConst;
610 final s = node.span;
580 switch (kind) { 611 switch (kind) {
581 case TokenKind.EQ_STRICT: 612 case TokenKind.EQ_STRICT:
582 return new BoolValue(type == other.type && code == other.code, 613 case TokenKind.EQ:
583 isConst && other.isConst, node.span); 614 return new BoolValue(true, c, s);
584 case TokenKind.NE_STRICT: 615 case TokenKind.NE_STRICT:
585 return new BoolValue(type != other.type || code != other.code, 616 case TokenKind.NE:
586 isConst && other.isConst, node.span); 617 return new BoolValue(false, c, s);
587 } 618 }
588 619
589 // TODO(jimhug): Will flesh out ops here!
590 return super.binop(kind, other, context, node); 620 return super.binop(kind, other, context, node);
591 } 621 }
592 } 622 }
593 623
594 class BoolValue extends EvaluatedValue { 624 class BoolValue extends EvaluatedValue {
595 bool actualValue; 625 bool actualValue;
596 626
597 BoolValue(this.actualValue, bool isConst, SourceSpan span): 627 BoolValue(this.actualValue, bool isConst, SourceSpan span):
598 super(isConst, world.nonNullBool, span); 628 super(isConst, world.nonNullBool, span);
599 629
600 String get code() => actualValue ? 'true' : 'false'; 630 String get code() => actualValue ? 'true' : 'false';
601 631
632 Value unop(int kind, MethodGenerator context, var node) {
633 switch (kind) {
634 case TokenKind.NOT:
635 return new BoolValue(!actualValue, isConst, node.span);
636 }
637 return super.unop(kind, context, node);
638 }
639
602 Value binop(int kind, var other, MethodGenerator context, var node) { 640 Value binop(int kind, var other, MethodGenerator context, var node) {
603 if (other is! BoolValue) return super.binop(kind, other, context, node); 641 if (other is! BoolValue) return super.binop(kind, other, context, node);
604 642
643 final c = isConst && other.isConst;
644 final s = node.span;
645 bool x = actualValue, y = other.actualValue;
605 switch (kind) { 646 switch (kind) {
647 case TokenKind.EQ_STRICT:
648 case TokenKind.EQ:
649 return new BoolValue(x == y, c, s);
650 case TokenKind.NE_STRICT:
651 case TokenKind.NE:
652 return new BoolValue(x != y, c, s);
606 case TokenKind.AND: 653 case TokenKind.AND:
607 return new BoolValue(actualValue && other.actualValue, 654 return new BoolValue(x && y, c, s);
608 isConst && other.isConst, node.span);
609 case TokenKind.OR: 655 case TokenKind.OR:
610 return new BoolValue(actualValue || other.actualValue, 656 return new BoolValue(x || y, c, s);
611 isConst && other.isConst, node.span);
612 case TokenKind.EQ_STRICT:
613 return new BoolValue(actualValue == other.actualValue,
614 isConst && other.isConst, node.span);
615 case TokenKind.NE_STRICT:
616 return new BoolValue(actualValue != other.actualValue,
617 isConst && other.isConst, node.span);
618 } 657 }
619 658
620 // TODO(jimhug): Could handle more ops here, but does it matter?
621 return super.binop(kind, other, context, node); 659 return super.binop(kind, other, context, node);
622 } 660 }
623 } 661 }
624 662
625 class IntValue extends EvaluatedValue { 663 class IntValue extends EvaluatedValue {
626 int actualValue; 664 int actualValue;
627 665
628 IntValue(this.actualValue, bool isConst, SourceSpan span): 666 IntValue(this.actualValue, bool isConst, SourceSpan span):
629 super(isConst, world.intType, span); 667 super(isConst, world.intType, span);
630 668
631 // TODO(jimhug): Only add parens when needed. 669 // TODO(jimhug): Only add parens when needed.
632 String get code() => '(${actualValue})'; 670 String get code() => '(${actualValue})';
633 671
672 Value unop(int kind, MethodGenerator context, var node) {
673 switch (kind) {
674 case TokenKind.ADD:
675 // This is allowed on numeric constants only
676 return new IntValue(actualValue, isConst, span);
677 case TokenKind.SUB:
678 return new IntValue(-actualValue, isConst, span);
679 case TokenKind.BIT_NOT:
680 return new IntValue(~actualValue, isConst, span);
681 }
682 return super.unop(kind, context, node);
683 }
684
685
634 Value binop(int kind, var other, MethodGenerator context, var node) { 686 Value binop(int kind, var other, MethodGenerator context, var node) {
635 // TODO(jimhug): Support int/double better 687 final c = isConst && other.isConst;
636 if (other is! IntValue) return super.binop(kind, other, context, node); 688 final s = node.span;
689 if (other is IntValue) {
690 int x = actualValue;
691 int y = other.actualValue;
692 switch (kind) {
693 case TokenKind.EQ_STRICT:
694 case TokenKind.EQ:
695 return new BoolValue(x == y, c, s);
696 case TokenKind.NE_STRICT:
697 case TokenKind.NE:
698 return new BoolValue(x != y, c, s);
637 699
638 switch (kind) { 700 case TokenKind.BIT_OR:
639 case TokenKind.EQ_STRICT: 701 return new IntValue(x | y, c, s);
640 return new BoolValue(actualValue == other.actualValue, 702 case TokenKind.BIT_XOR:
641 isConst && other.isConst, node.span); 703 return new IntValue(x ^ y, c, s);
642 case TokenKind.NE_STRICT: 704 case TokenKind.BIT_AND:
643 return new BoolValue(actualValue != other.actualValue, 705 return new IntValue(x & y, c, s);
644 isConst && other.isConst, node.span); 706 case TokenKind.SHL:
707 return new IntValue(x << y, c, s);
708 case TokenKind.SAR:
709 return new IntValue(x >> y, c, s);
710 case TokenKind.SHR:
711 return new IntValue(x >>> y, c, s);
712 case TokenKind.ADD:
713 return new IntValue(x + y, c, s);
714 case TokenKind.SUB:
715 return new IntValue(x - y, c, s);
716 case TokenKind.MUL:
717 return new IntValue(x * y, c, s);
718 case TokenKind.DIV:
719 return new DoubleValue(x / y, c, s);
720 case TokenKind.TRUNCDIV:
721 return new IntValue(x ~/ y, c, s);
722 case TokenKind.MOD:
723 return new IntValue(x % y, c, s);
724 case TokenKind.LT:
725 return new BoolValue(x < y, c, s);
726 case TokenKind.GT:
727 return new BoolValue(x > y, c, s);
728 case TokenKind.LTE:
729 return new BoolValue(x <= y, c, s);
730 case TokenKind.GTE:
731 return new BoolValue(x >= y, c, s);
732 }
733 } else if (other is DoubleValue) {
734 int x = actualValue;
735 double y = other.actualValue;
736 switch (kind) {
737 case TokenKind.EQ_STRICT:
738 case TokenKind.EQ:
739 return new BoolValue(x == y, c, s);
740 case TokenKind.NE_STRICT:
741 case TokenKind.NE:
742 return new BoolValue(x != y, c, s);
743
744 case TokenKind.ADD:
745 return new DoubleValue(x + y, c, s);
746 case TokenKind.SUB:
747 return new DoubleValue(x - y, c, s);
748 case TokenKind.MUL:
749 return new DoubleValue(x * y, c, s);
750 case TokenKind.DIV:
751 return new DoubleValue(x / y, c, s);
752 case TokenKind.TRUNCDIV:
753 // TODO(jimhug): I expected int, but corelib says double here...
754 return new DoubleValue(x ~/ y, c, s);
755 case TokenKind.MOD:
756 return new DoubleValue(x % y, c, s);
757 case TokenKind.LT:
758 return new BoolValue(x < y, c, s);
759 case TokenKind.GT:
760 return new BoolValue(x > y, c, s);
761 case TokenKind.LTE:
762 return new BoolValue(x <= y, c, s);
763 case TokenKind.GTE:
764 return new BoolValue(x >= y, c, s);
765 }
645 } 766 }
646 767
647 // TODO(jimhug): Will flesh out ops here!
648 return super.binop(kind, other, context, node); 768 return super.binop(kind, other, context, node);
649 } 769 }
650 } 770 }
651 771
652 class DoubleValue extends EvaluatedValue { 772 class DoubleValue extends EvaluatedValue {
653 double actualValue; 773 double actualValue;
654 774
655 DoubleValue(this.actualValue, bool isConst, SourceSpan span): 775 DoubleValue(this.actualValue, bool isConst, SourceSpan span):
656 super(isConst, world.doubleType, span); 776 super(isConst, world.doubleType, span);
657 777
658 String get code() => '(${actualValue})'; 778 String get code() => '(${actualValue})';
659 779
780 Value unop(int kind, MethodGenerator context, var node) {
781 switch (kind) {
782 case TokenKind.ADD:
783 // This is allowed on numeric constants only
784 return new DoubleValue(actualValue, isConst, span);
785 case TokenKind.SUB:
786 return new DoubleValue(-actualValue, isConst, span);
787 }
788 return super.unop(kind, context, node);
789 }
790
660 Value binop(int kind, var other, MethodGenerator context, var node) { 791 Value binop(int kind, var other, MethodGenerator context, var node) {
661 // TODO(jimhug): Support int/double better 792 final c = isConst && other.isConst;
662 if (other is! DoubleValue) return super.binop(kind, other, context, node); 793 final s = node.span;
794 if (other is DoubleValue) {
795 double x = actualValue;
796 double y = other.actualValue;
797 switch (kind) {
798 case TokenKind.EQ_STRICT:
799 case TokenKind.EQ:
800 return new BoolValue(x == y, c, s);
801 case TokenKind.NE_STRICT:
802 case TokenKind.NE:
803 return new BoolValue(x != y, c, s);
663 804
664 switch (kind) { 805 case TokenKind.ADD:
665 case TokenKind.EQ_STRICT: 806 return new DoubleValue(x + y, c, s);
666 return new BoolValue(actualValue == other.actualValue, 807 case TokenKind.SUB:
667 isConst && other.isConst, node.span); 808 return new DoubleValue(x - y, c, s);
668 case TokenKind.NE_STRICT: 809 case TokenKind.MUL:
669 return new BoolValue(actualValue != other.actualValue, 810 return new DoubleValue(x * y, c, s);
670 isConst && other.isConst, node.span); 811 case TokenKind.DIV:
812 return new DoubleValue(x / y, c, s);
813 case TokenKind.TRUNCDIV:
814 // TODO(jimhug): I expected int, but corelib says double here...
815 return new DoubleValue(x ~/ y, c, s);
816 case TokenKind.MOD:
817 return new DoubleValue(x % y, c, s);
818 case TokenKind.LT:
819 return new BoolValue(x < y, c, s);
820 case TokenKind.GT:
821 return new BoolValue(x > y, c, s);
822 case TokenKind.LTE:
823 return new BoolValue(x <= y, c, s);
824 case TokenKind.GTE:
825 return new BoolValue(x >= y, c, s);
826 }
827 } else if (other is IntValue) {
828 double x = actualValue;
829 int y = other.actualValue;
830 switch (kind) {
831 case TokenKind.EQ_STRICT:
832 case TokenKind.EQ:
833 return new BoolValue(x == y, c, s);
834 case TokenKind.NE_STRICT:
835 case TokenKind.NE:
836 return new BoolValue(x != y, c, s);
837
838 case TokenKind.ADD:
839 return new DoubleValue(x + y, c, s);
840 case TokenKind.SUB:
841 return new DoubleValue(x - y, c, s);
842 case TokenKind.MUL:
843 return new DoubleValue(x * y, c, s);
844 case TokenKind.DIV:
845 return new DoubleValue(x / y, c, s);
846 case TokenKind.TRUNCDIV:
847 // TODO(jimhug): I expected int, but corelib says double here...
848 return new DoubleValue(x ~/ y, c, s);
849 case TokenKind.MOD:
850 return new DoubleValue(x % y, c, s);
851 case TokenKind.LT:
852 return new BoolValue(x < y, c, s);
853 case TokenKind.GT:
854 return new BoolValue(x > y, c, s);
855 case TokenKind.LTE:
856 return new BoolValue(x <= y, c, s);
857 case TokenKind.GTE:
858 return new BoolValue(x >= y, c, s);
859 }
671 } 860 }
672 861
673 // TODO(jimhug): Will flesh out ops here!
674 return super.binop(kind, other, context, node); 862 return super.binop(kind, other, context, node);
675 } 863 }
676 } 864 }
677 865
678 class StringValue extends EvaluatedValue { 866 class StringValue extends EvaluatedValue {
679 String actualValue; 867 String actualValue;
680 868
681 StringValue(this.actualValue, bool isConst, SourceSpan span): 869 StringValue(this.actualValue, bool isConst, SourceSpan span):
682 super(isConst, world.stringType, span); 870 super(isConst, world.stringType, span);
683 871
684 Value binop(int kind, var other, MethodGenerator context, var node) { 872 Value binop(int kind, var other, MethodGenerator context, var node) {
685 // TODO(jimhug): Support int/double better
686 if (other is! StringValue) return super.binop(kind, other, context, node); 873 if (other is! StringValue) return super.binop(kind, other, context, node);
687 874
875 final c = isConst && other.isConst;
876 final s = node.span;
877 String x = actualValue, y = other.actualValue;
688 switch (kind) { 878 switch (kind) {
689 case TokenKind.EQ_STRICT: 879 case TokenKind.EQ_STRICT:
690 return new BoolValue(actualValue == other.actualValue, 880 case TokenKind.EQ:
691 isConst && other.isConst, node.span); 881 return new BoolValue(x == y, c, s);
692 case TokenKind.NE_STRICT: 882 case TokenKind.NE_STRICT:
693 return new BoolValue(actualValue != other.actualValue, 883 case TokenKind.NE:
694 isConst && other.isConst, node.span); 884 return new BoolValue(x != y, c, s);
885 case TokenKind.ADD:
886 return new StringValue(x + y, c, s);
695 } 887 }
696 888
697 // TODO(jimhug): Will flesh out ops here!
698 return super.binop(kind, other, context, node); 889 return super.binop(kind, other, context, node);
699 } 890 }
700 891
701 892
702 // This is expensive and we may want to cache its value if called often 893 // This is expensive and we may want to cache its value if called often
703 String get code() { 894 String get code() {
704 // TODO(jimhug): This could be much more efficient 895 // TODO(jimhug): This could be much more efficient
705 StringBuffer buf = new StringBuffer(); 896 StringBuffer buf = new StringBuffer();
706 buf.add('"'); 897 buf.add('"');
707 for (int i=0; i < actualValue.length; i++) { 898 for (int i=0; i < actualValue.length; i++) {
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 return new BoolValue(type != other.type || code != other.code, 1011 return new BoolValue(type != other.type || code != other.code,
821 isConst && other.isConst, node.span); 1012 isConst && other.isConst, node.span);
822 } 1013 }
823 1014
824 return super.binop(kind, other, context, node); 1015 return super.binop(kind, other, context, node);
825 } 1016 }
826 } 1017 }
827 1018
828 1019
829 class ObjectValue extends EvaluatedValue { 1020 class ObjectValue extends EvaluatedValue {
830 Map<String, Value> fields; 1021 Map<FieldMember, Value> fields;
1022 bool seenNativeInitializer = false;
1023
831 String _code; 1024 String _code;
832 1025
833 ObjectValue(this.fields, bool isConst, Type type, this._code, SourceSpan span) : 1026 ObjectValue(bool isConst, Type type, SourceSpan span):
834 super(isConst, type, span); 1027 fields = {}, super(isConst, type, span);
835 1028
836 String get code() { 1029 String get code() {
1030 if (_code === null) validateInitialized(null);
837 return _code; 1031 return _code;
838 } 1032 }
839 1033
1034 initFields() {
1035 var allMembers = world.gen._orderValues(type.getAllMembers());
1036 for (var f in allMembers) {
1037 if (f.isField && !f.isStatic && f.declaringType.isClass) {
1038 fields[f] = f.computeValue();
1039 }
1040 }
1041 }
1042
1043 setField(Member field, Value value, [bool duringInit = false]) {
1044 var currentValue = fields[field];
1045 if (isConst && !value.isConst) {
1046 world.error('used of non-const value in const intializer', value.span);
1047 }
1048
1049 if (currentValue === null) {
1050 fields[field] = value;
1051 if (field.isFinal && !duringInit) {
1052 world.error('can not initialize final fields outside of initializer',
1053 value.span);
1054 }
1055 } else {
1056 // TODO(jimhug): Clarify spec on reinitializing fields with defaults.
1057 if (field.isFinal && field.computeValue() === null) {
1058 world.error('reassignment of field not allowed', value.span,
1059 field.span);
1060 } else {
1061 fields[field] = value; //currentValue.union(value);
1062 }
1063 }
1064 }
1065
1066 validateInitialized(SourceSpan span) {
1067 var buf = new StringBuffer();
1068 buf.add('Object.create(');
1069 buf.add('${type.jsname}.prototype, ');
1070
1071 buf.add('{');
1072 for (var field in fields.getKeys()) {
1073 buf.add(field.name);
1074 buf.add(': ');
1075 buf.add('{"value": ');
1076 if (fields[field] === null) {
1077 world.error('Required field "${field.name}" was not initialized',
1078 span, field.span);
1079 buf.add('null');
1080 } else {
1081 buf.add(fields[field].code);
1082 }
1083 buf.add(', writeable: false}, ');
1084 }
1085 buf.add('})');
1086 _code = buf.toString();
1087 }
1088
840 Value binop(int kind, var other, MethodGenerator context, var node) { 1089 Value binop(int kind, var other, MethodGenerator context, var node) {
841 if (other is! ObjectValue) return super.binop(kind, other, context, node); 1090 if (other is! ObjectValue) return super.binop(kind, other, context, node);
842 1091
843 switch (kind) { 1092 switch (kind) {
844 case TokenKind.EQ_STRICT: 1093 case TokenKind.EQ_STRICT:
1094 case TokenKind.EQ:
845 return new BoolValue(type == other.type && code == other.code, 1095 return new BoolValue(type == other.type && code == other.code,
846 isConst && other.isConst, node.span); 1096 isConst && other.isConst, node.span);
847 case TokenKind.NE_STRICT: 1097 case TokenKind.NE_STRICT:
1098 case TokenKind.NE:
848 return new BoolValue(type != other.type || code != other.code, 1099 return new BoolValue(type != other.type || code != other.code,
849 isConst && other.isConst, node.span); 1100 isConst && other.isConst, node.span);
850 } 1101 }
851 1102
852 return super.binop(kind, other, context, node); 1103 return super.binop(kind, other, context, node);
853 } 1104 }
854 1105
855 } 1106 }
856 1107
857 1108
858 /** An evaluated constant object expression. */
859 /*
860 class ConstObjectValue extends EvaluatedValue {
861 Map<String, EvaluatedValue> fields;
862
863 factory ConstObjectValue(
864 Type type, Map<String, EvaluatedValue> fields,
865 String canonicalCode, SourceSpan span) {
866 // compute a unique-string form used to index this value in the global const
867 // map. This is used to ensure that multiple const object values are
868 // equivalent if they have the same type name and values on each field.
869 final fieldValues = [];
870 for (var f in fields.getKeys()) {
871 fieldValues.add('$f = ${fields[f].actualValue}');
872 }
873 fieldValues.sort((a, b) => a.compareTo(b));
874 final actualValue = 'const ${type.jsname} ['
875 + Strings.join(fieldValues, ',') + ']';
876 return new ConstObjectValue._internal(type, fields, actualValue,
877 canonicalCode, span, codeWithComments(canonicalCode, span));
878 }
879
880 ConstObjectValue._internal(type, this.fields,
881 actualValue, canonicalCode, span, code) :
882 super._internal(type, actualValue, canonicalCode, span, code);
883 }
884 */
885
886 /** 1109 /**
887 * A global value in the generated code, which corresponds to either a static 1110 * A global value in the generated code, which corresponds to either a static
888 * field or a memoized const expressions. 1111 * field or a memoized const expressions.
889 */ 1112 */
890 class GlobalValue extends Value implements Comparable { 1113 class GlobalValue extends Value implements Comparable {
891 /** Static field definition (null for constant exp). */ 1114 /** Static field definition (null for constant exp). */
892 FieldMember field; 1115 FieldMember field;
893 1116
894 /** 1117 /**
895 * When [this] represents a constant expression, the global variable name 1118 * When [this] represents a constant expression, the global variable name
896 * generated for it. 1119 * generated for it.
897 */ 1120 */
898 String name; 1121 String name;
899 1122
900 /** The value of the field or constant expression to declare. */ 1123 /** The value of the field or constant expression to declare. */
901 Value exp; 1124 Value exp;
902 1125
903
904 /** True for either cont expressions or a final static field. */ 1126 /** True for either cont expressions or a final static field. */
905 bool get isConst() => exp.isConst && (field == null || field.isFinal); 1127 bool isConst;
906 1128
907 /** The actual constant value, when [isConst] is true. */ 1129 /** The actual constant value, when [isConst] is true. */
908 get actualValue() => exp.dynamic.actualValue; 1130 get actualValue() => exp.dynamic.actualValue;
909 1131
910 /** If [isConst], the [EvaluatedValue] that defines this value. */ 1132 /** If [isConst], the [EvaluatedValue] that defines this value. */
911 EvaluatedValue get constValue() => isConst ? exp.constValue : null; 1133 EvaluatedValue get constValue() => isConst ? exp.constValue : null;
912 1134
913 /** Other globals that should be defined before this global. */ 1135 /** Other globals that should be defined before this global. */
914 List<GlobalValue> dependencies; 1136 List<GlobalValue> dependencies;
915 1137
916 GlobalValue(Type type, String code, bool isConst, 1138 GlobalValue(Type type, String code, bool isConst,
917 this.field, this.name, this.exp, 1139 this.field, this.name, this.exp,
918 SourceSpan span, List<Value> _dependencies) 1140 SourceSpan span, List<Value> _dependencies)
919 : super(type, code, span, !isConst), dependencies = [] { 1141 : super(type, code, span, !isConst),
1142 dependencies = [], isConst = isConst {
920 // store transitive-dependencies so sorting algorithm works correctly. 1143 // store transitive-dependencies so sorting algorithm works correctly.
921 for (var dep in _dependencies) { 1144 for (var dep in _dependencies) {
922 if (dep is GlobalValue) { 1145 if (dep is GlobalValue) {
923 dependencies.add(dep); 1146 dependencies.add(dep);
924 dependencies.addAll(dep.dependencies); 1147 dependencies.addAll(dep.dependencies);
925 } 1148 }
926 } 1149 }
927 } 1150 }
928 1151
929 int compareTo(GlobalValue other) { 1152 int compareTo(GlobalValue other) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 } 1221 }
999 1222
1000 _ensureCode(); 1223 _ensureCode();
1001 return null; 1224 return null;
1002 } 1225 }
1003 } 1226 }
1004 1227
1005 String _escapeForComment(String text) { 1228 String _escapeForComment(String text) {
1006 return text.replaceAll('/*', '/ *').replaceAll('*/', '* /'); 1229 return text.replaceAll('/*', '/ *').replaceAll('*/', '* /');
1007 } 1230 }
OLDNEW
« frog/member.dart ('K') | « frog/minfrog ('k') | tests/corelib/corelib.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698