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

Side by Side Diff: pkg/compiler/lib/src/serialization/equivalence.dart

Issue 1873573004: Serialize TreeElements (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 /// Functions for asserting equivalence across serialization. 5 /// Functions for asserting equivalence across serialization.
6 6
7 library dart2js.serialization.equivalence; 7 library dart2js.serialization.equivalence;
8 8
9 import '../common/resolution.dart'; 9 import '../common/resolution.dart';
10 import '../constants/expressions.dart'; 10 import '../constants/expressions.dart';
11 import '../dart_types.dart'; 11 import '../dart_types.dart';
12 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
13 import '../elements/visitor.dart'; 13 import '../elements/visitor.dart';
14 import '../resolution/send_structure.dart';
15 import '../resolution/tree_elements.dart';
16 import '../tokens/token.dart';
17 import '../tree/nodes.dart';
14 import '../universe/selector.dart'; 18 import '../universe/selector.dart';
15 import '../universe/use.dart'; 19 import '../universe/use.dart';
20 import 'resolved_ast_serialization.dart';
21
16 22
17 /// Equality based equivalence function. 23 /// Equality based equivalence function.
18 bool equality(a, b) => a == b; 24 bool equality(a, b) => a == b;
19 25
20 /// Returns `true` if the elements in [a] and [b] are pair-wise equivalent 26 /// Returns `true` if the elements in [a] and [b] are pair-wise equivalent
21 /// according to [elementEquivalence]. 27 /// according to [elementEquivalence].
22 bool areListsEquivalent( 28 bool areListsEquivalent(
23 List a, 29 List a,
24 List b, 30 List b,
25 [bool elementEquivalence(a, b) = equality]) { 31 [bool elementEquivalence(a, b) = equality]) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 } 94 }
89 95
90 /// Returns `true` if the lists of constants, [a] and [b], are equivalent. 96 /// Returns `true` if the lists of constants, [a] and [b], are equivalent.
91 bool areConstantListsEquivalent(List<ConstantExpression> a, 97 bool areConstantListsEquivalent(List<ConstantExpression> a,
92 List<ConstantExpression> b) { 98 List<ConstantExpression> b) {
93 return areListsEquivalent(a, b, areConstantsEquivalent); 99 return areListsEquivalent(a, b, areConstantsEquivalent);
94 } 100 }
95 101
96 /// Returns `true` if the selectors [a] and [b] are equivalent. 102 /// Returns `true` if the selectors [a] and [b] are equivalent.
97 bool areSelectorsEquivalent(Selector a, Selector b) { 103 bool areSelectorsEquivalent(Selector a, Selector b) {
104 if (identical(a, b)) return true;
105 if (a == null || b == null) return false;
98 return a.kind == b.kind && 106 return a.kind == b.kind &&
99 a.callStructure == b.callStructure && 107 a.callStructure == b.callStructure &&
100 areNamesEquivalent(a.memberName, b.memberName); 108 areNamesEquivalent(a.memberName, b.memberName);
101 } 109 }
102 110
103 /// Returns `true` if the names [a] and [b] are equivalent. 111 /// Returns `true` if the names [a] and [b] are equivalent.
104 bool areNamesEquivalent(Name a, Name b) { 112 bool areNamesEquivalent(Name a, Name b) {
105 return a.text == b.text && 113 return a.text == b.text &&
106 a.isSetter == b.isSetter && 114 a.isSetter == b.isSetter &&
107 areElementsEquivalent(a.library, b.library); 115 areElementsEquivalent(a.library, b.library);
(...skipping 23 matching lines...) Expand all
131 a.isEmpty == b.isEmpty; 139 a.isEmpty == b.isEmpty;
132 } 140 }
133 141
134 /// Returns `true` if the map literal uses [a] and [b] are equivalent. 142 /// Returns `true` if the map literal uses [a] and [b] are equivalent.
135 bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) { 143 bool areMapLiteralUsesEquivalent(MapLiteralUse a, MapLiteralUse b) {
136 return areTypesEquivalent(a.type, b.type) && 144 return areTypesEquivalent(a.type, b.type) &&
137 a.isConstant == b.isConstant && 145 a.isConstant == b.isConstant &&
138 a.isEmpty == b.isEmpty; 146 a.isEmpty == b.isEmpty;
139 } 147 }
140 148
149 /// Returns `true` if the send structures [a] and [b] are equivalent.
150 bool areSendStructuresEquivalent(SendStructure a, SendStructure b) {
151 if (identical(a, b)) return true;
152 if (a == null || b == null) return false;
153 if (a.kind != b.kind) return false;
154 // TODO(johnniwinther): Compute a deep equivalence.
155 return true;
156 }
157
158 /// Returns `true` if the new structures [a] and [b] are equivalent.
159 bool areNewStructuresEquivalent(NewStructure a, NewStructure b) {
160 if (identical(a, b)) return true;
161 if (a == null || b == null) return false;
162 if (a.kind != b.kind) return false;
163 // TODO(johnniwinther): Compute a deep equivalence.
164 return true;
165 }
166
141 /// Strategy for testing equivalence. 167 /// Strategy for testing equivalence.
142 /// 168 ///
143 /// Use this strategy to determine equivalence without failing on inequivalence. 169 /// Use this strategy to determine equivalence without failing on inequivalence.
144 class TestStrategy { 170 class TestStrategy {
145 const TestStrategy(); 171 const TestStrategy();
146 172
147 bool test(var object1, var object2, String property, var value1, var value2) { 173 bool test(var object1, var object2, String property, var value1, var value2,
148 return value1 == value2; 174 [bool equivalence(a, b) = equality]) {
175 return equivalence(value1, value2);
149 } 176 }
150 177
151 bool testLists( 178 bool testLists(
152 Object object1, Object object2, String property, 179 Object object1, Object object2, String property,
153 List list1, List list2, 180 List list1, List list2,
154 [bool elementEquivalence(a, b) = equality]) { 181 [bool elementEquivalence(a, b) = equality]) {
155 return areListsEquivalent(list1, list2, elementEquivalence); 182 return areListsEquivalent(list1, list2, elementEquivalence);
156 } 183 }
157 184
158 bool testSets( 185 bool testSets(
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 575
549 @override 576 @override
550 bool visitPositional(PositionalArgumentReference exp1, 577 bool visitPositional(PositionalArgumentReference exp1,
551 PositionalArgumentReference exp2) { 578 PositionalArgumentReference exp2) {
552 return strategy.test(exp1, exp2, 'index', exp1.index, exp2.index); 579 return strategy.test(exp1, exp2, 'index', exp1.index, exp2.index);
553 } 580 }
554 581
555 @override 582 @override
556 bool visitSymbol(SymbolConstantExpression exp1, 583 bool visitSymbol(SymbolConstantExpression exp1,
557 SymbolConstantExpression exp2) { 584 SymbolConstantExpression exp2) {
558 // TODO: implement visitSymbol 585 // TODO(johnniwinther): Handle private names. Currently not even supported
559 return true; 586 // in resolution.
587 return strategy.test(exp1, exp2, 'name', exp1.name, exp2.name);
560 } 588 }
561 589
562 @override 590 @override
563 bool visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) { 591 bool visitType(TypeConstantExpression exp1, TypeConstantExpression exp2) {
564 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type); 592 return strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type);
565 } 593 }
566 594
567 @override 595 @override
568 bool visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) { 596 bool visitUnary(UnaryConstantExpression exp1, UnaryConstantExpression exp2) {
569 return 597 return
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 StringLengthConstantExpression exp2) { 684 StringLengthConstantExpression exp2) {
657 return 685 return
658 strategy.testConstants( 686 strategy.testConstants(
659 exp1, exp2, 'expression', 687 exp1, exp2, 'expression',
660 exp1.expression, exp2.expression); 688 exp1.expression, exp2.expression);
661 } 689 }
662 690
663 @override 691 @override
664 bool visitDeferred(DeferredConstantExpression exp1, 692 bool visitDeferred(DeferredConstantExpression exp1,
665 DeferredConstantExpression exp2) { 693 DeferredConstantExpression exp2) {
666 // TODO: implement visitDeferred 694 // TODO(johnniwinther): Implement this.
667 return true; 695 return true;
668 } 696 }
669 } 697 }
670 698
671 /// Tests the equivalence of [impact1] and [impact2] using [strategy]. 699 /// Tests the equivalence of [impact1] and [impact2] using [strategy].
672 bool testResolutionImpactEquivalence( 700 bool testResolutionImpactEquivalence(
673 ResolutionImpact impact1, 701 ResolutionImpact impact1,
674 ResolutionImpact impact2, 702 ResolutionImpact impact2,
675 [TestStrategy strategy = const TestStrategy()]) { 703 [TestStrategy strategy = const TestStrategy()]) {
676 return 704 return
(...skipping 21 matching lines...) Expand all
698 areMapLiteralUsesEquivalent) && 726 areMapLiteralUsesEquivalent) &&
699 strategy.testSets( 727 strategy.testSets(
700 impact1, impact2, 'staticUses', 728 impact1, impact2, 'staticUses',
701 impact1.staticUses, impact2.staticUses, 729 impact1.staticUses, impact2.staticUses,
702 areStaticUsesEquivalent) && 730 areStaticUsesEquivalent) &&
703 strategy.testSets( 731 strategy.testSets(
704 impact1, impact2, 'typeUses', 732 impact1, impact2, 'typeUses',
705 impact1.typeUses, impact2.typeUses, 733 impact1.typeUses, impact2.typeUses,
706 areTypeUsesEquivalent); 734 areTypeUsesEquivalent);
707 } 735 }
736
737 /// Tests the equivalence of [resolvedAst1] and [resolvedAst2] using [strategy].
738 bool testResolvedAstEquivalence(
739 ResolvedAst resolvedAst1,
740 ResolvedAst resolvedAst2,
741 [TestStrategy strategy = const TestStrategy()]) {
742 return
743 strategy.testElements(
744 resolvedAst1, resolvedAst2, 'element',
745 resolvedAst1.element, resolvedAst2.element) &&
746 // Compute AST equivalence by structural comparison.
747 strategy.test(
748 resolvedAst1, resolvedAst2, 'node',
749 resolvedAst1.node.toDebugString(),
750 resolvedAst2.node.toDebugString()) &&
751 testTreeElementsEquivalence(
752 resolvedAst1, resolvedAst2, strategy);
753 }
754
755 /// Tests the equivalence of the data stored in the [TreeElements] of
756 /// [resolvedAst1] and [resolvedAst2] using [strategy].
757 bool testTreeElementsEquivalence(
758 ResolvedAst resolvedAst1,
759 ResolvedAst resolvedAst2,
760 [TestStrategy strategy = const TestStrategy()]) {
761
762 AstIndexComputer indices1 = new AstIndexComputer();
763 resolvedAst1.node.accept(indices1);
764 AstIndexComputer indices2 = new AstIndexComputer();
765 resolvedAst2.node.accept(indices2);
766
767 TreeElements elements1 = resolvedAst1.elements;
768 TreeElements elements2 = resolvedAst2.elements;
769
770 TreeElementsEquivalenceVisitor visitor =
771 new TreeElementsEquivalenceVisitor(
772 indices1, indices2, elements1, elements2, strategy);
773 resolvedAst1.node.accept(visitor);
774 return visitor.success;
775 }
776
777 /// Visitor that checks the equivalence of [TreeElements] data.
778 class TreeElementsEquivalenceVisitor extends Visitor {
779 final TestStrategy strategy;
780 final AstIndexComputer indices1;
781 final AstIndexComputer indices2;
782 final TreeElements elements1;
783 final TreeElements elements2;
784 bool success = true;
785
786 TreeElementsEquivalenceVisitor(
787 this.indices1, this.indices2,
788 this.elements1, this.elements2,
789 [this.strategy = const TestStrategy()]);
790
791 visitNode(Node node1) {
792 if (!success) return;
793 int index = indices1.nodeIndices[node1];
794 Node node2 = indices2.nodeList[index];
795 success =
796 strategy.testElements(
797 node1, node2, '[$index]',
798 elements1[node1], elements2[node2]) &&
799 strategy.testTypes(
800 node1, node2, 'getType($index)',
801 elements1.getType(node1), elements2.getType(node2)) &&
802 strategy.test(
803 node1, node2, 'getSelector($index)',
804 elements1.getSelector(node1), elements2.getSelector(node2),
805 areSelectorsEquivalent) &&
806 strategy.testConstants(
807 node1, node2, 'getConstant($index)',
808 elements1.getConstant(node1), elements2.getConstant(node2)) &&
809 strategy.testTypes(
810 node1, node2, 'typesCache[$index]',
811 elements1.typesCache[node1], elements2.typesCache[node2]);
812
813 node1.visitChildren(this);
814 }
815
816 @override
817 visitSend(Send node1) {
818 visitExpression(node1);
819 if (!success) return;
820 int index = indices1.nodeIndices[node1];
821 Send node2 = indices2.nodeList[index];
822 success =
823 strategy.test(
824 node1, node2, 'isTypeLiteral($index)',
825 elements1.isTypeLiteral(node1),
826 elements2.isTypeLiteral(node2)) &&
827 strategy.testTypes(
828 node1, node2, 'getTypeLiteralType($index)',
829 elements1.getTypeLiteralType(node1),
830 elements2.getTypeLiteralType(node2)) &&
831 strategy.test(
832 node1, node2, 'getSendStructure($index)',
833 elements1.getSendStructure(node1),
834 elements2.getSendStructure(node2),
835 areSendStructuresEquivalent);
836 }
837
838 @override
839 visitNewExpression(NewExpression node1) {
840 visitExpression(node1);
841 if (!success) return;
842 int index = indices1.nodeIndices[node1];
843 NewExpression node2 = indices2.nodeList[index];
844 success =
845 strategy.test(
846 node1, node2, 'getNewStructure($index)',
847 elements1.getNewStructure(node1),
848 elements2.getNewStructure(node2),
849 areNewStructuresEquivalent);
850 }
851
852 @override
853 visitSendSet(SendSet node1) {
854 visitSend(node1);
855 if (!success) return;
856 int index = indices1.nodeIndices[node1];
857 SendSet node2 = indices2.nodeList[index];
858 success =
859 strategy.test(
860 node1, node2, 'getGetterSelectorInComplexSendSet($index)',
861 elements1.getGetterSelectorInComplexSendSet(node1),
862 elements2.getGetterSelectorInComplexSendSet(node2),
863 areSelectorsEquivalent) &&
864 strategy.test(
865 node1, node2, 'getOperatorSelectorInComplexSendSet($index)',
866 elements1.getOperatorSelectorInComplexSendSet(node1),
867 elements2.getOperatorSelectorInComplexSendSet(node2),
868 areSelectorsEquivalent);
869 }
870
871 @override
872 visitFunctionExpression(FunctionExpression node1) {
873 visitNode(node1);
874 if (!success) return;
875 int index = indices1.nodeIndices[node1];
876 FunctionExpression node2 = indices2.nodeList[index];
877 if (elements1[node1] is! FunctionElement) {
878 // [getFunctionDefinition] is currently stored in [] which doesn't always
879 // contain a [FunctionElement].
880 return;
881 }
882 success =
883 strategy.testElements(
884 node1, node2, 'getFunctionDefinition($index)',
885 elements1.getFunctionDefinition(node1),
886 elements2.getFunctionDefinition(node2));
887 }
888
889 @override
890 visitForIn(ForIn node1) {
891 visitLoop(node1);
892 if (!success) return;
893 int index = indices1.nodeIndices[node1];
894 ForIn node2 = indices2.nodeList[index];
895 success =
896 strategy.testElements(
897 node1, node2, 'getForInVariable($index)',
898 elements1.getForInVariable(node1),
899 elements2.getForInVariable(node2));
900 }
901
902 @override
903 visitRedirectingFactoryBody(RedirectingFactoryBody node1) {
904 visitStatement(node1);
905 if (!success) return;
906 int index = indices1.nodeIndices[node1];
907 RedirectingFactoryBody node2 = indices2.nodeList[index];
908 success =
909 strategy.testElements(
910 node1, node2, 'getRedirectingTargetConstructor($index)',
911 elements1.getRedirectingTargetConstructor(node1),
912 elements2.getRedirectingTargetConstructor(node2));
913 }
914 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698