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 class Constant implements Hashable { | 5 class Constant implements Hashable { |
6 const Constant(); | 6 const Constant(); |
7 | 7 |
8 bool isNull() => false; | 8 bool isNull() => false; |
9 bool isBool() => false; | 9 bool isBool() => false; |
10 bool isTrue() => false; | 10 bool isTrue() => false; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 entry.writeJsCode(buffer, handler); | 268 entry.writeJsCode(buffer, handler); |
269 } | 269 } |
270 } | 270 } |
271 buffer.add("])"); | 271 buffer.add("])"); |
272 } | 272 } |
273 | 273 |
274 bool operator ==(var other) { | 274 bool operator ==(var other) { |
275 if (other is !ListConstant) return false; | 275 if (other is !ListConstant) return false; |
276 ListConstant otherList = other; | 276 ListConstant otherList = other; |
277 if (hashCode() != otherList.hashCode()) return false; | 277 if (hashCode() != otherList.hashCode()) return false; |
278 // TODO(floitsch): verify that the types are the same. | 278 // TODO(floitsch): verify that the generic types are the same. |
279 if (entries.length != otherList.entries.length) return false; | 279 if (entries.length != otherList.entries.length) return false; |
280 for (int i = 0; i < entries.length; i++) { | 280 for (int i = 0; i < entries.length; i++) { |
281 if (entries[i] != otherList.entries[i]) return false; | 281 if (entries[i] != otherList.entries[i]) return false; |
282 } | 282 } |
283 return true; | 283 return true; |
284 } | 284 } |
285 | 285 |
286 int hashCode() => _hashCode; | 286 int hashCode() => _hashCode; |
287 } | 287 } |
288 | 288 |
289 class MapConstant extends ObjectConstant { | |
290 /** The dart class implementing constant map literals. */ | |
291 static final SourceString DART_CLASS = const SourceString("ConstantMap"); | |
292 static final SourceString LENGTH_NAME = const SourceString("length"); | |
293 static final SourceString JS_OBJECT_NAME = const SourceString("_jsObject"); | |
294 static final SourceString KEYS_NAME = const SourceString("_keys"); | |
295 | |
296 final ListConstant keys; | |
297 final List<Constant> values; | |
298 int _hashCode; | |
299 | |
300 MapConstant(Type type, this.keys, this.values) : super(type) { | |
301 // TODO(floitsch): create a better hash. | |
302 int hash = 0; | |
303 for (Constant value in values) hash ^= value.hashCode(); | |
304 _hashCode = hash; | |
305 } | |
306 bool isMap() => true; | |
307 | |
308 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { | |
309 void writeJsMap() { | |
310 String isolatePrototype = "${handler.compiler.namer.ISOLATE}.prototype"; | |
311 buffer.add("{"); | |
312 for (int i = 0; i < keys.entries.length; i++) { | |
313 if (i != 0) buffer.add(", "); | |
314 | |
315 StringConstant key = keys.entries[i]; | |
316 key.writeJsCode(buffer, handler); | |
317 buffer.add(": "); | |
318 Constant value = values[i]; | |
319 // TODO(floitsch): share this code with the ListConstant and | |
320 // ConstructedConstant. | |
321 if (value.isObject()) { | |
322 String name = handler.getNameForConstant(value); | |
323 buffer.add("$isolatePrototype.$name"); | |
324 } else { | |
325 value.writeJsCode(buffer, handler); | |
326 } | |
327 } | |
328 buffer.add("}"); | |
329 } | |
330 | |
331 buffer.add("new "); | |
332 buffer.add(handler.getJsConstructor(type.element)); | |
333 buffer.add("("); | |
334 // We have to send the arguments in the same order as they appear in the | |
335 // class element. | |
ngeoffray
2012/03/09 18:08:50
Please also say that it's because we emit the orde
floitsch
2012/03/10 17:40:24
Done.
| |
336 int emittedArgumentCount = 0; | |
337 ClassElement classElement = type.element; | |
ngeoffray
2012/03/09 18:08:50
Share that with line 332.
floitsch
2012/03/10 17:40:24
Done.
| |
338 for (Element element in classElement.members) { | |
339 if (element.name == LENGTH_NAME) { | |
340 buffer.add(keys.entries.length); | |
341 } else if (element.name == JS_OBJECT_NAME) { | |
342 writeJsMap(); | |
343 } else if (element.name == KEYS_NAME) { | |
344 keys.writeJsCode(buffer, handler); | |
345 } else { | |
346 continue; | |
ngeoffray
2012/03/09 18:08:50
Please add a comment that this is for methods.
floitsch
2012/03/10 17:40:24
Done.
| |
347 } | |
348 emittedArgumentCount++; | |
349 if (emittedArgumentCount == 3) { | |
350 break; // All arguments have been emitted. | |
351 } else { | |
352 buffer.add(", "); | |
353 } | |
354 } | |
355 if (emittedArgumentCount != 3) { | |
356 handler.compiler.internalError("Could not generate constant map"); | |
ngeoffray
2012/03/09 18:08:50
Maybe say something more explicit like: "compiler
floitsch
2012/03/10 17:40:24
Done.
| |
357 } | |
358 buffer.add(")"); | |
359 } | |
360 | |
361 bool operator ==(var other) { | |
362 if (other is !MapConstant) return false; | |
363 MapConstant otherMap = other; | |
364 if (hashCode() != otherMap.hashCode()) return false; | |
365 // TODO(floitsch): verify that the generic types are the same. | |
366 if (keys != otherMap.keys) return false; | |
367 for (int i = 0; i < values.length; i++) { | |
368 if (values[i] != otherMap.values[i]) return false; | |
369 } | |
370 return true; | |
371 } | |
372 | |
373 int hashCode() => _hashCode; | |
374 } | |
375 | |
289 class ConstructedConstant extends ObjectConstant { | 376 class ConstructedConstant extends ObjectConstant { |
290 final List<Constant> fields; | 377 final List<Constant> fields; |
291 int _hashCode; | 378 int _hashCode; |
292 | 379 |
293 ConstructedConstant(Type type, this.fields) : super(type) { | 380 ConstructedConstant(Type type, this.fields) : super(type) { |
294 assert(type !== null); | 381 assert(type !== null); |
295 // TODO(floitsch): create a better hash. | 382 // TODO(floitsch): create a better hash. |
296 int hash = 0; | 383 int hash = 0; |
297 for (Constant field in fields) { | 384 for (Constant field in fields) { |
298 hash ^= field.hashCode(); | 385 hash ^= field.hashCode(); |
299 } | 386 } |
300 hash ^= type.element.hashCode(); | 387 hash ^= type.element.hashCode(); |
301 _hashCode = hash; | 388 _hashCode = hash; |
302 } | 389 } |
303 bool isConstructedObject() => true; | 390 bool isConstructedObject() => true; |
304 | 391 |
305 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { | 392 void writeJsCode(StringBuffer buffer, ConstantHandler handler) { |
306 buffer.add("new "); | 393 buffer.add("new "); |
307 buffer.add(handler.getJsConstructor(type.element)); | 394 buffer.add(handler.getJsConstructor(type.element)); |
308 buffer.add("("); | 395 buffer.add("("); |
309 String isolatePrototype = "${handler.compiler.namer.ISOLATE}.prototype"; | 396 String isolatePrototype = "${handler.compiler.namer.ISOLATE}.prototype"; |
310 for (int i = 0; i < fields.length; i++) { | 397 for (int i = 0; i < fields.length; i++) { |
311 if (i != 0) buffer.add(", "); | 398 if (i != 0) buffer.add(", "); |
312 Constant field = fields[i]; | 399 Constant field = fields[i]; |
313 // TODO(floitsch): share this code with the ListConstant. | 400 // TODO(floitsch): share this code with the ListConstant. |
314 if (field.isObject()) { | 401 if (field.isObject()) { |
315 String name = handler.getNameForConstant(entry); | 402 String name = handler.getNameForConstant(field); |
316 buffer.add("$isolatePrototype.$name"); | 403 buffer.add("$isolatePrototype.$name"); |
317 } else { | 404 } else { |
318 field.writeJsCode(buffer, handler); | 405 field.writeJsCode(buffer, handler); |
319 } | 406 } |
320 } | 407 } |
321 buffer.add(")"); | 408 buffer.add(")"); |
322 } | 409 } |
323 | 410 |
324 bool operator ==(var otherVar) { | 411 bool operator ==(var otherVar) { |
325 if (otherVar is !ConstructedConstant) return false; | 412 if (otherVar is !ConstructedConstant) return false; |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
585 Constant visitLiteralDouble(LiteralDouble node) { | 672 Constant visitLiteralDouble(LiteralDouble node) { |
586 return new DoubleConstant(node.value); | 673 return new DoubleConstant(node.value); |
587 } | 674 } |
588 | 675 |
589 Constant visitLiteralInt(LiteralInt node) { | 676 Constant visitLiteralInt(LiteralInt node) { |
590 return new IntConstant(node.value); | 677 return new IntConstant(node.value); |
591 } | 678 } |
592 | 679 |
593 Constant visitLiteralList(LiteralList node) { | 680 Constant visitLiteralList(LiteralList node) { |
594 if (!node.isConst()) error(node); | 681 if (!node.isConst()) error(node); |
595 List arguments = []; | 682 List<Constant> arguments = <Constant>[]; |
596 for (Link<Node> link = node.elements.nodes; | 683 for (Link<Node> link = node.elements.nodes; |
597 !link.isEmpty(); | 684 !link.isEmpty(); |
598 link = link.tail) { | 685 link = link.tail) { |
599 arguments.add(evaluate(link.head)); | 686 arguments.add(evaluate(link.head)); |
600 } | 687 } |
601 // TODO(floitsch): get type from somewhere. | 688 // TODO(floitsch): get type from somewhere. |
602 Type type = null; | 689 Type type = null; |
603 return constantHandler.compileListLiteral(node, type, arguments); | 690 return constantHandler.compileListLiteral(node, type, arguments); |
604 } | 691 } |
605 | 692 |
606 Constant visitLiteralMap(LiteralMap node) { | 693 Constant visitLiteralMap(LiteralMap node) { |
607 compiler.unimplemented("CompileTimeConstantEvaluator map", node: node); | 694 // TODO(floitsch): check for isConst, once the parser adds it into the node. |
695 // if (!node.isConst()) error(node); | |
696 List<StringConstant> keys = <StringConstant>[]; | |
697 List<Constant> values = <Constant>[]; | |
698 for (Link<Node> link = node.entries.nodes; | |
699 !link.isEmpty(); | |
700 link = link.tail) { | |
701 LiteralMapEntry entry = link.head; | |
702 Constant key = evaluate(entry.key); | |
703 if (!key.isString()) { | |
704 compiler.internalError("Key for literal map not a String", | |
705 node: entry.key); | |
706 } | |
707 keys.add(key); | |
708 values.add(evaluate(entry.value)); | |
709 } | |
710 // TODO(floitsch): this should be a List<String> type. | |
711 Type keysType = null; | |
712 ListConstant keysList = new ListConstant(keysType, keys); | |
713 // We don't actually need to register the constant, but there is no reason | |
714 // not to. | |
715 constantHandler.registerCompileTimeConstant(keysList); | |
716 ClassElement classElement = | |
717 compiler.jsHelperLibrary.find(MapConstant.DART_CLASS); | |
718 classElement.resolve(compiler); | |
719 // TODO(floitsch): copy over the generic type. | |
720 Type type = new SimpleType(classElement.name, classElement); | |
721 compiler.registerInstantiatedClass(classElement); | |
722 Constant constant = new MapConstant(type, keysList, values); | |
723 constantHandler.registerCompileTimeConstant(constant); | |
724 return constant; | |
608 } | 725 } |
609 | 726 |
610 Constant visitLiteralNull(LiteralNull node) { | 727 Constant visitLiteralNull(LiteralNull node) { |
611 return new NullConstant(); | 728 return new NullConstant(); |
612 } | 729 } |
613 | 730 |
614 Constant visitLiteralString(LiteralString node) { | 731 Constant visitLiteralString(LiteralString node) { |
615 return new StringConstant(node.dartString); | 732 return new StringConstant(node.dartString); |
616 } | 733 } |
617 | 734 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
762 arguments); | 879 arguments); |
763 } | 880 } |
764 | 881 |
765 error(Node node) { | 882 error(Node node) { |
766 // TODO(floitsch): get the list of constants that are currently compiled | 883 // TODO(floitsch): get the list of constants that are currently compiled |
767 // and present some kind of stack-trace. | 884 // and present some kind of stack-trace. |
768 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; | 885 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; |
769 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); | 886 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); |
770 } | 887 } |
771 } | 888 } |
OLD | NEW |