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 |