OLD | NEW |
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 abstract class ConstantVisitor<R> { | 5 abstract class ConstantVisitor<R> { |
6 R visitSentinel(SentinelConstant constant); | 6 R visitSentinel(SentinelConstant constant); |
7 R visitFunction(FunctionConstant constant); | 7 R visitFunction(FunctionConstant constant); |
8 R visitNull(NullConstant constant); | 8 R visitNull(NullConstant constant); |
9 R visitInt(IntConstant constant); | 9 R visitInt(IntConstant constant); |
10 R visitDouble(DoubleConstant constant); | 10 R visitDouble(DoubleConstant constant); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 abstract accept(ConstantVisitor); | 47 abstract accept(ConstantVisitor); |
48 } | 48 } |
49 | 49 |
50 class SentinelConstant extends Constant { | 50 class SentinelConstant extends Constant { |
51 const SentinelConstant(); | 51 const SentinelConstant(); |
52 static final SENTINEL = const SentinelConstant(); | 52 static final SENTINEL = const SentinelConstant(); |
53 | 53 |
54 List<Constant> getDependencies() => const <Constant>[]; | 54 List<Constant> getDependencies() => const <Constant>[]; |
55 | 55 |
56 // Just use a random value. | 56 // Just use a random value. |
57 int hashCode() => 24297418; | 57 int get hashCode => 24297418; |
58 | 58 |
59 bool isSentinel() => true; | 59 bool isSentinel() => true; |
60 | 60 |
61 accept(ConstantVisitor visitor) => visitor.visitSentinel(this); | 61 accept(ConstantVisitor visitor) => visitor.visitSentinel(this); |
62 | 62 |
63 DartType computeType(Compiler compiler) => compiler.types.dynamicType; | 63 DartType computeType(Compiler compiler) => compiler.types.dynamicType; |
64 } | 64 } |
65 | 65 |
66 class FunctionConstant extends Constant { | 66 class FunctionConstant extends Constant { |
67 Element element; | 67 Element element; |
(...skipping 10 matching lines...) Expand all Loading... |
78 String toString() => element.toString(); | 78 String toString() => element.toString(); |
79 List<Constant> getDependencies() => const <Constant>[]; | 79 List<Constant> getDependencies() => const <Constant>[]; |
80 DartString toDartString() { | 80 DartString toDartString() { |
81 return new DartString.literal(element.name.slowToString()); | 81 return new DartString.literal(element.name.slowToString()); |
82 } | 82 } |
83 | 83 |
84 DartType computeType(Compiler compiler) { | 84 DartType computeType(Compiler compiler) { |
85 return compiler.functionClass.computeType(compiler); | 85 return compiler.functionClass.computeType(compiler); |
86 } | 86 } |
87 | 87 |
88 int hashCode() => (17 * element.hashCode()) & 0x7fffffff; | 88 int get hashCode => (17 * element.hashCode) & 0x7fffffff; |
89 | 89 |
90 accept(ConstantVisitor visitor) => visitor.visitFunction(this); | 90 accept(ConstantVisitor visitor) => visitor.visitFunction(this); |
91 } | 91 } |
92 | 92 |
93 abstract class PrimitiveConstant extends Constant { | 93 abstract class PrimitiveConstant extends Constant { |
94 abstract get value; | 94 abstract get value; |
95 const PrimitiveConstant(); | 95 const PrimitiveConstant(); |
96 bool isPrimitive() => true; | 96 bool isPrimitive() => true; |
97 | 97 |
98 bool operator ==(var other) { | 98 bool operator ==(var other) { |
(...skipping 20 matching lines...) Expand all Loading... |
119 | 119 |
120 DartType computeType(Compiler compiler) { | 120 DartType computeType(Compiler compiler) { |
121 return compiler.nullClass.computeType(compiler); | 121 return compiler.nullClass.computeType(compiler); |
122 } | 122 } |
123 | 123 |
124 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { | 124 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { |
125 buffer.add(JsNull); | 125 buffer.add(JsNull); |
126 } | 126 } |
127 | 127 |
128 // The magic constant has no meaning. It is just a random value. | 128 // The magic constant has no meaning. It is just a random value. |
129 int hashCode() => 785965825; | 129 int get hashCode => 785965825; |
130 DartString toDartString() => const LiteralDartString("null"); | 130 DartString toDartString() => const LiteralDartString("null"); |
131 | 131 |
132 accept(ConstantVisitor visitor) => visitor.visitNull(this); | 132 accept(ConstantVisitor visitor) => visitor.visitNull(this); |
133 } | 133 } |
134 | 134 |
135 abstract class NumConstant extends PrimitiveConstant { | 135 abstract class NumConstant extends PrimitiveConstant { |
136 abstract num get value; | 136 abstract num get value; |
137 const NumConstant(); | 137 const NumConstant(); |
138 bool isNum() => true; | 138 bool isNum() => true; |
139 } | 139 } |
(...skipping 28 matching lines...) Expand all Loading... |
168 // We have to override the equality operator so that ints and doubles are | 168 // We have to override the equality operator so that ints and doubles are |
169 // treated as separate constants. | 169 // treated as separate constants. |
170 // The is [:!IntConstant:] check at the beginning of the function makes sure | 170 // The is [:!IntConstant:] check at the beginning of the function makes sure |
171 // that we compare only equal to integer constants. | 171 // that we compare only equal to integer constants. |
172 bool operator ==(var other) { | 172 bool operator ==(var other) { |
173 if (other is !IntConstant) return false; | 173 if (other is !IntConstant) return false; |
174 IntConstant otherInt = other; | 174 IntConstant otherInt = other; |
175 return value == otherInt.value; | 175 return value == otherInt.value; |
176 } | 176 } |
177 | 177 |
178 int hashCode() => value.hashCode(); | 178 int get hashCode => value.hashCode; |
179 DartString toDartString() => new DartString.literal(value.toString()); | 179 DartString toDartString() => new DartString.literal(value.toString()); |
180 | 180 |
181 accept(ConstantVisitor visitor) => visitor.visitInt(this); | 181 accept(ConstantVisitor visitor) => visitor.visitInt(this); |
182 } | 182 } |
183 | 183 |
184 class DoubleConstant extends NumConstant { | 184 class DoubleConstant extends NumConstant { |
185 final double value; | 185 final double value; |
186 factory DoubleConstant(double value) { | 186 factory DoubleConstant(double value) { |
187 if (value.isNaN()) { | 187 if (value.isNaN()) { |
188 return const DoubleConstant._internal(double.NAN); | 188 return const DoubleConstant._internal(double.NAN); |
(...skipping 25 matching lines...) Expand all Loading... |
214 double otherValue = otherDouble.value; | 214 double otherValue = otherDouble.value; |
215 if (value == 0.0 && otherValue == 0.0) { | 215 if (value == 0.0 && otherValue == 0.0) { |
216 return value.isNegative() == otherValue.isNegative(); | 216 return value.isNegative() == otherValue.isNegative(); |
217 } else if (value.isNaN()) { | 217 } else if (value.isNaN()) { |
218 return otherValue.isNaN(); | 218 return otherValue.isNaN(); |
219 } else { | 219 } else { |
220 return value == otherValue; | 220 return value == otherValue; |
221 } | 221 } |
222 } | 222 } |
223 | 223 |
224 int hashCode() => value.hashCode(); | 224 int get hashCode => value.hashCode; |
225 DartString toDartString() => new DartString.literal(value.toString()); | 225 DartString toDartString() => new DartString.literal(value.toString()); |
226 | 226 |
227 accept(ConstantVisitor visitor) => visitor.visitDouble(this); | 227 accept(ConstantVisitor visitor) => visitor.visitDouble(this); |
228 } | 228 } |
229 | 229 |
230 abstract class BoolConstant extends PrimitiveConstant { | 230 abstract class BoolConstant extends PrimitiveConstant { |
231 factory BoolConstant(value) { | 231 factory BoolConstant(value) { |
232 return value ? new TrueConstant() : new FalseConstant(); | 232 return value ? new TrueConstant() : new FalseConstant(); |
233 } | 233 } |
234 const BoolConstant._internal(); | 234 const BoolConstant._internal(); |
(...skipping 11 matching lines...) Expand all Loading... |
246 | 246 |
247 factory TrueConstant() => const TrueConstant._internal(); | 247 factory TrueConstant() => const TrueConstant._internal(); |
248 const TrueConstant._internal() : super._internal(); | 248 const TrueConstant._internal() : super._internal(); |
249 bool isTrue() => true; | 249 bool isTrue() => true; |
250 | 250 |
251 FalseConstant negate() => new FalseConstant(); | 251 FalseConstant negate() => new FalseConstant(); |
252 | 252 |
253 bool operator ==(var other) => identical(this, other); | 253 bool operator ==(var other) => identical(this, other); |
254 // The magic constant is just a random value. It does not have any | 254 // The magic constant is just a random value. It does not have any |
255 // significance. | 255 // significance. |
256 int hashCode() => 499; | 256 int get hashCode => 499; |
257 DartString toDartString() => const LiteralDartString("true"); | 257 DartString toDartString() => const LiteralDartString("true"); |
258 | 258 |
259 accept(ConstantVisitor visitor) => visitor.visitTrue(this); | 259 accept(ConstantVisitor visitor) => visitor.visitTrue(this); |
260 } | 260 } |
261 | 261 |
262 class FalseConstant extends BoolConstant { | 262 class FalseConstant extends BoolConstant { |
263 final bool value = false; | 263 final bool value = false; |
264 | 264 |
265 factory FalseConstant() => const FalseConstant._internal(); | 265 factory FalseConstant() => const FalseConstant._internal(); |
266 const FalseConstant._internal() : super._internal(); | 266 const FalseConstant._internal() : super._internal(); |
267 bool isFalse() => true; | 267 bool isFalse() => true; |
268 | 268 |
269 TrueConstant negate() => new TrueConstant(); | 269 TrueConstant negate() => new TrueConstant(); |
270 | 270 |
271 bool operator ==(var other) => identical(this, other); | 271 bool operator ==(var other) => identical(this, other); |
272 // The magic constant is just a random value. It does not have any | 272 // The magic constant is just a random value. It does not have any |
273 // significance. | 273 // significance. |
274 int hashCode() => 536555975; | 274 int get hashCode => 536555975; |
275 DartString toDartString() => const LiteralDartString("false"); | 275 DartString toDartString() => const LiteralDartString("false"); |
276 | 276 |
277 accept(ConstantVisitor visitor) => visitor.visitFalse(this); | 277 accept(ConstantVisitor visitor) => visitor.visitFalse(this); |
278 } | 278 } |
279 | 279 |
280 class StringConstant extends PrimitiveConstant { | 280 class StringConstant extends PrimitiveConstant { |
281 final DartString value; | 281 final DartString value; |
282 int _hashCode; | 282 final int hashCode; |
283 final Node node; | 283 final Node node; |
284 | 284 |
285 StringConstant(this.value, this.node) { | 285 // TODO(floitsch): cache StringConstants. |
286 // TODO(floitsch): cache StringConstants. | 286 // TODO(floitsch): compute hashcode without calling toString() on the |
287 // TODO(floitsch): compute hashcode without calling toString() on the | 287 // DartString. |
288 // DartString. | 288 StringConstant(DartString value, this.node) |
289 _hashCode = value.slowToString().hashCode(); | 289 : this.value = value, |
290 } | 290 this.hashCode = value.slowToString().hashCode; |
291 bool isString() => true; | 291 bool isString() => true; |
292 | 292 |
293 DartType computeType(Compiler compiler) { | 293 DartType computeType(Compiler compiler) { |
294 return compiler.stringClass.computeType(compiler); | 294 return compiler.stringClass.computeType(compiler); |
295 } | 295 } |
296 | 296 |
297 bool operator ==(var other) { | 297 bool operator ==(var other) { |
298 if (other is !StringConstant) return false; | 298 if (other is !StringConstant) return false; |
299 StringConstant otherString = other; | 299 StringConstant otherString = other; |
300 return (_hashCode == otherString._hashCode) && (value == otherString.value); | 300 return (hashCode == otherString.hashCode) && (value == otherString.value); |
301 } | 301 } |
302 | 302 |
303 int hashCode() => _hashCode; | |
304 DartString toDartString() => value; | 303 DartString toDartString() => value; |
305 int get length => value.length; | 304 int get length => value.length; |
306 | 305 |
307 accept(ConstantVisitor visitor) => visitor.visitString(this); | 306 accept(ConstantVisitor visitor) => visitor.visitString(this); |
308 } | 307 } |
309 | 308 |
310 abstract class ObjectConstant extends Constant { | 309 abstract class ObjectConstant extends Constant { |
311 final DartType type; | 310 final DartType type; |
312 | 311 |
313 ObjectConstant(this.type); | 312 ObjectConstant(this.type); |
314 bool isObject() => true; | 313 bool isObject() => true; |
315 | 314 |
316 DartType computeType(Compiler compiler) => type; | 315 DartType computeType(Compiler compiler) => type; |
317 | 316 |
318 // 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 |
319 // currently allow this. | 318 // currently allow this. |
320 abstract int hashCode(); | 319 abstract int get hashCode; |
321 } | 320 } |
322 | 321 |
323 class ListConstant extends ObjectConstant { | 322 class ListConstant extends ObjectConstant { |
324 final List<Constant> entries; | 323 final List<Constant> entries; |
325 int _hashCode; | 324 final int hashCode; |
326 | 325 |
327 ListConstant(DartType type, this.entries) : super(type) { | 326 ListConstant(DartType type, List<Constant> entries) |
| 327 : this.entries = entries, |
| 328 hashCode = _computeHash(entries), |
| 329 super(type); |
| 330 bool isList() => true; |
| 331 |
| 332 static int _computeHash(List<Constant> entries) { |
328 // TODO(floitsch): create a better hash. | 333 // TODO(floitsch): create a better hash. |
329 int hash = 0; | 334 int hash = 0; |
330 for (Constant input in entries) hash ^= input.hashCode(); | 335 for (Constant input in entries) hash ^= input.hashCode; |
331 _hashCode = hash; | 336 return hash; |
332 } | 337 } |
333 bool isList() => true; | |
334 | 338 |
335 bool operator ==(var other) { | 339 bool operator ==(var other) { |
336 if (other is !ListConstant) return false; | 340 if (other is !ListConstant) return false; |
337 ListConstant otherList = other; | 341 ListConstant otherList = other; |
338 if (hashCode() != otherList.hashCode()) return false; | 342 if (hashCode != otherList.hashCode) return false; |
339 // TODO(floitsch): verify that the generic types are the same. | 343 // TODO(floitsch): verify that the generic types are the same. |
340 if (entries.length != otherList.entries.length) return false; | 344 if (entries.length != otherList.entries.length) return false; |
341 for (int i = 0; i < entries.length; i++) { | 345 for (int i = 0; i < entries.length; i++) { |
342 if (entries[i] != otherList.entries[i]) return false; | 346 if (entries[i] != otherList.entries[i]) return false; |
343 } | 347 } |
344 return true; | 348 return true; |
345 } | 349 } |
346 | 350 |
347 int hashCode() => _hashCode; | |
348 | |
349 List<Constant> getDependencies() => entries; | 351 List<Constant> getDependencies() => entries; |
350 | 352 |
351 int get length => entries.length; | 353 int get length => entries.length; |
352 | 354 |
353 accept(ConstantVisitor visitor) => visitor.visitList(this); | 355 accept(ConstantVisitor visitor) => visitor.visitList(this); |
354 } | 356 } |
355 | 357 |
356 class MapConstant extends ObjectConstant { | 358 class MapConstant extends ObjectConstant { |
357 /** | 359 /** |
358 * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript | 360 * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript |
359 * object. It would change the prototype chain. | 361 * object. It would change the prototype chain. |
360 */ | 362 */ |
361 static const LiteralDartString PROTO_PROPERTY = | 363 static const LiteralDartString PROTO_PROPERTY = |
362 const LiteralDartString("__proto__"); | 364 const LiteralDartString("__proto__"); |
363 | 365 |
364 /** The dart class implementing constant map literals. */ | 366 /** The dart class implementing constant map literals. */ |
365 static const SourceString DART_CLASS = const SourceString("ConstantMap"); | 367 static const SourceString DART_CLASS = const SourceString("ConstantMap"); |
366 static const SourceString DART_PROTO_CLASS = | 368 static const SourceString DART_PROTO_CLASS = |
367 const SourceString("ConstantProtoMap"); | 369 const SourceString("ConstantProtoMap"); |
368 static const SourceString LENGTH_NAME = const SourceString("length"); | 370 static const SourceString LENGTH_NAME = const SourceString("length"); |
369 static const SourceString JS_OBJECT_NAME = const SourceString("_jsObject"); | 371 static const SourceString JS_OBJECT_NAME = const SourceString("_jsObject"); |
370 static const SourceString KEYS_NAME = const SourceString("_keys"); | 372 static const SourceString KEYS_NAME = const SourceString("_keys"); |
371 static const SourceString PROTO_VALUE = const SourceString("_protoValue"); | 373 static const SourceString PROTO_VALUE = const SourceString("_protoValue"); |
372 | 374 |
373 final ListConstant keys; | 375 final ListConstant keys; |
374 final List<Constant> values; | 376 final List<Constant> values; |
375 final Constant protoValue; | 377 final Constant protoValue; |
376 int _hashCode; | 378 final int hashCode; |
377 | 379 |
378 MapConstant(DartType type, this.keys, this.values, this.protoValue) | 380 MapConstant(DartType type, this.keys, List<Constant> values, this.protoValue) |
379 : super(type) { | 381 : this.values = values, |
| 382 this.hashCode = computeHash(values), |
| 383 super(type); |
| 384 bool isMap() => true; |
| 385 |
| 386 static int computeHash(List<Constant> values) { |
380 // TODO(floitsch): create a better hash. | 387 // TODO(floitsch): create a better hash. |
381 int hash = 0; | 388 int hash = 0; |
382 for (Constant value in values) hash ^= value.hashCode(); | 389 for (Constant value in values) hash ^= value.hashCode; |
383 _hashCode = hash; | 390 return hash; |
384 } | 391 } |
385 bool isMap() => true; | |
386 | 392 |
387 bool operator ==(var other) { | 393 bool operator ==(var other) { |
388 if (other is !MapConstant) return false; | 394 if (other is !MapConstant) return false; |
389 MapConstant otherMap = other; | 395 MapConstant otherMap = other; |
390 if (hashCode() != otherMap.hashCode()) return false; | 396 if (hashCode != otherMap.hashCode) return false; |
391 // TODO(floitsch): verify that the generic types are the same. | 397 // TODO(floitsch): verify that the generic types are the same. |
392 if (keys != otherMap.keys) return false; | 398 if (keys != otherMap.keys) return false; |
393 for (int i = 0; i < values.length; i++) { | 399 for (int i = 0; i < values.length; i++) { |
394 if (values[i] != otherMap.values[i]) return false; | 400 if (values[i] != otherMap.values[i]) return false; |
395 } | 401 } |
396 return true; | 402 return true; |
397 } | 403 } |
398 | 404 |
399 int hashCode() => _hashCode; | |
400 | |
401 List<Constant> getDependencies() { | 405 List<Constant> getDependencies() { |
402 List<Constant> result = <Constant>[keys]; | 406 List<Constant> result = <Constant>[keys]; |
403 result.addAll(values); | 407 result.addAll(values); |
404 return result; | 408 return result; |
405 } | 409 } |
406 | 410 |
407 int get length => keys.length; | 411 int get length => keys.length; |
408 | 412 |
409 accept(ConstantVisitor visitor) => visitor.visitMap(this); | 413 accept(ConstantVisitor visitor) => visitor.visitMap(this); |
410 } | 414 } |
411 | 415 |
412 class ConstructedConstant extends ObjectConstant { | 416 class ConstructedConstant extends ObjectConstant { |
413 final List<Constant> fields; | 417 final List<Constant> fields; |
414 int _hashCode; | 418 final int hashCode; |
415 | 419 |
416 ConstructedConstant(DartType type, this.fields) : super(type) { | 420 ConstructedConstant(DartType type, List<Constant> fields) |
| 421 : this.fields = fields, |
| 422 hashCode = computeHash(type, fields), |
| 423 super(type) { |
417 assert(type != null); | 424 assert(type != null); |
| 425 } |
| 426 bool isConstructedObject() => true; |
| 427 |
| 428 static int computeHash(DartType type, List<Constant> fields) { |
418 // TODO(floitsch): create a better hash. | 429 // TODO(floitsch): create a better hash. |
419 int hash = 0; | 430 int hash = 0; |
420 for (Constant field in fields) { | 431 for (Constant field in fields) { |
421 hash ^= field.hashCode(); | 432 hash ^= field.hashCode; |
422 } | 433 } |
423 hash ^= type.element.hashCode(); | 434 hash ^= type.element.hashCode; |
424 _hashCode = hash; | 435 return hash; |
425 } | 436 } |
426 bool isConstructedObject() => true; | |
427 | 437 |
428 bool operator ==(var otherVar) { | 438 bool operator ==(var otherVar) { |
429 if (otherVar is !ConstructedConstant) return false; | 439 if (otherVar is !ConstructedConstant) return false; |
430 ConstructedConstant other = otherVar; | 440 ConstructedConstant other = otherVar; |
431 if (hashCode() != other.hashCode()) return false; | 441 if (hashCode != other.hashCode) return false; |
432 // TODO(floitsch): verify that the (generic) types are the same. | 442 // TODO(floitsch): verify that the (generic) types are the same. |
433 if (type.element != other.type.element) return false; | 443 if (type.element != other.type.element) return false; |
434 if (fields.length != other.fields.length) return false; | 444 if (fields.length != other.fields.length) return false; |
435 for (int i = 0; i < fields.length; i++) { | 445 for (int i = 0; i < fields.length; i++) { |
436 if (fields[i] != other.fields[i]) return false; | 446 if (fields[i] != other.fields[i]) return false; |
437 } | 447 } |
438 return true; | 448 return true; |
439 } | 449 } |
440 | 450 |
441 int hashCode() => _hashCode; | |
442 List<Constant> getDependencies() => fields; | 451 List<Constant> getDependencies() => fields; |
443 | 452 |
444 accept(ConstantVisitor visitor) => visitor.visitConstructed(this); | 453 accept(ConstantVisitor visitor) => visitor.visitConstructed(this); |
445 } | 454 } |
OLD | NEW |