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

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

Issue 10696194: Introduce CodeBuffer as StringBuffer replacement in compiler. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: . Created 8 years, 5 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 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;
11 bool isFalse() => false; 11 bool isFalse() => false;
12 bool isInt() => false; 12 bool isInt() => false;
13 bool isDouble() => false; 13 bool isDouble() => false;
14 bool isNum() => false; 14 bool isNum() => false;
15 bool isString() => false; 15 bool isString() => false;
16 bool isList() => false; 16 bool isList() => false;
17 bool isMap() => false; 17 bool isMap() => false;
18 bool isConstructedObject() => false; 18 bool isConstructedObject() => false;
19 /** Returns true if the constant is null, a bool, a number or a string. */ 19 /** Returns true if the constant is null, a bool, a number or a string. */
20 bool isPrimitive() => false; 20 bool isPrimitive() => false;
21 /** Returns true if the constant is a list, a map or a constructed object. */ 21 /** Returns true if the constant is a list, a map or a constructed object. */
22 bool isObject() => false; 22 bool isObject() => false;
23 23
24 bool isNaN() => false; 24 bool isNaN() => false;
25 25
26 abstract void _writeJsCode(StringBuffer buffer, ConstantHandler handler); 26 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler);
27 /** 27 /**
28 * Unless the constant can be emitted multiple times (as for numbers and 28 * Unless the constant can be emitted multiple times (as for numbers and
29 * strings) adds its canonical name to the buffer. 29 * strings) adds its canonical name to the buffer.
30 */ 30 */
31 abstract void _writeCanonicalizedJsCode(StringBuffer buffer, 31 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer,
32 ConstantHandler handler); 32 ConstantHandler handler);
33 abstract List<Constant> getDependencies(); 33 abstract List<Constant> getDependencies();
34 } 34 }
35 35
36 class PrimitiveConstant extends Constant { 36 class PrimitiveConstant extends Constant {
37 abstract get value(); 37 abstract get value();
38 const PrimitiveConstant(); 38 const PrimitiveConstant();
39 bool isPrimitive() => true; 39 bool isPrimitive() => true;
40 40
41 bool operator ==(var other) { 41 bool operator ==(var other) {
42 if (other is !PrimitiveConstant) return false; 42 if (other is !PrimitiveConstant) return false;
43 PrimitiveConstant otherPrimitive = other; 43 PrimitiveConstant otherPrimitive = other;
44 // We use == instead of === so that DartStrings compare correctly. 44 // We use == instead of === so that DartStrings compare correctly.
45 return value == otherPrimitive.value; 45 return value == otherPrimitive.value;
46 } 46 }
47 47
48 String toString() => value.toString(); 48 String toString() => value.toString();
49 // Primitive constants don't have dependencies. 49 // Primitive constants don't have dependencies.
50 List<Constant> getDependencies() => const <Constant>[]; 50 List<Constant> getDependencies() => const <Constant>[];
51 abstract DartString toDartString(); 51 abstract DartString toDartString();
52 52
53 void _writeCanonicalizedJsCode(StringBuffer buffer, ConstantHandler handler) { 53 void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
54 _writeJsCode(buffer, handler); 54 _writeJsCode(buffer, handler);
55 } 55 }
56 } 56 }
57 57
58 class NullConstant extends PrimitiveConstant { 58 class NullConstant extends PrimitiveConstant {
59 /** The value a Dart null is compiled to in JavaScript. */ 59 /** The value a Dart null is compiled to in JavaScript. */
60 static final String JsNull = "null"; 60 static final String JsNull = "null";
61 61
62 factory NullConstant() => const NullConstant._internal(); 62 factory NullConstant() => const NullConstant._internal();
63 const NullConstant._internal(); 63 const NullConstant._internal();
64 bool isNull() => true; 64 bool isNull() => true;
65 get value() => null; 65 get value() => null;
66 66
67 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 67 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
68 buffer.add(JsNull); 68 buffer.add(JsNull);
69 } 69 }
70 70
71 // The magic constant has no meaning. It is just a random value. 71 // The magic constant has no meaning. It is just a random value.
72 int hashCode() => 785965825; 72 int hashCode() => 785965825;
73 DartString toDartString() => const LiteralDartString("null"); 73 DartString toDartString() => const LiteralDartString("null");
74 } 74 }
75 75
76 class NumConstant extends PrimitiveConstant { 76 class NumConstant extends PrimitiveConstant {
77 abstract num get value(); 77 abstract num get value();
(...skipping 17 matching lines...) Expand all
95 case 9: return const IntConstant._internal(9); 95 case 9: return const IntConstant._internal(9);
96 case 10: return const IntConstant._internal(10); 96 case 10: return const IntConstant._internal(10);
97 case -1: return const IntConstant._internal(-1); 97 case -1: return const IntConstant._internal(-1);
98 case -2: return const IntConstant._internal(-2); 98 case -2: return const IntConstant._internal(-2);
99 default: return new IntConstant._internal(value); 99 default: return new IntConstant._internal(value);
100 } 100 }
101 } 101 }
102 const IntConstant._internal(this.value); 102 const IntConstant._internal(this.value);
103 bool isInt() => true; 103 bool isInt() => true;
104 104
105 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 105 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
106 buffer.add("$value"); 106 buffer.add("$value");
107 } 107 }
108 108
109 // We have to override the equality operator so that ints and doubles are 109 // We have to override the equality operator so that ints and doubles are
110 // treated as separate constants. 110 // treated as separate constants.
111 // The is [:!IntConstant:] check at the beginning of the function makes sure 111 // The is [:!IntConstant:] check at the beginning of the function makes sure
112 // that we compare only equal to integer constants. 112 // that we compare only equal to integer constants.
113 bool operator ==(var other) { 113 bool operator ==(var other) {
114 if (other is !IntConstant) return false; 114 if (other is !IntConstant) return false;
115 IntConstant otherInt = other; 115 IntConstant otherInt = other;
(...skipping 18 matching lines...) Expand all
134 } else if (value == 1.0) { 134 } else if (value == 1.0) {
135 return const DoubleConstant._internal(1.0); 135 return const DoubleConstant._internal(1.0);
136 } else { 136 } else {
137 return new DoubleConstant._internal(value); 137 return new DoubleConstant._internal(value);
138 } 138 }
139 } 139 }
140 const DoubleConstant._internal(this.value); 140 const DoubleConstant._internal(this.value);
141 bool isDouble() => true; 141 bool isDouble() => true;
142 bool isNaN() => value.isNaN(); 142 bool isNaN() => value.isNaN();
143 143
144 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 144 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
145 if (value.isNaN()) { 145 if (value.isNaN()) {
146 buffer.add("(0/0)"); 146 buffer.add("(0/0)");
147 } else if (value == double.INFINITY) { 147 } else if (value == double.INFINITY) {
148 buffer.add("(1/0)"); 148 buffer.add("(1/0)");
149 } else if (value == -double.INFINITY) { 149 } else if (value == -double.INFINITY) {
150 buffer.add("(-1/0)"); 150 buffer.add("(-1/0)");
151 } else { 151 } else {
152 buffer.add("$value"); 152 buffer.add("$value");
153 } 153 }
154 } 154 }
(...skipping 30 matching lines...) Expand all
185 abstract BoolConstant negate(); 185 abstract BoolConstant negate();
186 } 186 }
187 187
188 class TrueConstant extends BoolConstant { 188 class TrueConstant extends BoolConstant {
189 final bool value = true; 189 final bool value = true;
190 190
191 factory TrueConstant() => const TrueConstant._internal(); 191 factory TrueConstant() => const TrueConstant._internal();
192 const TrueConstant._internal() : super._internal(); 192 const TrueConstant._internal() : super._internal();
193 bool isTrue() => true; 193 bool isTrue() => true;
194 194
195 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 195 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
196 buffer.add("true"); 196 buffer.add("true");
197 } 197 }
198 198
199 FalseConstant negate() => new FalseConstant(); 199 FalseConstant negate() => new FalseConstant();
200 200
201 bool operator ==(var other) => this === other; 201 bool operator ==(var other) => this === other;
202 // The magic constant is just a random value. It does not have any 202 // The magic constant is just a random value. It does not have any
203 // significance. 203 // significance.
204 int hashCode() => 499; 204 int hashCode() => 499;
205 DartString toDartString() => const LiteralDartString("true"); 205 DartString toDartString() => const LiteralDartString("true");
206 } 206 }
207 207
208 class FalseConstant extends BoolConstant { 208 class FalseConstant extends BoolConstant {
209 final bool value = false; 209 final bool value = false;
210 210
211 factory FalseConstant() => const FalseConstant._internal(); 211 factory FalseConstant() => const FalseConstant._internal();
212 const FalseConstant._internal() : super._internal(); 212 const FalseConstant._internal() : super._internal();
213 bool isFalse() => true; 213 bool isFalse() => true;
214 214
215 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 215 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
216 buffer.add("false"); 216 buffer.add("false");
217 } 217 }
218 218
219 TrueConstant negate() => new TrueConstant(); 219 TrueConstant negate() => new TrueConstant();
220 220
221 bool operator ==(var other) => this === other; 221 bool operator ==(var other) => this === other;
222 // The magic constant is just a random value. It does not have any 222 // The magic constant is just a random value. It does not have any
223 // significance. 223 // significance.
224 int hashCode() => 536555975; 224 int hashCode() => 536555975;
225 DartString toDartString() => const LiteralDartString("false"); 225 DartString toDartString() => const LiteralDartString("false");
226 } 226 }
227 227
228 class StringConstant extends PrimitiveConstant { 228 class StringConstant extends PrimitiveConstant {
229 final DartString value; 229 final DartString value;
230 int _hashCode; 230 int _hashCode;
231 final Node node; 231 final Node node;
232 232
233 StringConstant(this.value, this.node) { 233 StringConstant(this.value, this.node) {
234 // TODO(floitsch): cache StringConstants. 234 // TODO(floitsch): cache StringConstants.
235 // TODO(floitsch): compute hashcode without calling toString() on the 235 // TODO(floitsch): compute hashcode without calling toString() on the
236 // DartString. 236 // DartString.
237 _hashCode = value.slowToString().hashCode(); 237 _hashCode = value.slowToString().hashCode();
238 } 238 }
239 bool isString() => true; 239 bool isString() => true;
240 240
241 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 241 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
242 buffer.add("'"); 242 buffer.add("'");
243 ConstantHandler.writeEscapedString(value, buffer, (reason) { 243 ConstantHandler.writeEscapedString(value, buffer, (reason) {
244 handler.compiler.reportError(node, reason); 244 handler.compiler.reportError(node, reason);
245 }); 245 });
246 buffer.add("'"); 246 buffer.add("'");
247 } 247 }
248 248
249 bool operator ==(var other) { 249 bool operator ==(var other) {
250 if (other is !StringConstant) return false; 250 if (other is !StringConstant) return false;
251 StringConstant otherString = other; 251 StringConstant otherString = other;
252 return (_hashCode == otherString._hashCode) && (value == otherString.value); 252 return (_hashCode == otherString._hashCode) && (value == otherString.value);
253 } 253 }
254 254
255 int hashCode() => _hashCode; 255 int hashCode() => _hashCode;
256 DartString toDartString() => value; 256 DartString toDartString() => value;
257 int get length() => value.length; 257 int get length() => value.length;
258 } 258 }
259 259
260 class ObjectConstant extends Constant { 260 class ObjectConstant extends Constant {
261 final Type type; 261 final Type type;
262 262
263 ObjectConstant(this.type); 263 ObjectConstant(this.type);
264 bool isObject() => true; 264 bool isObject() => true;
265 265
266 // TODO(1603): The class should be marked as abstract, but the VM doesn't 266 // TODO(1603): The class should be marked as abstract, but the VM doesn't
267 // currently allow this. 267 // currently allow this.
268 abstract int hashCode(); 268 abstract int hashCode();
269 269
270 void _writeCanonicalizedJsCode(StringBuffer buffer, ConstantHandler handler) { 270 void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
271 String name = handler.getNameForConstant(this); 271 String name = handler.getNameForConstant(this);
272 buffer.add(handler.compiler.namer.isolatePropertiesAccessForConstant(name)); 272 buffer.add(handler.compiler.namer.isolatePropertiesAccessForConstant(name));
273 } 273 }
274 } 274 }
275 275
276 class ListConstant extends ObjectConstant { 276 class ListConstant extends ObjectConstant {
277 final List<Constant> entries; 277 final List<Constant> entries;
278 int _hashCode; 278 int _hashCode;
279 279
280 ListConstant(Type type, this.entries) : super(type) { 280 ListConstant(Type type, this.entries) : super(type) {
281 // TODO(floitsch): create a better hash. 281 // TODO(floitsch): create a better hash.
282 int hash = 0; 282 int hash = 0;
283 for (Constant input in entries) hash ^= input.hashCode(); 283 for (Constant input in entries) hash ^= input.hashCode();
284 _hashCode = hash; 284 _hashCode = hash;
285 } 285 }
286 bool isList() => true; 286 bool isList() => true;
287 287
288 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 288 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
289 // TODO(floitsch): we should not need to go through the compiler to make 289 // TODO(floitsch): we should not need to go through the compiler to make
290 // the list constant. 290 // the list constant.
291 buffer.add("${handler.compiler.namer.ISOLATE}.makeConstantList"); 291 buffer.add("${handler.compiler.namer.ISOLATE}.makeConstantList");
292 buffer.add("(["); 292 buffer.add("([");
293 for (int i = 0; i < entries.length; i++) { 293 for (int i = 0; i < entries.length; i++) {
294 if (i != 0) buffer.add(", "); 294 if (i != 0) buffer.add(", ");
295 Constant entry = entries[i]; 295 Constant entry = entries[i];
296 handler.writeConstant(buffer, entry); 296 handler.writeConstant(buffer, entry);
297 } 297 }
298 buffer.add("])"); 298 buffer.add("])");
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 340
341 MapConstant(Type type, this.keys, this.values, this.protoValue) 341 MapConstant(Type type, this.keys, this.values, this.protoValue)
342 : super(type) { 342 : super(type) {
343 // TODO(floitsch): create a better hash. 343 // TODO(floitsch): create a better hash.
344 int hash = 0; 344 int hash = 0;
345 for (Constant value in values) hash ^= value.hashCode(); 345 for (Constant value in values) hash ^= value.hashCode();
346 _hashCode = hash; 346 _hashCode = hash;
347 } 347 }
348 bool isMap() => true; 348 bool isMap() => true;
349 349
350 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 350 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
351 351
352 void writeJsMap() { 352 void writeJsMap() {
353 buffer.add("{"); 353 buffer.add("{");
354 int valueIndex = 0; 354 int valueIndex = 0;
355 for (int i = 0; i < keys.entries.length; i++) { 355 for (int i = 0; i < keys.entries.length; i++) {
356 StringConstant key = keys.entries[i]; 356 StringConstant key = keys.entries[i];
357 if (key.value == const LiteralDartString(PROTO_PROPERTY)) continue; 357 if (key.value == const LiteralDartString(PROTO_PROPERTY)) continue;
358 358
359 if (valueIndex != 0) buffer.add(", "); 359 if (valueIndex != 0) buffer.add(", ");
360 360
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 // TODO(floitsch): create a better hash. 439 // TODO(floitsch): create a better hash.
440 int hash = 0; 440 int hash = 0;
441 for (Constant field in fields) { 441 for (Constant field in fields) {
442 hash ^= field.hashCode(); 442 hash ^= field.hashCode();
443 } 443 }
444 hash ^= type.element.hashCode(); 444 hash ^= type.element.hashCode();
445 _hashCode = hash; 445 _hashCode = hash;
446 } 446 }
447 bool isConstructedObject() => true; 447 bool isConstructedObject() => true;
448 448
449 void _writeJsCode(StringBuffer buffer, ConstantHandler handler) { 449 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
450 buffer.add("new "); 450 buffer.add("new ");
451 buffer.add(handler.getJsConstructor(type.element)); 451 buffer.add(handler.getJsConstructor(type.element));
452 buffer.add("("); 452 buffer.add("(");
453 for (int i = 0; i < fields.length; i++) { 453 for (int i = 0; i < fields.length; i++) {
454 if (i != 0) buffer.add(", "); 454 if (i != 0) buffer.add(", ");
455 Constant field = fields[i]; 455 Constant field = fields[i];
456 handler.writeConstant(buffer, field); 456 handler.writeConstant(buffer, field);
457 } 457 }
458 buffer.add(")"); 458 buffer.add(")");
459 } 459 }
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 626
627 compiledConstants.forEach((Constant key, ignored) => addConstant(key)); 627 compiledConstants.forEach((Constant key, ignored) => addConstant(key));
628 return result; 628 return result;
629 } 629 }
630 630
631 String getNameForConstant(Constant constant) { 631 String getNameForConstant(Constant constant) {
632 return compiledConstants[constant]; 632 return compiledConstants[constant];
633 } 633 }
634 634
635 /** This function writes the constant in non-canonicalized form. */ 635 /** This function writes the constant in non-canonicalized form. */
636 StringBuffer writeJsCode(StringBuffer buffer, Constant value) { 636 CodeBuffer writeJsCode(CodeBuffer buffer, Constant value) {
637 value._writeJsCode(buffer, this); 637 value._writeJsCode(buffer, this);
638 return buffer; 638 return buffer;
639 } 639 }
640 640
641 StringBuffer writeConstant(StringBuffer buffer, Constant value) { 641 CodeBuffer writeConstant(CodeBuffer buffer, Constant value) {
642 value._writeCanonicalizedJsCode(buffer, this); 642 value._writeCanonicalizedJsCode(buffer, this);
643 return buffer; 643 return buffer;
644 } 644 }
645 645
646 StringBuffer writeJsCodeForVariable(StringBuffer buffer, 646 CodeBuffer writeJsCodeForVariable(CodeBuffer buffer,
647 VariableElement element) { 647 VariableElement element) {
648 if (!initialVariableValues.containsKey(element)) { 648 if (!initialVariableValues.containsKey(element)) {
649 compiler.internalError("No initial value for given element", 649 compiler.internalError("No initial value for given element",
650 element: element); 650 element: element);
651 } 651 }
652 Constant constant = initialVariableValues[element]; 652 Constant constant = initialVariableValues[element];
653 writeConstant(buffer, constant); 653 writeConstant(buffer, constant);
654 return buffer; 654 return buffer;
655 } 655 }
656 656
657 /** 657 /**
658 * Write the contents of the quoted string to a [StringBuffer] in 658 * Write the contents of the quoted string to a [CodeBuffer] in
659 * a form that is valid as JavaScript string literal content. 659 * a form that is valid as JavaScript string literal content.
660 * The string is assumed quoted by single quote characters. 660 * The string is assumed quoted by single quote characters.
661 */ 661 */
662 static void writeEscapedString(DartString string, 662 static void writeEscapedString(DartString string,
663 StringBuffer buffer, 663 CodeBuffer buffer,
664 void cancel(String reason)) { 664 void cancel(String reason)) {
665 Iterator<int> iterator = string.iterator(); 665 Iterator<int> iterator = string.iterator();
666 while (iterator.hasNext()) { 666 while (iterator.hasNext()) {
667 int code = iterator.next(); 667 int code = iterator.next();
668 if (code === $SQ) { 668 if (code === $SQ) {
669 buffer.add(@"\'"); 669 buffer.add(@"\'");
670 } else if (code === $LF) { 670 } else if (code === $LF) {
671 buffer.add(@'\n'); 671 buffer.add(@'\n');
672 } else if (code === $CR) { 672 } else if (code === $CR) {
673 buffer.add(@'\r'); 673 buffer.add(@'\r');
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 Constant fieldValue = fieldValues[field]; 1166 Constant fieldValue = fieldValues[field];
1167 if (fieldValue === null) { 1167 if (fieldValue === null) {
1168 // Use the default value. 1168 // Use the default value.
1169 fieldValue = compiler.compileVariable(field); 1169 fieldValue = compiler.compileVariable(field);
1170 } 1170 }
1171 jsNewArguments.add(fieldValue); 1171 jsNewArguments.add(fieldValue);
1172 }); 1172 });
1173 return jsNewArguments; 1173 return jsNewArguments;
1174 } 1174 }
1175 } 1175 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698