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

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

Issue 10917097: Move constants into their own file. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase (on top of copy of compile_time_constants.dart) 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
« no previous file with comments | « no previous file | lib/compiler/implementation/constants.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 {
6 const Constant();
7
8 bool isNull() => false;
9 bool isBool() => false;
10 bool isTrue() => false;
11 bool isFalse() => false;
12 bool isInt() => false;
13 bool isDouble() => false;
14 bool isNum() => false;
15 bool isString() => false;
16 bool isList() => false;
17 bool isMap() => false;
18 bool isConstructedObject() => false;
19 bool isFunction() => false;
20 /** Returns true if the constant is null, a bool, a number or a string. */
21 bool isPrimitive() => false;
22 /** Returns true if the constant is a list, a map or a constructed object. */
23 bool isObject() => false;
24 bool isSentinel() => false;
25
26 bool isNaN() => false;
27 bool isMinusZero() => false;
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);
36 abstract List<Constant> getDependencies();
37 }
38
39 class SentinelConstant extends Constant {
40 const SentinelConstant();
41 static final SENTINEL = const SentinelConstant();
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>[];
53
54 // Just use a randome value.
55 int hashCode() => 926429784158;
56
57 bool isSentinel() => true;
58 }
59
60 class FunctionConstant extends Constant {
61 Element element;
62
63 FunctionConstant(this.element);
64
65 bool isFunction() => true;
66
67 bool operator ==(var other) {
68 if (other is !FunctionConstant) return false;
69 return other.element === element;
70 }
71
72 String toString() => element.toString();
73 List<Constant> getDependencies() => const <Constant>[];
74 DartString toDartString() {
75 return new DartString.literal(element.name.slowToString());
76 }
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
87 int hashCode() => (17 * element.hashCode()) & 0x7fffffff;
88 }
89
90 class PrimitiveConstant extends Constant {
91 abstract get value;
92 const PrimitiveConstant();
93 bool isPrimitive() => true;
94
95 bool operator ==(var other) {
96 if (other is !PrimitiveConstant) return false;
97 PrimitiveConstant otherPrimitive = other;
98 // We use == instead of === so that DartStrings compare correctly.
99 return value == otherPrimitive.value;
100 }
101
102 String toString() => value.toString();
103 // Primitive constants don't have dependencies.
104 List<Constant> getDependencies() => const <Constant>[];
105 abstract DartString toDartString();
106
107 void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
108 _writeJsCode(buffer, handler);
109 }
110 }
111
112 class NullConstant extends PrimitiveConstant {
113 /** The value a Dart null is compiled to in JavaScript. */
114 static const String JsNull = "null";
115
116 factory NullConstant() => const NullConstant._internal();
117 const NullConstant._internal();
118 bool isNull() => true;
119 get value => null;
120
121 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
122 buffer.add(JsNull);
123 }
124
125 // The magic constant has no meaning. It is just a random value.
126 int hashCode() => 785965825;
127 DartString toDartString() => const LiteralDartString("null");
128 }
129
130 class NumConstant extends PrimitiveConstant {
131 abstract num get value;
132 const NumConstant();
133 bool isNum() => true;
134 }
135
136 class IntConstant extends NumConstant {
137 final int value;
138 factory IntConstant(int value) {
139 switch (value) {
140 case 0: return const IntConstant._internal(0);
141 case 1: return const IntConstant._internal(1);
142 case 2: return const IntConstant._internal(2);
143 case 3: return const IntConstant._internal(3);
144 case 4: return const IntConstant._internal(4);
145 case 5: return const IntConstant._internal(5);
146 case 6: return const IntConstant._internal(6);
147 case 7: return const IntConstant._internal(7);
148 case 8: return const IntConstant._internal(8);
149 case 9: return const IntConstant._internal(9);
150 case 10: return const IntConstant._internal(10);
151 case -1: return const IntConstant._internal(-1);
152 case -2: return const IntConstant._internal(-2);
153 default: return new IntConstant._internal(value);
154 }
155 }
156 const IntConstant._internal(this.value);
157 bool isInt() => true;
158
159 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
160 buffer.add("$value");
161 }
162
163 // We have to override the equality operator so that ints and doubles are
164 // treated as separate constants.
165 // The is [:!IntConstant:] check at the beginning of the function makes sure
166 // that we compare only equal to integer constants.
167 bool operator ==(var other) {
168 if (other is !IntConstant) return false;
169 IntConstant otherInt = other;
170 return value == otherInt.value;
171 }
172
173 int hashCode() => value.hashCode();
174 DartString toDartString() => new DartString.literal(value.toString());
175 }
176
177 class DoubleConstant extends NumConstant {
178 final double value;
179 factory DoubleConstant(double value) {
180 if (value.isNaN()) {
181 return const DoubleConstant._internal(double.NAN);
182 } else if (value == double.INFINITY) {
183 return const DoubleConstant._internal(double.INFINITY);
184 } else if (value == -double.INFINITY) {
185 return const DoubleConstant._internal(-double.INFINITY);
186 } else if (value == 0.0 && !value.isNegative()) {
187 return const DoubleConstant._internal(0.0);
188 } else if (value == 1.0) {
189 return const DoubleConstant._internal(1.0);
190 } else {
191 return new DoubleConstant._internal(value);
192 }
193 }
194 const DoubleConstant._internal(this.value);
195 bool isDouble() => true;
196 bool isNaN() => value.isNaN();
197 // We need to check for the negative sign since -0.0 == 0.0.
198 bool isMinusZero() => value == 0.0 && value.isNegative();
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
212 bool operator ==(var other) {
213 if (other is !DoubleConstant) return false;
214 DoubleConstant otherDouble = other;
215 double otherValue = otherDouble.value;
216 if (value == 0.0 && otherValue == 0.0) {
217 return value.isNegative() == otherValue.isNegative();
218 } else if (value.isNaN()) {
219 return otherValue.isNaN();
220 } else {
221 return value == otherValue;
222 }
223 }
224
225 int hashCode() => value.hashCode();
226 DartString toDartString() => new DartString.literal(value.toString());
227 }
228
229 class BoolConstant extends PrimitiveConstant {
230 factory BoolConstant(value) {
231 return value ? new TrueConstant() : new FalseConstant();
232 }
233 const BoolConstant._internal();
234 bool isBool() => true;
235
236 abstract BoolConstant negate();
237 }
238
239 class TrueConstant extends BoolConstant {
240 final bool value = true;
241
242 factory TrueConstant() => const TrueConstant._internal();
243 const TrueConstant._internal() : super._internal();
244 bool isTrue() => true;
245
246 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
247 buffer.add("true");
248 }
249
250 FalseConstant negate() => new FalseConstant();
251
252 bool operator ==(var other) => this === other;
253 // The magic constant is just a random value. It does not have any
254 // significance.
255 int hashCode() => 499;
256 DartString toDartString() => const LiteralDartString("true");
257 }
258
259 class FalseConstant extends BoolConstant {
260 final bool value = false;
261
262 factory FalseConstant() => const FalseConstant._internal();
263 const FalseConstant._internal() : super._internal();
264 bool isFalse() => true;
265
266 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
267 buffer.add("false");
268 }
269
270 TrueConstant negate() => new TrueConstant();
271
272 bool operator ==(var other) => this === other;
273 // The magic constant is just a random value. It does not have any
274 // significance.
275 int hashCode() => 536555975;
276 DartString toDartString() => const LiteralDartString("false");
277 }
278
279 class StringConstant extends PrimitiveConstant {
280 final DartString value;
281 int _hashCode;
282 final Node node;
283
284 StringConstant(this.value, this.node) {
285 // TODO(floitsch): cache StringConstants.
286 // TODO(floitsch): compute hashcode without calling toString() on the
287 // DartString.
288 _hashCode = value.slowToString().hashCode();
289 }
290 bool isString() => true;
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
300 bool operator ==(var other) {
301 if (other is !StringConstant) return false;
302 StringConstant otherString = other;
303 return (_hashCode == otherString._hashCode) && (value == otherString.value);
304 }
305
306 int hashCode() => _hashCode;
307 DartString toDartString() => value;
308 int get length => value.length;
309 }
310
311 class ObjectConstant extends Constant {
312 final DartType type;
313
314 ObjectConstant(this.type);
315 bool isObject() => true;
316
317 // TODO(1603): The class should be marked as abstract, but the VM doesn't
318 // currently allow this.
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 }
325 }
326
327 class ListConstant extends ObjectConstant {
328 final List<Constant> entries;
329 int _hashCode;
330
331 ListConstant(DartType type, this.entries) : super(type) {
332 // TODO(floitsch): create a better hash.
333 int hash = 0;
334 for (Constant input in entries) hash ^= input.hashCode();
335 _hashCode = hash;
336 }
337 bool isList() => true;
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
352 bool operator ==(var other) {
353 if (other is !ListConstant) return false;
354 ListConstant otherList = other;
355 if (hashCode() != otherList.hashCode()) return false;
356 // TODO(floitsch): verify that the generic types are the same.
357 if (entries.length != otherList.entries.length) return false;
358 for (int i = 0; i < entries.length; i++) {
359 if (entries[i] != otherList.entries[i]) return false;
360 }
361 return true;
362 }
363
364 int hashCode() => _hashCode;
365
366 List<Constant> getDependencies() => entries;
367
368 int get length => entries.length;
369 }
370
371 class MapConstant extends ObjectConstant {
372 /**
373 * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript
374 * object. It would change the prototype chain.
375 */
376 static const String PROTO_PROPERTY = "__proto__";
377
378 /** The dart class implementing constant map literals. */
379 static const SourceString DART_CLASS = const SourceString("ConstantMap");
380 static const SourceString DART_PROTO_CLASS =
381 const SourceString("ConstantProtoMap");
382 static const SourceString LENGTH_NAME = const SourceString("length");
383 static const SourceString JS_OBJECT_NAME = const SourceString("_jsObject");
384 static const SourceString KEYS_NAME = const SourceString("_keys");
385 static const SourceString PROTO_VALUE = const SourceString("_protoValue");
386
387 final ListConstant keys;
388 final List<Constant> values;
389 final Constant protoValue;
390 int _hashCode;
391
392 MapConstant(DartType type, this.keys, this.values, this.protoValue)
393 : super(type) {
394 // TODO(floitsch): create a better hash.
395 int hash = 0;
396 for (Constant value in values) hash ^= value.hashCode();
397 _hashCode = hash;
398 }
399 bool isMap() => true;
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
461 bool operator ==(var other) {
462 if (other is !MapConstant) return false;
463 MapConstant otherMap = other;
464 if (hashCode() != otherMap.hashCode()) return false;
465 // TODO(floitsch): verify that the generic types are the same.
466 if (keys != otherMap.keys) return false;
467 for (int i = 0; i < values.length; i++) {
468 if (values[i] != otherMap.values[i]) return false;
469 }
470 return true;
471 }
472
473 int hashCode() => _hashCode;
474
475 List<Constant> getDependencies() {
476 List<Constant> result = <Constant>[keys];
477 result.addAll(values);
478 return result;
479 }
480
481 int get length => keys.length;
482 }
483
484 class ConstructedConstant extends ObjectConstant {
485 final List<Constant> fields;
486 int _hashCode;
487
488 ConstructedConstant(DartType type, this.fields) : super(type) {
489 assert(type !== null);
490 // TODO(floitsch): create a better hash.
491 int hash = 0;
492 for (Constant field in fields) {
493 hash ^= field.hashCode();
494 }
495 hash ^= type.element.hashCode();
496 _hashCode = hash;
497 }
498 bool isConstructedObject() => true;
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
512 bool operator ==(var otherVar) {
513 if (otherVar is !ConstructedConstant) return false;
514 ConstructedConstant other = otherVar;
515 if (hashCode() != other.hashCode()) return false;
516 // TODO(floitsch): verify that the (generic) types are the same.
517 if (type.element != other.type.element) return false;
518 if (fields.length != other.fields.length) return false;
519 for (int i = 0; i < fields.length; i++) {
520 if (fields[i] != other.fields[i]) return false;
521 }
522 return true;
523 }
524
525 int hashCode() => _hashCode;
526 List<Constant> getDependencies() => fields;
527 }
528
529 /** 5 /**
530 * The [ConstantHandler] keeps track of compile-time constants, 6 * The [ConstantHandler] keeps track of compile-time constants,
531 * initializations of global and static fields, and default values of 7 * initializations of global and static fields, and default values of
532 * optional parameters. 8 * optional parameters.
533 */ 9 */
534 class ConstantHandler extends CompilerTask { 10 class ConstantHandler extends CompilerTask {
535 final ConstantSystem constantSystem; 11 final ConstantSystem constantSystem;
536 12
537 /** 13 /**
538 * Contains the initial value of fields. Must contain all static and global 14 * Contains the initial value of fields. Must contain all static and global
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after
1339 Constant fieldValue = fieldValues[field]; 815 Constant fieldValue = fieldValues[field];
1340 if (fieldValue === null) { 816 if (fieldValue === null) {
1341 // Use the default value. 817 // Use the default value.
1342 fieldValue = compiler.compileConstant(field); 818 fieldValue = compiler.compileConstant(field);
1343 } 819 }
1344 jsNewArguments.add(fieldValue); 820 jsNewArguments.add(fieldValue);
1345 }); 821 });
1346 return jsNewArguments; 822 return jsNewArguments;
1347 } 823 }
1348 } 824 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/constants.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698