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

Side by Side Diff: pkg/compiler/lib/src/serialization/serialization.dart

Issue 1192103002: Support serialization of the compiler backbone. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments Created 5 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
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
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.
4
5 library dart2js.serialization;
6
7 import '../elements/elements.dart';
8 import '../constants/expressions.dart';
9 import '../dart_types.dart';
10
11 import 'element_serialization.dart';
12 import 'constant_serialization.dart';
13 import 'type_serialization.dart';
14 import 'keys.dart';
15 import 'json_serializer.dart';
16 import 'values.dart';
17
18 /// An object that supports the encoding an [ObjectValue] for serialization.
19 ///
20 /// The [ObjectEncoder] ensures that nominality and circularities of
21 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are
22 /// handled.
23 class ObjectEncoder extends AbstractEncoder<Key> {
24 /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map]
25 /// as its internal storage.
26 ObjectEncoder(Serializer serializer, Map<dynamic, Value> map)
27 : super(serializer, map);
28
29 String get _name => 'Object';
30 }
31
32 /// An object that supports the encoding a [MapValue] for serialization.
33 ///
34 /// The [MapEncoder] ensures that nominality and circularities of
35 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are
36 /// handled.
37 class MapEncoder extends AbstractEncoder<String> {
38 /// Creates an [MapEncoder] in the scope of [serializer] that uses [map]
39 /// as its internal storage.
40 MapEncoder(Serializer serializer, Map<String, Value> map)
41 : super(serializer, map);
42
43 String get _name => 'Map';
44 }
45
46 /// An object that supports the encoding a [ListValue] containing [ObjectValue]s
47 /// or [MapValue]s.
48 ///
49 /// The [ListEncoder] ensures that nominality and circularities of
50 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are
51 /// handled.
52 class ListEncoder {
53 final Serializer _serializer;
54 final List<Value> _list;
55
56 /// Creates an [ListEncoder] in the scope of [_serializer] that uses [_list]
57 /// as its internal storage.
58 ListEncoder(this._serializer, this._list);
59
60 /// Creates an [ObjectEncoder] and adds it to the encoded list.
61 ObjectEncoder createObject() {
62 Map<Key, Value> map = <Key, Value>{};
63 _list.add(new ObjectValue(map));
64 return new ObjectEncoder(_serializer, map);
65 }
66
67 /// Creates an [ObjectEncoder] and adds it to the encoded list.
68 MapEncoder createMap() {
69 Map<String, Value> map = {};
70 _list.add(new MapValue(map));
71 return new MapEncoder(_serializer, map);
72 }
73 }
74
75 /// Abstract base implementation for [ObjectEncoder] and [MapEncoder].
76 abstract class AbstractEncoder<K> {
77 final Serializer _serializer;
78 final Map<K, Value> _map;
79
80 AbstractEncoder(this._serializer, this._map);
81
82 /// The name of the encoder kind. Use for error reporting.
83 String get _name;
84
85 void _checkKey(K key) {
86 if (_map.containsKey(key)) {
87 throw new StateError("$_name value '$key' already in $_map.");
88 }
89 }
90
91 /// Maps the [key] entry to the enum [value] in the encoded object.
92 void setEnum(K key, var value) {
93 _checkKey(key);
94 _map[key] = new EnumValue(value);
95 }
96
97 /// Maps the [key] entry to the [element] in the encoded object.
98 void setElement(K key, Element element) {
99 _checkKey(key);
100 _map[key] = _serializer.createElementValue(element);
101 }
102
103 /// Maps the [key] entry to the [elements] in the encoded object.
104 ///
105 /// If [elements] is empty, it is skipped.
106 void setElements(K key, Iterable<Element> elements) {
107 _checkKey(key);
108 if (elements.isNotEmpty) {
109 _map[key] = new ListValue(
110 elements.map(_serializer.createElementValue).toList());
111 }
112 }
113
114 /// Maps the [key] entry to the [constant] in the encoded object.
115 void setConstant(K key, ConstantExpression constant) {
116 _checkKey(key);
117 _map[key] = _serializer.createConstantValue(constant);
118 }
119
120 /// Maps the [key] entry to the [constants] in the encoded object.
121 ///
122 /// If [constants] is empty, it is skipped.
123 void setConstants(K key, Iterable<ConstantExpression> constants) {
124 _checkKey(key);
125 if (constants.isNotEmpty) {
126 _map[key] = new ListValue(
127 constants.map(_serializer.createConstantValue).toList());
128 }
129 }
130
131 /// Maps the [key] entry to the [type] in the encoded object.
132 void setType(K key, DartType type) {
133 _checkKey(key);
134 _map[key] = _serializer.createTypeValue(type);
135 }
136
137 /// Maps the [key] entry to the [types] in the encoded object.
138 ///
139 /// If [types] is empty, it is skipped.
140 void setTypes(K key, Iterable<DartType> types) {
141 _checkKey(key);
142 if (types.isNotEmpty) {
143 _map[key] = new ListValue(types.map(_serializer.createTypeValue).toList()) ;
floitsch 2015/07/03 17:06:25 long line.
Johnni Winther 2015/07/06 08:33:22 Done.
144 }
145 }
146
147 /// Maps the [key] entry to the [uri] in the encoded object using [baseUri] to
148 /// relatives the encoding.
149 ///
150 /// For instance, a source file like `sdk/lib/core/string.dart` should be
151 /// serialized relative to the library root.
152 void setUri(K key, Uri baseUri, Uri uri) {
153 _checkKey(key);
154 _map[key] = new UriValue(baseUri, uri);
155 }
156
157 /// Maps the [key] entry to the string [value] in the encoded object.
158 void setString(K key, String value) {
159 _checkKey(key);
160 _map[key] = new StringValue(value);
161 }
162
163 /// Maps the [key] entry to the string [values] in the encoded object.
164 ///
165 /// If [values] is empty, it is skipped.
166 void setStrings(K key, Iterable<String> values) {
167 _checkKey(key);
168 if (values.isNotEmpty) {
169 _map[key] = new ListValue(values.map((v) => new StringValue(v)).toList());
170 }
171 }
172
173 /// Maps the [key] entry to the bool [value] in the encoded object.
174 void setBool(K key, bool value) {
175 _checkKey(key);
176 _map[key] = new BoolValue(value);
177 }
178
179 /// Maps the [key] entry to the int [value] in the encoded object.
180 void setInt(K key, int value) {
181 _checkKey(key);
182 _map[key] = new IntValue(value);
183 }
184
185 /// Maps the [key] entry to the int [values] in this serializer.
186 ///
187 /// If [values] is empty, it is skipped.
188 void setInts(K key, Iterable<int> values) {
189 _checkKey(key);
190 if (values.isNotEmpty) {
191 _map[key] = new ListValue(values.map((v) => new IntValue(v)).toList());
192 }
193 }
194
195 /// Maps the [key] entry to the double [value] in the encoded object.
196 void setDouble(K key, double value) {
197 _checkKey(key);
198 _map[key] = new DoubleValue(value);
199 }
200
201 /// Creates and returns an [ObjectEncoder] that is mapped to the [key]
202 /// entry in the encoded object.
203 ObjectEncoder createObject(K key) {
204 Map<Key, Value> map = <Key, Value>{};
205 _map[key] = new ObjectValue(map);
206 return new ObjectEncoder(_serializer, map);
207 }
208
209 /// Creates and returns a [MapEncoder] that is mapped to the [key] entry
210 /// in the encoded object.
211 MapEncoder createMap(K key) {
212 Map<String, Value> map = <String, Value>{};
213 _map[key] = new MapValue(map);
214 return new MapEncoder(_serializer, map);
215 }
216
217 /// Creates and returns a [ListEncoder] that is mapped to the [key] entry
218 /// in the encoded object.
219 ListEncoder createList(K key) {
220 List<Value> list = <Value>[];
221 _map[key] = new ListValue(list);
222 return new ListEncoder(_serializer, list);
223 }
224
225 String toString() => _map.toString();
226 }
227
228 /// [ObjectDecoder] reads serialized values from a [Map] encoded from an
229 /// [ObjectValue] where properties are stored using [Key] values as keys.
230 class ObjectDecoder extends AbstractDecoder<Key> {
231 /// Creates an [ObjectDecoder] that decodes [map] into deserialized values
232 /// using [deserializer] to create canonicalized values.
233 ObjectDecoder(Deserializer deserializer, Map map)
234 : super(deserializer, map);
235
236 @override
237 _getKeyValue(Key key) => _deserializer.decoder.getObjectPropertyValue(key);
238 }
239
240 /// [MapDecoder] reads serialized values from a [Map] encoded from an
241 /// [MapValue] where entries are stored using [String] values as keys.
242 class MapDecoder extends AbstractDecoder<String> {
243 /// Creates an [MapDecoder] that decodes [map] into deserialized values
244 /// using [deserializer] to create canonicalized values.
245 MapDecoder(Deserializer deserializer, Map<String, dynamic> map)
246 : super(deserializer, map);
247
248 @override
249 _getKeyValue(String key) => key;
250
251 /// Applies [f] to every key in the decoded [Map].
252 void forEachKey(f(String key)) {
253 _map.keys.forEach(f);
254 }
255 }
256
257 /// [ListDecoder] reads serialized map or object values from a [List].
258 class ListDecoder {
259 final Deserializer _deserializer;
260 final List _list;
261
262 /// Creates a [ListDecoder] that decodes [_list] using [_deserializer] to
263 /// create canonicalized values.
264 ListDecoder(this._deserializer, this._list);
265
266 /// The number of values in the decoded list.
267 int get length => _list.length;
268
269 /// Returns an [ObjectDecoder] for the [index]th object value in the decoded
270 /// list.
271 ObjectDecoder getObject(int index) {
272 return new ObjectDecoder(_deserializer, _list[index]);
273 }
274
275 /// Returns an [MapDecoder] for the [index]th map value in the decoded list.
276 MapDecoder getMap(int index) {
277 return new MapDecoder(_deserializer, _list[index]);
278 }
279 }
280
281 /// Abstract base implementation for [ObjectDecoder] and [MapDecoder].
282 abstract class AbstractDecoder<K> {
283 final Deserializer _deserializer;
284 final Map<K, dynamic> _map;
285
286 AbstractDecoder(this._deserializer, this._map) {
287 assert(_deserializer != null);
288 assert(_map != null);
289 }
290
291 /// Returns the value for [key] defined by the [SerializationDecoder] in used
292 /// [_deserializer].
293 _getKeyValue(K key);
294
295 /// Returns `true` if [key] has an associated value in the decoded object.
296 bool containsKey(K key) => _map.containsKey(_getKeyValue(key));
297
298 /// Returns the enum value from the [enumValues] associated with [key] in the
299 /// decoded object.
300 ///
301 /// If no value is associated with [key], then if [isOptional] is `true`,
302 /// [defaultValue] is returned, otherwise an exception is thrown.
303 getEnum(K key, List enumValues, {bool isOptional: false, defaultValue}) {
304 int value = _map[_getKeyValue(key)];
305 if (value == null) {
306 if (isOptional || defaultValue != null) {
307 return defaultValue;
308 }
309 throw new StateError("enum value '$key' not found in $_map.");
310 }
311 return enumValues[value];
312 }
313
314 /// Returns the [Element] value associated with [key] in the decoded object.
315 ///
316 /// If no value is associated with [key], then if [isOptional] is `true`,
317 /// `null` is returned, otherwise an exception is thrown.
318 Element getElement(K key, {bool isOptional: false}) {
319 int id = _map[_getKeyValue(key)];
320 if (id == null) {
321 if (isOptional) {
322 return null;
323 }
324 throw new StateError("Element value '$key' not found in $_map.");
325 }
326 return _deserializer.deserializeElement(id);
327 }
328
329 /// Returns the list of [Element] values associated with [key] in the decoded
330 /// object.
331 ///
332 /// If no value is associated with [key], then if [isOptional] is `true`,
333 /// and empty [List] is returned, otherwise an exception is thrown.
334 List<Element> getElements(K key, {bool isOptional: false}) {
335 List list = _map[_getKeyValue(key)];
336 if (list == null) {
337 if (isOptional) {
338 return const [];
339 }
340 throw new StateError("Elements value '$key' not found in $_map.");
341 }
342 return list.map(_deserializer.deserializeElement).toList();
343 }
344
345 /// Returns the [ConstantExpression] value associated with [key] in the
346 /// decoded object.
347 ///
348 /// If no value is associated with [key], then if [isOptional] is `true`,
349 /// `null` is returned, otherwise an exception is thrown.
350 ConstantExpression getConstant(K key, {bool isOptional: false}) {
351 int id = _map[_getKeyValue(key)];
352 if (id == null) {
353 if (isOptional) {
354 return null;
355 }
356 throw new StateError("Constant value '$key' not found in $_map.");
357 }
358 return _deserializer.deserializeConstant(id);
359 }
360
361 /// Returns the list of [ConstantExpression] values associated with [key] in
362 /// the decoded object.
363 ///
364 /// If no value is associated with [key], then if [isOptional] is `true`,
365 /// and empty [List] is returned, otherwise an exception is thrown.
366 List<ConstantExpression> getConstants(K key, {bool isOptional: false}) {
367 List list = _map[_getKeyValue(key)];
368 if (list == null) {
369 if (isOptional) {
370 return const [];
371 }
372 throw new StateError("Constants value '$key' not found in $_map.");
373 }
374 return list.map(_deserializer.deserializeConstant).toList();
375 }
376
377 /// Returns the [DartType] value associated with [key] in the decoded object.
378 ///
379 /// If no value is associated with [key], then if [isOptional] is `true`,
380 /// `null` is returned, otherwise an exception is thrown.
381 DartType getType(K key, {bool isOptional: false}) {
382 int id = _map[_getKeyValue(key)];
383 if (id == null) {
384 if (isOptional) {
385 return null;
386 }
387 throw new StateError("Type value '$key' not found in $_map.");
388 }
389 return _deserializer.deserializeType(id);
390 }
391
392 /// Returns the list of [DartType] values associated with [key] in the decoded
393 /// object.
394 ///
395 /// If no value is associated with [key], then if [isOptional] is `true`,
396 /// and empty [List] is returned, otherwise an exception is thrown.
397 List<DartType> getTypes(K key, {bool isOptional: false}) {
398 List list = _map[_getKeyValue(key)];
399 if (list == null) {
400 if (isOptional) {
401 return const [];
402 }
403 throw new StateError("Types value '$key' not found in $_map.");
404 }
405 return list.map(_deserializer.deserializeType).toList();
406 }
407
408 /// Returns the [Uri] value associated with [key] in the decoded object.
409 ///
410 /// If no value is associated with [key], then if [isOptional] is `true`,
411 /// [defaultValue] is returned, otherwise an exception is thrown.
412 Uri getUri(K key, {bool isOptional: false, Uri defaultValue}) {
413 String value = _map[_getKeyValue(key)];
414 if (value == null) {
415 if (isOptional || defaultValue != null) {
416 return defaultValue;
417 }
418 throw new StateError("Uri value '$key' not found in $_map.");
419 }
420 return Uri.parse(value);
421 }
422
423 /// Returns the [String] value associated with [key] in the decoded object.
424 ///
425 /// If no value is associated with [key], then if [isOptional] is `true`,
426 /// [defaultValue] is returned, otherwise an exception is thrown.
427 String getString(K key, {bool isOptional: false, String defaultValue}) {
428 String value = _map[_getKeyValue(key)];
429 if (value == null) {
430 if (isOptional || defaultValue != null) {
431 return defaultValue;
432 }
433 throw new StateError("String value '$key' not found in $_map.");
434 }
435 return value;
436 }
437
438 /// Returns the list of [String] values associated with [key] in the decoded
439 /// object.
440 ///
441 /// If no value is associated with [key], then if [isOptional] is `true`,
442 /// and empty [List] is returned, otherwise an exception is thrown.
443 List<String> getStrings(K key, {bool isOptional: false}) {
444 List list = _map[_getKeyValue(key)];
445 if (list == null) {
446 if (isOptional) {
447 return const [];
448 }
449 throw new StateError("Strings value '$key' not found in $_map.");
450 }
451 return list;
452 }
453
454 /// Returns the [bool] value associated with [key] in the decoded object.
455 ///
456 /// If no value is associated with [key], then if [isOptional] is `true`,
457 /// [defaultValue] is returned, otherwise an exception is thrown.
458 bool getBool(K key, {bool isOptional: false, bool defaultValue}) {
459 bool value = _map[_getKeyValue(key)];
460 if (value == null) {
461 if (isOptional || defaultValue != null) {
462 return defaultValue;
463 }
464 throw new StateError("bool value '$key' not found in $_map.");
465 }
466 return value;
467 }
468
469 /// Returns the [int] value associated with [key] in the decoded object.
470 ///
471 /// If no value is associated with [key], then if [isOptional] is `true`,
472 /// [defaultValue] is returned, otherwise an exception is thrown.
473 int getInt(K key, {bool isOptional: false, int defaultValue}) {
474 int value = _map[_getKeyValue(key)];
475 if (value == null) {
476 if (isOptional || defaultValue != null) {
477 return defaultValue;
478 }
479 throw new StateError("int value '$key' not found in $_map.");
480 }
481 return value;
482 }
483
484 /// Returns the list of [int] values associated with [key] in the decoded
485 /// object.
486 ///
487 /// If no value is associated with [key], then if [isOptional] is `true`,
488 /// and empty [List] is returned, otherwise an exception is thrown.
489 List<int> getInts(K key, {bool isOptional: false}) {
490 List list = _map[_getKeyValue(key)];
491 if (list == null) {
492 if (isOptional) {
493 return const [];
494 }
495 throw new StateError("Ints value '$key' not found in $_map.");
496 }
497 return list;
498 }
499
500 /// Returns the [double] value associated with [key] in the decoded object.
501 ///
502 /// If no value is associated with [key], then if [isOptional] is `true`,
503 /// [defaultValue] is returned, otherwise an exception is thrown.
504 double getDouble(K key, {bool isOptional: false, double defaultValue}) {
505 double value = _map[_getKeyValue(key)];
506 if (value == null) {
507 if (isOptional || defaultValue != null) {
508 return defaultValue;
509 }
510 throw new StateError("double value '$key' not found in $_map.");
511 }
512 return value;
513 }
514
515 /// Returns an [ObjectDecoder] for the map value associated with [key] in the
516 /// decoded object.
517 ///
518 /// If no value is associated with [key], then if [isOptional] is `true`,
519 /// `null` is returned, otherwise an exception is thrown.
520 ObjectDecoder getObject(K key, {bool isOptional: false}) {
521 Map map = _map[_getKeyValue(key)];
522 if (map == null) {
523 if (isOptional) {
524 return null;
525 }
526 throw new StateError("Object value '$key' not found in $_map.");
527 }
528 return new ObjectDecoder(_deserializer, map);
529 }
530
531 /// Returns an [MapDecoder] for the map value associated with [key] in the
532 /// decoded object.
533 ///
534 /// If no value is associated with [key], then if [isOptional] is `true`,
535 /// `null` is returned, otherwise an exception is thrown.
536 MapDecoder getMap(K key, {bool isOptional: false}) {
537 Map map = _map[_getKeyValue(key)];
538 if (map == null) {
539 if (isOptional) {
540 return null;
541 }
542 throw new StateError("Map value '$key' not found in $_map.");
543 }
544 return new MapDecoder(_deserializer, map);
545 }
546
547 /// Returns an [ListDecoder] for the list value associated with [key] in the
548 /// decoded object.
549 ///
550 /// If no value is associated with [key], then if [isOptional] is `true`,
551 /// `null` is returned, otherwise an exception is thrown.
552 ListDecoder getList(K key, {bool isOptional: false}) {
553 List list = _map[_getKeyValue(key)];
554 if (list == null) {
555 if (isOptional) {
556 return null;
557 }
558 throw new StateError("List value '$key' not found in $_map.");
559 }
560 return new ListDecoder(_deserializer, list);
561 }
562 }
563
564 /// A nominal object containing its serialized value.
565 class DataObject {
566 /// The id for the object.
567 final Value id;
568
569 /// The serialized value of the object.
570 final ObjectValue objectValue;
571
572 DataObject(Value id, EnumValue kind)
573 : this.id = id,
574 this.objectValue =
575 new ObjectValue(<Key, Value>{Key.ID: id, Key.KIND: kind});
576
577 Map<Key, Value> get map => objectValue.map;
578 }
579
580 /// Serializer for the transitive closure of a collection of libraries.
581 ///
582 /// The serializer creates an [ObjectValue] model of the [Element], [DartType]
583 /// and [ConstantExpression] values in the transitive closure of the serialized
584 /// libraries.
585 ///
586 /// The model layout of the produced [objectValue] is:
587 ///
588 /// { // Header object
589 /// Key.ELEMENTS: [
590 /// {...}, // [ObjectValue] of the 0th [Element].
591 /// ...
592 /// {...}, // [ObjectValue] of the n-th [Element].
593 /// ],
594 /// Key.TYPES: [
595 /// {...}, // [ObjectValue] of the 0th [DartType].
596 /// ...
597 /// {...}, // [ObjectValue] of the n-th [DartType].
598 /// ],
599 /// Key.CONSTANTS: [
600 /// {...}, // [ObjectValue] of the 0th [ConstantExpression].
601 /// ...
602 /// {...}, // [ObjectValue] of the n-th [ConstantExpression].
603 /// ],
604 /// }
605 ///
606 // TODO(johnniwinther): Support per-library serialization and dependencies
607 // between serialized subcomponent.
608 class Serializer {
609 final SerializationEncoder _encoder;
610
611 Map<Element, DataObject> _elementMap = <Element, DataObject>{};
612 Map<ConstantExpression, DataObject> _constantMap =
613 <ConstantExpression, DataObject>{};
614 Map<DartType, DataObject> _typeMap = <DartType, DataObject>{};
615 List _pendingList = [];
616
617 Serializer(this._encoder);
618
619 /// Add the transitive closure of [library] to this serializer.
620 void serialize(LibraryElement library) {
621 // Create a [DataObject] for [library]. If not already created, this will
622 // put the serialization of [library] in the work queue.
623 _getElementDataObject(library);
floitsch 2015/07/03 17:06:25 Mention that we don't care for the value, but do t
Johnni Winther 2015/07/06 08:33:22 Done.
624 _emptyWorklist();
625 }
626
627 void _emptyWorklist() {
628 while (_pendingList.isNotEmpty) {
629 _pendingList.removeLast()();
630 }
631 }
632
633 /// Returns the [DataObject] for [element].
634 ///
635 /// If [constant] has no [DataObject], a new [DataObject] is created and
636 /// encoding the [ObjectValue] for [constant] is put into the work queue of
637 /// this serializer.
638 DataObject _getElementDataObject(Element element) {
639 if (element == null) {
640 throw new ArgumentError('Serializer._getElementDataObject(null)');
641 }
642 return _elementMap.putIfAbsent(element, () {
643 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) {
floitsch 2015/07/03 17:06:25 Add comment: Sequentially run through all seriali
Johnni Winther 2015/07/06 08:33:22 Done.
644 SerializedElementKind kind = serializer.getSerializedKind(element);
645 if (kind != null) {
646 DataObject dataObject = new DataObject(
647 new IntValue(_elementMap.length), new EnumValue(kind));
648 // Delay the serialization of the element itself to avoid loops, and
649 // to keep the call stack small.
650 _pendingList.add(() {
651 serializer.serialize(
652 element, new ObjectEncoder(this, dataObject.map), kind);
653 });
654 return dataObject;
655 }
656 }
657 throw new UnsupportedError(
658 'Unsupported element: $element (${element.kind})');
659 });
660 }
661
662 /// Creates the [ElementValue] for [element].
663 ///
664 /// If [element] has not already been serialized, it is added to the work
665 /// queue of this serializer.
666 ElementValue createElementValue(Element element) {
667 return new ElementValue(element, _getElementDataObject(element).id);
668 }
669
670 /// Returns the [DataObject] for [constant].
671 ///
672 /// If [constant] has no [DataObject], a new [DataObject] is created and
673 /// encoding the [ObjectValue] for [constant] is put into the work queue of
674 /// this serializer.
675 DataObject _getConstantDataObject(ConstantExpression constant) {
676 return _constantMap.putIfAbsent(constant, () {
677 DataObject dataObject = new DataObject(
678 new IntValue(_constantMap.length), new EnumValue(constant.kind));
679 // Delay the serialization of the constant itself to avoid loops, and to
680 // keep the call stack small.
681 _pendingList.add(() => _encodeConstant(constant, dataObject));
682 return dataObject;
683 });
684 }
685
686 /// Encodes [constant] into the [ObjectValue] of [dataObject].
687 void _encodeConstant(ConstantExpression constant, DataObject dataObject) {
688 const ConstantSerializer().visit(constant,
689 new ObjectEncoder(this, dataObject.map));
690 }
691
692 /// Creates the [ConstantValue] for [constant].
693 ///
694 /// If [constant] has not already been serialized, it is added to the work
695 /// queue of this serializer.
696 ConstantValue createConstantValue(ConstantExpression constant) {
697 return new ConstantValue(constant, _getConstantDataObject(constant).id);
698 }
699
700 /// Returns the [DataObject] for [type].
701 ///
702 /// If [type] has no [DataObject], a new [DataObject] is created and
703 /// encoding the [ObjectValue] for [type] is put into the work queue of this
704 /// serializer.
705 DataObject _getTypeDataObject(DartType type) {
706 return _typeMap.putIfAbsent(type, () {
707 DataObject dataObject = new DataObject(
708 new IntValue(_typeMap.length), new EnumValue(type.kind));
709 // Delay the serialization of the type itself to avoid loops, and to keep
710 // the call stack small.
711 _pendingList.add(() => _encodeType(type, dataObject));
712 return dataObject;
713 });
714 }
715
716 /// Encodes [type] into the [ObjectValue] of [dataObject].
717 void _encodeType(DartType type, DataObject dataObject) {
718 const TypeSerializer().visit(type, new ObjectEncoder(this, dataObject.map));
719 }
720
721 /// Creates the [TypeValue] for [type].
722 ///
723 /// If [type] has not already been serialized, it is added to the work
724 /// queue of this serializer.
725 TypeValue createTypeValue(DartType type) {
726 return new TypeValue(type, _getTypeDataObject(type).id);
727 }
728
729 ObjectValue get objectValue {
730 Map<Key, Value> map = <Key, Value>{};
731 map[Key.ELEMENTS] =
732 new ListValue(_elementMap.values.map((l) => l.objectValue).toList());
733 if (_typeMap.isNotEmpty) {
734 map[Key.TYPES] =
735 new ListValue(_typeMap.values.map((l) => l.objectValue).toList());
736 }
737 if (_constantMap.isNotEmpty) {
738 map[Key.CONSTANTS] =
739 new ListValue(_constantMap.values.map((l) => l.objectValue).toList());
740 }
741 return new ObjectValue(map);
742 }
743
744 String toText() {
745 return _encoder.encode(objectValue);
746 }
747
748 String prettyPrint() {
749 PrettyPrintEncoder encoder = new PrettyPrintEncoder();
750 return encoder.toText(objectValue);
751 }
752 }
753
754 /// Deserializer for a closed collection of libraries.
755 // TODO(johnniwinther): Support per-library deserialization and dependencies
756 // between deserialized subcomponent.
757 class Deserializer {
758 final SerializationDecoder decoder;
759 ObjectDecoder _headerObject;
760 ListDecoder _elementList;
761 ListDecoder _typeList;
762 ListDecoder _constantList;
763 Map<int, Element> _elementMap = {};
764 Map<int, DartType> _typeMap = {};
765 Map<int, ConstantExpression> _constantMap = {};
766
767 Deserializer.fromText(String text, this.decoder) {
768 _headerObject = new ObjectDecoder(this, decoder.decode(text));
769 }
770
771 /// Returns the [ListDecoder] for the [Element]s in this deserializer.
772 ListDecoder get elements {
773 if (_elementList == null) {
774 _elementList = _headerObject.getList(Key.ELEMENTS);
775 }
776 return _elementList;
777 }
778
779 /// Returns the [ListDecoder] for the [DartType]s in this deserializer.
780 ListDecoder get types {
781 if (_typeList == null) {
782 _typeList = _headerObject.getList(Key.TYPES);
783 }
784 return _typeList;
785 }
786
787 /// Returns the [ListDecoder] for the [ConstantExpression]s in this
788 /// deserializer.
789 ListDecoder get constants {
790 if (_constantList == null) {
791 _constantList = _headerObject.getList(Key.CONSTANTS);
792 }
793 return _constantList;
794 }
795
796 /// Returns the [LibraryElement] for [uri] if part of the deserializer.
797 LibraryElement lookupLibrary(Uri uri) {
798 // TODO(johnniwinther): Libraries should be stored explicitly in the header.
799 ListDecoder list = elements;
800 for (int i = 0; i < list.length; i++) {
801 ObjectDecoder object = list.getObject(i);
802 SerializedElementKind kind =
803 object.getEnum(Key.KIND, SerializedElementKind.values);
804 if (kind == SerializedElementKind.LIBRARY) {
805 Uri libraryUri = object.getUri(Key.CANONICAL_URI);
806 if (libraryUri == uri) {
807 return deserializeElement(object.getInt(Key.ID));
808 }
809 }
810 }
811 return null;
812 }
813
814 /// Returns the deserialized [Element] for [id].
815 Element deserializeElement(int id) {
816 if (id == null) throw new ArgumentError('Deserializer.getElement(null)');
817 return _elementMap.putIfAbsent(id, () {
818 return ElementDeserializer.deserialize(elements.getObject(id));
819 });
820 }
821
822 /// Returns the deserialized [DartType] for [id].
823 DartType deserializeType(int id) {
824 if (id == null) throw new ArgumentError('Deserializer.getType(null)');
825 return _typeMap.putIfAbsent(id, () {
826 return TypeDeserializer.deserialize(types.getObject(id));
827 });
828 }
829
830 /// Returns the deserialized [ConstantExpression] for [id].
831 ConstantExpression deserializeConstant(int id) {
832 if (id == null) throw new ArgumentError('Deserializer.getConstant(null)');
833 return _constantMap.putIfAbsent(id, () {
834 return ConstantDeserializer.deserialize(constants.getObject(id));
835 });
836 }
837 }
838
839 /// Strategy used by [Serializer] to define the memory and output encoding.
840 abstract class SerializationEncoder {
841 /// Encode [objectValue] into text.
842 String encode(ObjectValue objectValue);
843 }
844
845 /// Strategy used by [Deserializer] for decoding and reading data from a
846 /// serialized output.
847 abstract class SerializationDecoder {
848 /// Decode [text] into [Map] containing the data corresponding to an encoding
849 /// of the serializer header object.
850 Map decode(String text);
851
852 /// Returns the value used to store [key] as a property in the encoding an
853 /// [ObjectValue].
854 ///
855 /// Different encodings have different restrictions and capabilities as how
856 /// to store a [Key] value. For instance: A JSON encoding needs to convert
857 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can
858 /// choose to store a [Key] as an [int] or as the [Key] itself.
859 getObjectPropertyValue(Key key);
860 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698