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

Unified Diff: frog/leg/compile_time_constants.dart

Issue 9665001: Implement constant maps. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cosmetic changes. Created 8 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | frog/leg/lib/constant_map.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: frog/leg/compile_time_constants.dart
diff --git a/frog/leg/compile_time_constants.dart b/frog/leg/compile_time_constants.dart
index 4199c4faea516bd6cc862eee5615f554ed81c367..8967bb5cf19df6cd47f6b4ac1bf346980b6bb21c 100644
--- a/frog/leg/compile_time_constants.dart
+++ b/frog/leg/compile_time_constants.dart
@@ -275,7 +275,7 @@ class ListConstant extends ObjectConstant {
if (other is !ListConstant) return false;
ListConstant otherList = other;
if (hashCode() != otherList.hashCode()) return false;
- // TODO(floitsch): verify that the types are the same.
+ // TODO(floitsch): verify that the generic types are the same.
if (entries.length != otherList.entries.length) return false;
for (int i = 0; i < entries.length; i++) {
if (entries[i] != otherList.entries[i]) return false;
@@ -286,6 +286,93 @@ class ListConstant extends ObjectConstant {
int hashCode() => _hashCode;
}
+class MapConstant extends ObjectConstant {
+ /** The dart class implementing constant map literals. */
+ static final SourceString DART_CLASS = const SourceString("ConstantMap");
+ static final SourceString LENGTH_NAME = const SourceString("length");
+ static final SourceString JS_OBJECT_NAME = const SourceString("_jsObject");
+ static final SourceString KEYS_NAME = const SourceString("_keys");
+
+ final ListConstant keys;
+ final List<Constant> values;
+ int _hashCode;
+
+ MapConstant(Type type, this.keys, this.values) : super(type) {
+ // TODO(floitsch): create a better hash.
+ int hash = 0;
+ for (Constant value in values) hash ^= value.hashCode();
+ _hashCode = hash;
+ }
+ bool isMap() => true;
+
+ void writeJsCode(StringBuffer buffer, ConstantHandler handler) {
+ void writeJsMap() {
+ String isolatePrototype = "${handler.compiler.namer.ISOLATE}.prototype";
+ buffer.add("{");
+ for (int i = 0; i < keys.entries.length; i++) {
+ if (i != 0) buffer.add(", ");
+
+ StringConstant key = keys.entries[i];
+ key.writeJsCode(buffer, handler);
+ buffer.add(": ");
+ Constant value = values[i];
+ // TODO(floitsch): share this code with the ListConstant and
+ // ConstructedConstant.
+ if (value.isObject()) {
+ String name = handler.getNameForConstant(value);
+ buffer.add("$isolatePrototype.$name");
+ } else {
+ value.writeJsCode(buffer, handler);
+ }
+ }
+ buffer.add("}");
+ }
+
+ buffer.add("new ");
+ buffer.add(handler.getJsConstructor(type.element));
+ buffer.add("(");
+ // We have to send the arguments in the same order as they appear in the
+ // 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.
+ int emittedArgumentCount = 0;
+ ClassElement classElement = type.element;
ngeoffray 2012/03/09 18:08:50 Share that with line 332.
floitsch 2012/03/10 17:40:24 Done.
+ for (Element element in classElement.members) {
+ if (element.name == LENGTH_NAME) {
+ buffer.add(keys.entries.length);
+ } else if (element.name == JS_OBJECT_NAME) {
+ writeJsMap();
+ } else if (element.name == KEYS_NAME) {
+ keys.writeJsCode(buffer, handler);
+ } else {
+ 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.
+ }
+ emittedArgumentCount++;
+ if (emittedArgumentCount == 3) {
+ break; // All arguments have been emitted.
+ } else {
+ buffer.add(", ");
+ }
+ }
+ if (emittedArgumentCount != 3) {
+ 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.
+ }
+ buffer.add(")");
+ }
+
+ bool operator ==(var other) {
+ if (other is !MapConstant) return false;
+ MapConstant otherMap = other;
+ if (hashCode() != otherMap.hashCode()) return false;
+ // TODO(floitsch): verify that the generic types are the same.
+ if (keys != otherMap.keys) return false;
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] != otherMap.values[i]) return false;
+ }
+ return true;
+ }
+
+ int hashCode() => _hashCode;
+}
+
class ConstructedConstant extends ObjectConstant {
final List<Constant> fields;
int _hashCode;
@@ -312,7 +399,7 @@ class ConstructedConstant extends ObjectConstant {
Constant field = fields[i];
// TODO(floitsch): share this code with the ListConstant.
if (field.isObject()) {
- String name = handler.getNameForConstant(entry);
+ String name = handler.getNameForConstant(field);
buffer.add("$isolatePrototype.$name");
} else {
field.writeJsCode(buffer, handler);
@@ -592,7 +679,7 @@ class CompileTimeConstantEvaluator extends AbstractVisitor {
Constant visitLiteralList(LiteralList node) {
if (!node.isConst()) error(node);
- List arguments = [];
+ List<Constant> arguments = <Constant>[];
for (Link<Node> link = node.elements.nodes;
!link.isEmpty();
link = link.tail) {
@@ -604,7 +691,37 @@ class CompileTimeConstantEvaluator extends AbstractVisitor {
}
Constant visitLiteralMap(LiteralMap node) {
- compiler.unimplemented("CompileTimeConstantEvaluator map", node: node);
+ // TODO(floitsch): check for isConst, once the parser adds it into the node.
+ // if (!node.isConst()) error(node);
+ List<StringConstant> keys = <StringConstant>[];
+ List<Constant> values = <Constant>[];
+ for (Link<Node> link = node.entries.nodes;
+ !link.isEmpty();
+ link = link.tail) {
+ LiteralMapEntry entry = link.head;
+ Constant key = evaluate(entry.key);
+ if (!key.isString()) {
+ compiler.internalError("Key for literal map not a String",
+ node: entry.key);
+ }
+ keys.add(key);
+ values.add(evaluate(entry.value));
+ }
+ // TODO(floitsch): this should be a List<String> type.
+ Type keysType = null;
+ ListConstant keysList = new ListConstant(keysType, keys);
+ // We don't actually need to register the constant, but there is no reason
+ // not to.
+ constantHandler.registerCompileTimeConstant(keysList);
+ ClassElement classElement =
+ compiler.jsHelperLibrary.find(MapConstant.DART_CLASS);
+ classElement.resolve(compiler);
+ // TODO(floitsch): copy over the generic type.
+ Type type = new SimpleType(classElement.name, classElement);
+ compiler.registerInstantiatedClass(classElement);
+ Constant constant = new MapConstant(type, keysList, values);
+ constantHandler.registerCompileTimeConstant(constant);
+ return constant;
}
Constant visitLiteralNull(LiteralNull node) {
« no previous file with comments | « no previous file | frog/leg/lib/constant_map.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698