OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library dart2js.js_emitter.constant_ordering; | |
6 | |
7 import '../constants/values.dart'; | |
8 | |
9 import '../common.dart'; | |
10 //import '../core_types.dart'; | |
11 import '../dart_types.dart'; | |
12 import '../elements/elements.dart' | |
13 show Element, | |
14 Elements, | |
15 FieldElement; | |
16 import '../tree/tree.dart' show DartString; | |
17 | |
18 /// A canonical but arbrary ordering of constants. The ordering is 'stable' | |
19 /// under perturbation of the source. | |
20 int deepCompareConstants(ConstantValue a, ConstantValue b) { | |
21 return _CompareVisitor.compareValues(a, b); | |
22 } | |
23 | |
24 class _CompareVisitor implements ConstantValueVisitor<int, ConstantValue> { | |
25 const _CompareVisitor(); | |
26 | |
27 static int compareValues(ConstantValue a, ConstantValue b) { | |
28 if (identical(a, b)) return 0; | |
29 int r = _KindVisitor.kind(a).compareTo(_KindVisitor.kind(b)); | |
30 if (r != 0) return r; | |
31 r = a.accept(const _CompareVisitor(), b); | |
32 return r; | |
33 } | |
34 | |
35 static int compareNullable(int compare(a, b), a, b) { | |
36 if (a == null && b == null) return 0; | |
37 if (a == null) return -1; | |
38 if (b == null) return 1; | |
39 return compare(a, b); | |
40 } | |
41 | |
42 static int compareLists(int compare(a, b), List a, List b) { | |
43 int r = a.length.compareTo(b.length); | |
44 if (r != 0) return r; | |
45 for (int i = 0; i < a.length; i++) { | |
46 r = compare(a[i], b[i]); | |
47 if (r != 0) return r; | |
48 } | |
49 return 0; | |
50 } | |
51 | |
52 static int compareElements(Element a, Element b) { | |
53 int r = a.name.compareTo(b.name); | |
54 if (r != 0) return r; | |
55 return Elements.compareByPosition(a, b); | |
56 } | |
57 | |
58 static int compareDartTypes(DartType a, DartType b) { | |
59 if (a == b) return 0; | |
60 int r = a.kind.index.compareTo(b.kind.index); | |
61 if (r != 0) return r; | |
62 r = compareNullable(compareElements, a.element, b.element); | |
63 if (r != 0) return r; | |
64 | |
65 if (a is GenericType) { | |
66 GenericType aGeneric = a; | |
67 GenericType bGeneric = b; | |
68 r = compareLists(compareDartTypes, | |
69 aGeneric.typeArguments, bGeneric.typeArguments); | |
70 if (r != 0) return r; | |
71 } | |
72 throw 'unexpected compareDartTypes $a $b'; | |
73 } | |
74 | |
75 int visitFunction(FunctionConstantValue a, FunctionConstantValue b) { | |
76 return compareElements(a.element, b.element); | |
77 } | |
78 | |
79 int visitNull(NullConstantValue a, NullConstantValue b) { | |
80 return 0; | |
81 } | |
82 | |
83 int visitInt(IntConstantValue a, IntConstantValue b) { | |
84 return a.primitiveValue.compareTo(b.primitiveValue); | |
85 } | |
86 | |
87 int visitDouble(DoubleConstantValue a, DoubleConstantValue b) { | |
88 return a.primitiveValue.compareTo(b.primitiveValue); | |
89 } | |
90 | |
91 int visitBool(BoolConstantValue a, BoolConstantValue b) { | |
92 int aInt = a.primitiveValue ? 1 : 0; | |
93 int bInt = b.primitiveValue ? 1 : 0; | |
94 return aInt.compareTo(bInt); | |
95 } | |
96 | |
97 int visitString(StringConstantValue a, StringConstantValue b) { | |
98 DartString aString = a.primitiveValue; | |
99 DartString bString = b.primitiveValue; | |
100 int r = aString.length.compareTo(bString.length); | |
101 if (r != 0) return r; | |
102 return aString.slowToString().compareTo(bString.slowToString()); | |
103 } | |
104 | |
105 int visitList(ListConstantValue a, ListConstantValue b) { | |
106 int r = compareLists(compareValues, a.entries, b.entries); | |
107 if (r != 0) return r; | |
108 return compareDartTypes(a.type, b.type); | |
109 } | |
110 | |
111 int visitMap(MapConstantValue a, MapConstantValue b) { | |
112 int r = compareLists(compareValues, a.keys, b.keys); | |
113 if (r != 0) return r; | |
114 r = compareLists(compareValues, a.values, b.values); | |
115 if (r != 0) return r; | |
116 return compareDartTypes(a.type, b.type); | |
117 } | |
118 | |
119 int visitConstructed(ConstructedConstantValue a, ConstructedConstantValue b) { | |
120 int r = compareDartTypes(a.type, b.type); | |
121 if (r != 0) return r; | |
122 | |
123 List<FieldElement> aFields = a.fields.keys.toList()..sort(compareElements); | |
124 List<FieldElement> bFields = b.fields.keys.toList()..sort(compareElements); | |
125 | |
126 r = compareLists(compareElements, aFields, bFields); | |
127 if (r != 0) return r; | |
128 | |
129 return compareLists(compareValues, | |
130 aFields.map((field) => a.fields[field]).toList(), | |
131 aFields.map((field) => b.fields[field]).toList()); | |
132 } | |
133 | |
134 int visitType(TypeConstantValue a, TypeConstantValue b) { | |
135 int r = compareDartTypes(a.representedType, b.representedType); | |
136 if (r != 0) return r; | |
137 return compareDartTypes(a.type, b.type); | |
138 } | |
139 | |
140 int visitInterceptor(InterceptorConstantValue a, InterceptorConstantValue b) { | |
141 return compareDartTypes(a.dispatchedType, b.dispatchedType); | |
142 } | |
143 | |
144 int visitSynthetic(SyntheticConstantValue a, SyntheticConstantValue b) { | |
145 // [SyntheticConstantValue]s have abstract fields that are set only by | |
146 // convention. Lucky for us, they do not occur as top level constant, only | |
147 // as elements of a few constants. If this becomes a source of instability, | |
148 // we will need to add a total ordering on JavaScript ASTs including | |
149 // deferred elements. | |
150 SyntheticConstantKind aKind = a.kind; | |
151 SyntheticConstantKind bKind = b.kind; | |
152 int r = aKind.index - bKind.index; | |
153 if (r != 0) return r; | |
154 switch (a.kind) { | |
155 case SyntheticConstantKind.DUMMY_INTERCEPTOR: | |
156 case SyntheticConstantKind.EMPTY_VALUE: | |
157 // Never emitted. | |
158 return 0: | |
159 | |
160 case SyntheticConstantKind.TYPEVARIABLE_REFERENCE: | |
161 // An opaque deferred JS AST reference to a type in reflection data. | |
162 return 0; | |
163 case SyntheticConstantKind.NAME: | |
164 // An opaque deferred JS AST reference to a name. | |
165 return 0; | |
166 default: | |
167 // Should not happen. | |
168 throw 'unexpected SyntheticConstantKind $akind'; | |
169 } | |
170 } | |
171 | |
172 int visitDeferred(DeferredConstantValue a, DeferredConstantValue b) { | |
173 int r = compareValues(a.referenced, b.referenced); | |
174 if (r != 0) return r; | |
175 return compareElements(a.prefix, b.prefix); | |
176 } | |
177 } | |
178 | |
179 class _KindVisitor implements ConstantValueVisitor<int, Null> { | |
180 const _KindVisitor(); | |
181 | |
182 static const int FUNCTION = 1; | |
183 static const int NULL = 2; | |
184 static const int INT = 3; | |
185 static const int DOUBLE = 4; | |
186 static const int BOOL = 5; | |
187 static const int STRING = 6; | |
188 static const int LIST = 7; | |
189 static const int MAP = 8; | |
190 static const int CONSTRUCTED = 9; | |
191 static const int TYPE = 10; | |
192 static const int INTERCEPTOR = 11; | |
193 static const int SYNTHETIC = 12; | |
194 static const int DEFERRED = 13; | |
195 | |
196 static int kind(ConstantValue constant) => | |
197 constant.accept(const _KindVisitor(), null); | |
198 | |
199 int visitFunction(FunctionConstantValue a, _) => FUNCTION; | |
200 int visitNull(NullConstantValue a, _) => NULL; | |
201 int visitInt(IntConstantValue a, _) => INT; | |
202 int visitDouble(DoubleConstantValue a, _) => DOUBLE; | |
203 int visitBool(BoolConstantValue a, _) => BOOL; | |
204 int visitString(StringConstantValue a, _) => STRING; | |
205 int visitList(ListConstantValue a, _) => LIST; | |
206 int visitMap(MapConstantValue a, _) => MAP; | |
207 int visitConstructed(ConstructedConstantValue a, _) => CONSTRUCTED; | |
208 int visitType(TypeConstantValue a, _) => TYPE; | |
209 int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR; | |
210 int visitSynthetic(SyntheticConstantValue a, _) => SYNTHETIC; | |
211 int visitDeferred(DeferredConstantValue a, _) => DEFERRED; | |
212 } | |
OLD | NEW |