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

Side by Side Diff: lib/compiler/implementation/constants.dart

Issue 10915083: Change assert implementation to not depend on a top-level function called 'assert'. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments. Created 8 years, 3 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) 2012, the Dart project authors. Please see the AUTHORS file 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 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 interface ConstantVisitor<R> {
6 R visitSentinel(SentinelConstant constant);
7 R visitFunction(FunctionConstant constant);
8 R visitNull(NullConstant constant);
9 R visitInt(IntConstant constant);
10 R visitDouble(DoubleConstant constant);
11 R visitTrue(TrueConstant constant);
12 R visitFalse(FalseConstant constant);
13 R visitString(StringConstant constant);
14 R visitList(ListConstant constant);
15 R visitMap(MapConstant constant);
16 R visitConstructed(ConstructedConstant constant);
17 }
18
19 class Constant implements Hashable { 5 class Constant implements Hashable {
20 const Constant(); 6 const Constant();
21 7
22 bool isNull() => false; 8 bool isNull() => false;
23 bool isBool() => false; 9 bool isBool() => false;
24 bool isTrue() => false; 10 bool isTrue() => false;
25 bool isFalse() => false; 11 bool isFalse() => false;
26 bool isInt() => false; 12 bool isInt() => false;
27 bool isDouble() => false; 13 bool isDouble() => false;
28 bool isNum() => false; 14 bool isNum() => false;
29 bool isString() => false; 15 bool isString() => false;
30 bool isList() => false; 16 bool isList() => false;
31 bool isMap() => false; 17 bool isMap() => false;
32 bool isConstructedObject() => false; 18 bool isConstructedObject() => false;
33 bool isFunction() => false; 19 bool isFunction() => false;
34 /** Returns true if the constant is null, a bool, a number or a string. */ 20 /** Returns true if the constant is null, a bool, a number or a string. */
35 bool isPrimitive() => false; 21 bool isPrimitive() => false;
36 /** Returns true if the constant is a list, a map or a constructed object. */ 22 /** Returns true if the constant is a list, a map or a constructed object. */
37 bool isObject() => false; 23 bool isObject() => false;
38 bool isSentinel() => false; 24 bool isSentinel() => false;
39 25
40 bool isNaN() => false; 26 bool isNaN() => false;
41 bool isMinusZero() => false; 27 bool isMinusZero() => false;
42 28
29 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler);
30 /**
31 * Unless the constant can be emitted multiple times (as for numbers and
32 * strings) adds its canonical name to the buffer.
33 */
34 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer,
35 ConstantHandler handler);
43 abstract List<Constant> getDependencies(); 36 abstract List<Constant> getDependencies();
44
45 abstract accept(ConstantVisitor);
46 } 37 }
47 38
48 class SentinelConstant extends Constant { 39 class SentinelConstant extends Constant {
49 const SentinelConstant(); 40 const SentinelConstant();
50 static final SENTINEL = const SentinelConstant(); 41 static final SENTINEL = const SentinelConstant();
51 42
43 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
44 handler.compiler.internalError(
45 "The parameter sentinel constant does not need specific JS code");
46 }
47
48 void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
49 buffer.add(handler.compiler.namer.CURRENT_ISOLATE);
50 }
51
52 List<Constant> getDependencies() => const <Constant>[]; 52 List<Constant> getDependencies() => const <Constant>[];
53 53
54 // Just use a random value. 54 // Just use a randome value.
55 int hashCode() => 24297418; 55 int hashCode() => 926429784158;
56 56
57 bool isSentinel() => true; 57 bool isSentinel() => true;
58
59 accept(ConstantVisitor visitor) => visitor.visitSentinel(this);
60 } 58 }
61 59
62 class FunctionConstant extends Constant { 60 class FunctionConstant extends Constant {
63 Element element; 61 Element element;
64 62
65 FunctionConstant(this.element); 63 FunctionConstant(this.element);
66 64
67 bool isFunction() => true; 65 bool isFunction() => true;
68 66
69 bool operator ==(var other) { 67 bool operator ==(var other) {
70 if (other is !FunctionConstant) return false; 68 if (other is !FunctionConstant) return false;
71 return other.element === element; 69 return other.element === element;
72 } 70 }
73 71
74 String toString() => element.toString(); 72 String toString() => element.toString();
75 List<Constant> getDependencies() => const <Constant>[]; 73 List<Constant> getDependencies() => const <Constant>[];
76 DartString toDartString() { 74 DartString toDartString() {
77 return new DartString.literal(element.name.slowToString()); 75 return new DartString.literal(element.name.slowToString());
78 } 76 }
79 77
78 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
79 handler.compiler.internalError(
80 "A constant function does not need specific JS code");
81 }
82
83 void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
84 buffer.add(handler.compiler.namer.isolatePropertiesAccess(element));
85 }
86
80 int hashCode() => (17 * element.hashCode()) & 0x7fffffff; 87 int hashCode() => (17 * element.hashCode()) & 0x7fffffff;
81
82 accept(ConstantVisitor visitor) => visitor.visitFunction(this);
83 } 88 }
84 89
85 class PrimitiveConstant extends Constant { 90 class PrimitiveConstant extends Constant {
86 abstract get value; 91 abstract get value;
87 const PrimitiveConstant(); 92 const PrimitiveConstant();
88 bool isPrimitive() => true; 93 bool isPrimitive() => true;
89 94
90 bool operator ==(var other) { 95 bool operator ==(var other) {
91 if (other is !PrimitiveConstant) return false; 96 if (other is !PrimitiveConstant) return false;
92 PrimitiveConstant otherPrimitive = other; 97 PrimitiveConstant otherPrimitive = other;
93 // We use == instead of === so that DartStrings compare correctly. 98 // We use == instead of === so that DartStrings compare correctly.
94 return value == otherPrimitive.value; 99 return value == otherPrimitive.value;
95 } 100 }
96 101
97 String toString() => value.toString(); 102 String toString() => value.toString();
98 // Primitive constants don't have dependencies. 103 // Primitive constants don't have dependencies.
99 List<Constant> getDependencies() => const <Constant>[]; 104 List<Constant> getDependencies() => const <Constant>[];
100 abstract DartString toDartString(); 105 abstract DartString toDartString();
106
107 void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
108 _writeJsCode(buffer, handler);
109 }
101 } 110 }
102 111
103 class NullConstant extends PrimitiveConstant { 112 class NullConstant extends PrimitiveConstant {
104 /** The value a Dart null is compiled to in JavaScript. */ 113 /** The value a Dart null is compiled to in JavaScript. */
105 static const String JsNull = "null"; 114 static const String JsNull = "null";
106 115
107 factory NullConstant() => const NullConstant._internal(); 116 factory NullConstant() => const NullConstant._internal();
108 const NullConstant._internal(); 117 const NullConstant._internal();
109 bool isNull() => true; 118 bool isNull() => true;
110 get value => null; 119 get value => null;
111 120
112 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { 121 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
113 buffer.add(JsNull); 122 buffer.add(JsNull);
114 } 123 }
115 124
116 // The magic constant has no meaning. It is just a random value. 125 // The magic constant has no meaning. It is just a random value.
117 int hashCode() => 785965825; 126 int hashCode() => 785965825;
118 DartString toDartString() => const LiteralDartString("null"); 127 DartString toDartString() => const LiteralDartString("null");
119
120 accept(ConstantVisitor visitor) => visitor.visitNull(this);
121 } 128 }
122 129
123 class NumConstant extends PrimitiveConstant { 130 class NumConstant extends PrimitiveConstant {
124 abstract num get value; 131 abstract num get value;
125 const NumConstant(); 132 const NumConstant();
126 bool isNum() => true; 133 bool isNum() => true;
127 } 134 }
128 135
129 class IntConstant extends NumConstant { 136 class IntConstant extends NumConstant {
130 final int value; 137 final int value;
(...skipping 11 matching lines...) Expand all
142 case 9: return const IntConstant._internal(9); 149 case 9: return const IntConstant._internal(9);
143 case 10: return const IntConstant._internal(10); 150 case 10: return const IntConstant._internal(10);
144 case -1: return const IntConstant._internal(-1); 151 case -1: return const IntConstant._internal(-1);
145 case -2: return const IntConstant._internal(-2); 152 case -2: return const IntConstant._internal(-2);
146 default: return new IntConstant._internal(value); 153 default: return new IntConstant._internal(value);
147 } 154 }
148 } 155 }
149 const IntConstant._internal(this.value); 156 const IntConstant._internal(this.value);
150 bool isInt() => true; 157 bool isInt() => true;
151 158
159 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
160 buffer.add("$value");
161 }
162
152 // We have to override the equality operator so that ints and doubles are 163 // We have to override the equality operator so that ints and doubles are
153 // treated as separate constants. 164 // treated as separate constants.
154 // The is [:!IntConstant:] check at the beginning of the function makes sure 165 // The is [:!IntConstant:] check at the beginning of the function makes sure
155 // that we compare only equal to integer constants. 166 // that we compare only equal to integer constants.
156 bool operator ==(var other) { 167 bool operator ==(var other) {
157 if (other is !IntConstant) return false; 168 if (other is !IntConstant) return false;
158 IntConstant otherInt = other; 169 IntConstant otherInt = other;
159 return value == otherInt.value; 170 return value == otherInt.value;
160 } 171 }
161 172
162 int hashCode() => value.hashCode(); 173 int hashCode() => value.hashCode();
163 DartString toDartString() => new DartString.literal(value.toString()); 174 DartString toDartString() => new DartString.literal(value.toString());
164
165 accept(ConstantVisitor visitor) => visitor.visitInt(this);
166 } 175 }
167 176
168 class DoubleConstant extends NumConstant { 177 class DoubleConstant extends NumConstant {
169 final double value; 178 final double value;
170 factory DoubleConstant(double value) { 179 factory DoubleConstant(double value) {
171 if (value.isNaN()) { 180 if (value.isNaN()) {
172 return const DoubleConstant._internal(double.NAN); 181 return const DoubleConstant._internal(double.NAN);
173 } else if (value == double.INFINITY) { 182 } else if (value == double.INFINITY) {
174 return const DoubleConstant._internal(double.INFINITY); 183 return const DoubleConstant._internal(double.INFINITY);
175 } else if (value == -double.INFINITY) { 184 } else if (value == -double.INFINITY) {
176 return const DoubleConstant._internal(-double.INFINITY); 185 return const DoubleConstant._internal(-double.INFINITY);
177 } else if (value == 0.0 && !value.isNegative()) { 186 } else if (value == 0.0 && !value.isNegative()) {
178 return const DoubleConstant._internal(0.0); 187 return const DoubleConstant._internal(0.0);
179 } else if (value == 1.0) { 188 } else if (value == 1.0) {
180 return const DoubleConstant._internal(1.0); 189 return const DoubleConstant._internal(1.0);
181 } else { 190 } else {
182 return new DoubleConstant._internal(value); 191 return new DoubleConstant._internal(value);
183 } 192 }
184 } 193 }
185 const DoubleConstant._internal(this.value); 194 const DoubleConstant._internal(this.value);
186 bool isDouble() => true; 195 bool isDouble() => true;
187 bool isNaN() => value.isNaN(); 196 bool isNaN() => value.isNaN();
188 // We need to check for the negative sign since -0.0 == 0.0. 197 // We need to check for the negative sign since -0.0 == 0.0.
189 bool isMinusZero() => value == 0.0 && value.isNegative(); 198 bool isMinusZero() => value == 0.0 && value.isNegative();
190 199
200 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
201 if (value.isNaN()) {
202 buffer.add("(0/0)");
203 } else if (value == double.INFINITY) {
204 buffer.add("(1/0)");
205 } else if (value == -double.INFINITY) {
206 buffer.add("(-1/0)");
207 } else {
208 buffer.add("$value");
209 }
210 }
211
191 bool operator ==(var other) { 212 bool operator ==(var other) {
192 if (other is !DoubleConstant) return false; 213 if (other is !DoubleConstant) return false;
193 DoubleConstant otherDouble = other; 214 DoubleConstant otherDouble = other;
194 double otherValue = otherDouble.value; 215 double otherValue = otherDouble.value;
195 if (value == 0.0 && otherValue == 0.0) { 216 if (value == 0.0 && otherValue == 0.0) {
196 return value.isNegative() == otherValue.isNegative(); 217 return value.isNegative() == otherValue.isNegative();
197 } else if (value.isNaN()) { 218 } else if (value.isNaN()) {
198 return otherValue.isNaN(); 219 return otherValue.isNaN();
199 } else { 220 } else {
200 return value == otherValue; 221 return value == otherValue;
201 } 222 }
202 } 223 }
203 224
204 int hashCode() => value.hashCode(); 225 int hashCode() => value.hashCode();
205 DartString toDartString() => new DartString.literal(value.toString()); 226 DartString toDartString() => new DartString.literal(value.toString());
206
207 accept(ConstantVisitor visitor) => visitor.visitDouble(this);
208 } 227 }
209 228
210 class BoolConstant extends PrimitiveConstant { 229 class BoolConstant extends PrimitiveConstant {
211 factory BoolConstant(value) { 230 factory BoolConstant(value) {
212 return value ? new TrueConstant() : new FalseConstant(); 231 return value ? new TrueConstant() : new FalseConstant();
213 } 232 }
214 const BoolConstant._internal(); 233 const BoolConstant._internal();
215 bool isBool() => true; 234 bool isBool() => true;
216 235
217 abstract BoolConstant negate(); 236 abstract BoolConstant negate();
218 } 237 }
219 238
220 class TrueConstant extends BoolConstant { 239 class TrueConstant extends BoolConstant {
221 final bool value = true; 240 final bool value = true;
222 241
223 factory TrueConstant() => const TrueConstant._internal(); 242 factory TrueConstant() => const TrueConstant._internal();
224 const TrueConstant._internal() : super._internal(); 243 const TrueConstant._internal() : super._internal();
225 bool isTrue() => true; 244 bool isTrue() => true;
226 245
246 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
247 buffer.add("true");
248 }
249
227 FalseConstant negate() => new FalseConstant(); 250 FalseConstant negate() => new FalseConstant();
228 251
229 bool operator ==(var other) => this === other; 252 bool operator ==(var other) => this === other;
230 // The magic constant is just a random value. It does not have any 253 // The magic constant is just a random value. It does not have any
231 // significance. 254 // significance.
232 int hashCode() => 499; 255 int hashCode() => 499;
233 DartString toDartString() => const LiteralDartString("true"); 256 DartString toDartString() => const LiteralDartString("true");
234
235 accept(ConstantVisitor visitor) => visitor.visitTrue(this);
236 } 257 }
237 258
238 class FalseConstant extends BoolConstant { 259 class FalseConstant extends BoolConstant {
239 final bool value = false; 260 final bool value = false;
240 261
241 factory FalseConstant() => const FalseConstant._internal(); 262 factory FalseConstant() => const FalseConstant._internal();
242 const FalseConstant._internal() : super._internal(); 263 const FalseConstant._internal() : super._internal();
243 bool isFalse() => true; 264 bool isFalse() => true;
244 265
266 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
267 buffer.add("false");
268 }
269
245 TrueConstant negate() => new TrueConstant(); 270 TrueConstant negate() => new TrueConstant();
246 271
247 bool operator ==(var other) => this === other; 272 bool operator ==(var other) => this === other;
248 // The magic constant is just a random value. It does not have any 273 // The magic constant is just a random value. It does not have any
249 // significance. 274 // significance.
250 int hashCode() => 536555975; 275 int hashCode() => 536555975;
251 DartString toDartString() => const LiteralDartString("false"); 276 DartString toDartString() => const LiteralDartString("false");
252
253 accept(ConstantVisitor visitor) => visitor.visitFalse(this);
254 } 277 }
255 278
256 class StringConstant extends PrimitiveConstant { 279 class StringConstant extends PrimitiveConstant {
257 final DartString value; 280 final DartString value;
258 int _hashCode; 281 int _hashCode;
259 final Node node; 282 final Node node;
260 283
261 StringConstant(this.value, this.node) { 284 StringConstant(this.value, this.node) {
262 // TODO(floitsch): cache StringConstants. 285 // TODO(floitsch): cache StringConstants.
263 // TODO(floitsch): compute hashcode without calling toString() on the 286 // TODO(floitsch): compute hashcode without calling toString() on the
264 // DartString. 287 // DartString.
265 _hashCode = value.slowToString().hashCode(); 288 _hashCode = value.slowToString().hashCode();
266 } 289 }
267 bool isString() => true; 290 bool isString() => true;
268 291
292 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
293 buffer.add("'");
294 ConstantHandler.writeEscapedString(value, buffer, (reason) {
295 handler.compiler.reportError(node, reason);
296 });
297 buffer.add("'");
298 }
299
269 bool operator ==(var other) { 300 bool operator ==(var other) {
270 if (other is !StringConstant) return false; 301 if (other is !StringConstant) return false;
271 StringConstant otherString = other; 302 StringConstant otherString = other;
272 return (_hashCode == otherString._hashCode) && (value == otherString.value); 303 return (_hashCode == otherString._hashCode) && (value == otherString.value);
273 } 304 }
274 305
275 int hashCode() => _hashCode; 306 int hashCode() => _hashCode;
276 DartString toDartString() => value; 307 DartString toDartString() => value;
277 int get length => value.length; 308 int get length => value.length;
278
279 accept(ConstantVisitor visitor) => visitor.visitString(this);
280 } 309 }
281 310
282 class ObjectConstant extends Constant { 311 class ObjectConstant extends Constant {
283 final DartType type; 312 final DartType type;
284 313
285 ObjectConstant(this.type); 314 ObjectConstant(this.type);
286 bool isObject() => true; 315 bool isObject() => true;
287 316
288 // TODO(1603): The class should be marked as abstract, but the VM doesn't 317 // TODO(1603): The class should be marked as abstract, but the VM doesn't
289 // currently allow this. 318 // currently allow this.
290 abstract int hashCode(); 319 abstract int hashCode();
320
321 void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
322 String name = handler.getNameForConstant(this);
323 buffer.add(handler.compiler.namer.isolatePropertiesAccessForConstant(name));
324 }
291 } 325 }
292 326
293 class ListConstant extends ObjectConstant { 327 class ListConstant extends ObjectConstant {
294 final List<Constant> entries; 328 final List<Constant> entries;
295 int _hashCode; 329 int _hashCode;
296 330
297 ListConstant(DartType type, this.entries) : super(type) { 331 ListConstant(DartType type, this.entries) : super(type) {
298 // TODO(floitsch): create a better hash. 332 // TODO(floitsch): create a better hash.
299 int hash = 0; 333 int hash = 0;
300 for (Constant input in entries) hash ^= input.hashCode(); 334 for (Constant input in entries) hash ^= input.hashCode();
301 _hashCode = hash; 335 _hashCode = hash;
302 } 336 }
303 bool isList() => true; 337 bool isList() => true;
304 338
339 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
340 // TODO(floitsch): we should not need to go through the compiler to make
341 // the list constant.
342 buffer.add("${handler.compiler.namer.ISOLATE}.makeConstantList");
343 buffer.add("([");
344 for (int i = 0; i < entries.length; i++) {
345 if (i != 0) buffer.add(", ");
346 Constant entry = entries[i];
347 handler.writeConstant(buffer, entry);
348 }
349 buffer.add("])");
350 }
351
305 bool operator ==(var other) { 352 bool operator ==(var other) {
306 if (other is !ListConstant) return false; 353 if (other is !ListConstant) return false;
307 ListConstant otherList = other; 354 ListConstant otherList = other;
308 if (hashCode() != otherList.hashCode()) return false; 355 if (hashCode() != otherList.hashCode()) return false;
309 // TODO(floitsch): verify that the generic types are the same. 356 // TODO(floitsch): verify that the generic types are the same.
310 if (entries.length != otherList.entries.length) return false; 357 if (entries.length != otherList.entries.length) return false;
311 for (int i = 0; i < entries.length; i++) { 358 for (int i = 0; i < entries.length; i++) {
312 if (entries[i] != otherList.entries[i]) return false; 359 if (entries[i] != otherList.entries[i]) return false;
313 } 360 }
314 return true; 361 return true;
315 } 362 }
316 363
317 int hashCode() => _hashCode; 364 int hashCode() => _hashCode;
318 365
319 List<Constant> getDependencies() => entries; 366 List<Constant> getDependencies() => entries;
320 367
321 int get length => entries.length; 368 int get length => entries.length;
322
323 accept(ConstantVisitor visitor) => visitor.visitList(this);
324 } 369 }
325 370
326 class MapConstant extends ObjectConstant { 371 class MapConstant extends ObjectConstant {
327 /** 372 /**
328 * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript 373 * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript
329 * object. It would change the prototype chain. 374 * object. It would change the prototype chain.
330 */ 375 */
331 static const LiteralDartString PROTO_PROPERTY = 376 static const String PROTO_PROPERTY = "__proto__";
332 const LiteralDartString("__proto__");
333 377
334 /** The dart class implementing constant map literals. */ 378 /** The dart class implementing constant map literals. */
335 static const SourceString DART_CLASS = const SourceString("ConstantMap"); 379 static const SourceString DART_CLASS = const SourceString("ConstantMap");
336 static const SourceString DART_PROTO_CLASS = 380 static const SourceString DART_PROTO_CLASS =
337 const SourceString("ConstantProtoMap"); 381 const SourceString("ConstantProtoMap");
338 static const SourceString LENGTH_NAME = const SourceString("length"); 382 static const SourceString LENGTH_NAME = const SourceString("length");
339 static const SourceString JS_OBJECT_NAME = const SourceString("_jsObject"); 383 static const SourceString JS_OBJECT_NAME = const SourceString("_jsObject");
340 static const SourceString KEYS_NAME = const SourceString("_keys"); 384 static const SourceString KEYS_NAME = const SourceString("_keys");
341 static const SourceString PROTO_VALUE = const SourceString("_protoValue"); 385 static const SourceString PROTO_VALUE = const SourceString("_protoValue");
342 386
343 final ListConstant keys; 387 final ListConstant keys;
344 final List<Constant> values; 388 final List<Constant> values;
345 final Constant protoValue; 389 final Constant protoValue;
346 int _hashCode; 390 int _hashCode;
347 391
348 MapConstant(DartType type, this.keys, this.values, this.protoValue) 392 MapConstant(DartType type, this.keys, this.values, this.protoValue)
349 : super(type) { 393 : super(type) {
350 // TODO(floitsch): create a better hash. 394 // TODO(floitsch): create a better hash.
351 int hash = 0; 395 int hash = 0;
352 for (Constant value in values) hash ^= value.hashCode(); 396 for (Constant value in values) hash ^= value.hashCode();
353 _hashCode = hash; 397 _hashCode = hash;
354 } 398 }
355 bool isMap() => true; 399 bool isMap() => true;
356 400
401 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
402
403 void writeJsMap() {
404 buffer.add("{");
405 int valueIndex = 0;
406 for (int i = 0; i < keys.entries.length; i++) {
407 StringConstant key = keys.entries[i];
408 if (key.value == const LiteralDartString(PROTO_PROPERTY)) continue;
409
410 if (valueIndex != 0) buffer.add(", ");
411
412 key._writeJsCode(buffer, handler);
413 buffer.add(": ");
414 Constant value = values[valueIndex++];
415 handler.writeConstant(buffer, value);
416 }
417 buffer.add("}");
418 if (valueIndex != values.length) {
419 handler.compiler.internalError("Bad value count.");
420 }
421 }
422
423 void badFieldCountError() {
424 handler.compiler.internalError(
425 "Compiler and ConstantMap disagree on number of fields.");
426 }
427
428 ClassElement classElement = type.element;
429 buffer.add("new ");
430 buffer.add(handler.getJsConstructor(classElement));
431 buffer.add("(");
432 // The arguments of the JavaScript constructor for any given Dart class
433 // are in the same order as the members of the class element.
434 int emittedArgumentCount = 0;
435 classElement.forEachInstanceField(
436 includeBackendMembers: true,
437 includeSuperMembers: true,
438 f: (ClassElement enclosing, Element field) {
439 if (emittedArgumentCount != 0) buffer.add(", ");
440 if (field.name == LENGTH_NAME) {
441 buffer.add(keys.entries.length);
442 } else if (field.name == JS_OBJECT_NAME) {
443 writeJsMap();
444 } else if (field.name == KEYS_NAME) {
445 handler.writeConstant(buffer, keys);
446 } else if (field.name == PROTO_VALUE) {
447 assert(protoValue !== null);
448 handler.writeConstant(buffer, protoValue);
449 } else {
450 badFieldCountError();
451 }
452 emittedArgumentCount++;
453 });
454 if ((protoValue === null && emittedArgumentCount != 3) ||
455 (protoValue !== null && emittedArgumentCount != 4)) {
456 badFieldCountError();
457 }
458 buffer.add(")");
459 }
460
357 bool operator ==(var other) { 461 bool operator ==(var other) {
358 if (other is !MapConstant) return false; 462 if (other is !MapConstant) return false;
359 MapConstant otherMap = other; 463 MapConstant otherMap = other;
360 if (hashCode() != otherMap.hashCode()) return false; 464 if (hashCode() != otherMap.hashCode()) return false;
361 // TODO(floitsch): verify that the generic types are the same. 465 // TODO(floitsch): verify that the generic types are the same.
362 if (keys != otherMap.keys) return false; 466 if (keys != otherMap.keys) return false;
363 for (int i = 0; i < values.length; i++) { 467 for (int i = 0; i < values.length; i++) {
364 if (values[i] != otherMap.values[i]) return false; 468 if (values[i] != otherMap.values[i]) return false;
365 } 469 }
366 return true; 470 return true;
367 } 471 }
368 472
369 int hashCode() => _hashCode; 473 int hashCode() => _hashCode;
370 474
371 List<Constant> getDependencies() { 475 List<Constant> getDependencies() {
372 List<Constant> result = <Constant>[keys]; 476 List<Constant> result = <Constant>[keys];
373 result.addAll(values); 477 result.addAll(values);
374 return result; 478 return result;
375 } 479 }
376 480
377 int get length => keys.length; 481 int get length => keys.length;
378
379 accept(ConstantVisitor visitor) => visitor.visitMap(this);
380 } 482 }
381 483
382 class ConstructedConstant extends ObjectConstant { 484 class ConstructedConstant extends ObjectConstant {
383 final List<Constant> fields; 485 final List<Constant> fields;
384 int _hashCode; 486 int _hashCode;
385 487
386 ConstructedConstant(DartType type, this.fields) : super(type) { 488 ConstructedConstant(DartType type, this.fields) : super(type) {
387 assert(type !== null); 489 assert(type !== null);
388 // TODO(floitsch): create a better hash. 490 // TODO(floitsch): create a better hash.
389 int hash = 0; 491 int hash = 0;
390 for (Constant field in fields) { 492 for (Constant field in fields) {
391 hash ^= field.hashCode(); 493 hash ^= field.hashCode();
392 } 494 }
393 hash ^= type.element.hashCode(); 495 hash ^= type.element.hashCode();
394 _hashCode = hash; 496 _hashCode = hash;
395 } 497 }
396 bool isConstructedObject() => true; 498 bool isConstructedObject() => true;
397 499
500 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
501 buffer.add("new ");
502 buffer.add(handler.getJsConstructor(type.element));
503 buffer.add("(");
504 for (int i = 0; i < fields.length; i++) {
505 if (i != 0) buffer.add(", ");
506 Constant field = fields[i];
507 handler.writeConstant(buffer, field);
508 }
509 buffer.add(")");
510 }
511
398 bool operator ==(var otherVar) { 512 bool operator ==(var otherVar) {
399 if (otherVar is !ConstructedConstant) return false; 513 if (otherVar is !ConstructedConstant) return false;
400 ConstructedConstant other = otherVar; 514 ConstructedConstant other = otherVar;
401 if (hashCode() != other.hashCode()) return false; 515 if (hashCode() != other.hashCode()) return false;
402 // TODO(floitsch): verify that the (generic) types are the same. 516 // TODO(floitsch): verify that the (generic) types are the same.
403 if (type.element != other.type.element) return false; 517 if (type.element != other.type.element) return false;
404 if (fields.length != other.fields.length) return false; 518 if (fields.length != other.fields.length) return false;
405 for (int i = 0; i < fields.length; i++) { 519 for (int i = 0; i < fields.length; i++) {
406 if (fields[i] != other.fields[i]) return false; 520 if (fields[i] != other.fields[i]) return false;
407 } 521 }
408 return true; 522 return true;
409 } 523 }
410 524
411 int hashCode() => _hashCode; 525 int hashCode() => _hashCode;
412 List<Constant> getDependencies() => fields; 526 List<Constant> getDependencies() => fields;
413
414 accept(ConstantVisitor visitor) => visitor.visitConstructed(this);
415 } 527 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/compiler.dart ('k') | lib/compiler/implementation/elements/elements.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698