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

Side by Side Diff: pkg/compiler/lib/src/serialization/element_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.elements;
6
7 import '../constants/expressions.dart';
8 import '../dart_types.dart';
9 import '../dart2jslib.dart' show SourceSpan;
10 import '../elements/elements.dart';
11 import '../tree/tree.dart';
12 import 'constant_serialization.dart';
13 import 'keys.dart';
14 import 'modelz.dart';
15 import 'serialization.dart';
16
17 /// Enum kinds used for encoding [Element]s.
18 enum SerializedElementKind {
19 LIBRARY,
20 COMPILATION_UNIT,
21 CLASS,
22 GENERATIVE_CONSTRUCTOR,
23 FACTORY_CONSTRUCTOR,
24 TOPLEVEL_FIELD,
25 STATIC_FIELD,
26 INSTANCE_FIELD,
27 TOPLEVEL_FUNCTION,
28 TOPLEVEL_GETTER,
29 TOPLEVEL_SETTER,
30 STATIC_FUNCTION,
31 STATIC_GETTER,
32 STATIC_SETTER,
33 INSTANCE_FUNCTION,
34 INSTANCE_GETTER,
35 INSTANCE_SETTER,
36 TYPEDEF,
37 TYPEVARIABLE,
38 PARAMETER,
39 INITIALIZING_FORMAL,
40 }
41
42 /// Set of serializers used to serialize different kinds of elements by
43 /// encoding into them into [ObjectEncoder]s.
44 ///
45 /// This class is called from the [Serializer] when an [Element] needs
46 /// serialization. The [ObjectEncoder] ensures that any [Element], [DartType],
47 /// and [ConstantExpression] that the serialized [Element] depends upon are also
48 /// serialized.
49 const List<ElementSerializer> ELEMENT_SERIALIZERS = const [
50 const LibrarySerializer(),
51 const CompilationUnitSerializer(),
52 const ClassSerializer(),
53 const ConstructorSerializer(),
54 const FieldSerializer(),
55 const FunctionSerializer(),
56 const TypedefSerializer(),
57 const TypeVariableSerializer(),
58 const ParameterSerializer(),
59 ];
60
61 /// Interface for a function that can serialize a set of element kinds.
62 abstract class ElementSerializer {
63 /// Returns the [SerializedElementKind] for [element] if this serializer
64 /// supports serialization of [element] or `null` otherwise.
65 SerializedElementKind getSerializedKind(Element element);
66
67 /// Serializes [element] into the [encoder] using the [kind] computed
68 /// by [getSerializedKind].
69 void serialize(Element element,
70 ObjectEncoder encoder,
71 SerializedElementKind kind);
72 }
73
74 class SerializerUtil {
75 /// Serialize the declared members of [element] into [encoder].
76 static void serializeMembers(ScopeContainerElement element,
77 ObjectEncoder encoder) {
78 MapEncoder mapEncoder = encoder.createMap(Key.MEMBERS);
79 element.forEachLocalMember((Element member) {
80 String name = member.name;
81 if (member.isSetter) {
82 name = '$name,=';
83 }
84 mapEncoder.setElement(name, member);
85 });
86 }
87
88 /// Serialize the source position of [element] into [encoder].
89 static void serializePosition(Element element, ObjectEncoder encoder) {
90 if (element.sourcePosition != null) {
91 SourceSpan position = element.sourcePosition;
92 encoder.setInt(Key.OFFSET, position.begin);
93 if (position.uri != element.compilationUnit.script.resourceUri) {
94 // TODO(johnniwinther): What is the base URI in the case?
95 encoder.setUri(Key.URI, element.library.canonicalUri, position.uri);
96 }
97 int length = position.end - position.begin;
98 if (element.name.length != length) {
99 encoder.setInt(Key.LENGTH, length);
100 }
101 }
102 }
103
104 /// Serialize the parameters of [element] into [encoder].
105 static void serializeParameters(FunctionElement element,
106 ObjectEncoder encoder) {
107 FunctionType type = element.type;
108 encoder.setType(Key.RETURN_TYPE, type.returnType);
109 encoder.setElements(Key.PARAMETERS, element.parameters);
110 }
111
112 /// Returns a function that addeds the underlying declared elements for a
floitsch 2015/07/03 17:06:25 adds
Johnni Winther 2015/07/06 08:33:22 Done.
113 /// particular element into [list].
114 ///
115 /// For instance, for an [AbstractFieldElement] the getter and setter elements
116 /// are added, if available.
117 static flattenElements(List<Element> list) {
118 return (Element element) {
119 // TODO(johnniwinther): Handle ambiguous elements.
120 if (element.isAmbiguous) return;
121 if (element.isAbstractField) {
122 AbstractFieldElement abstractField = element;
123 if (abstractField.getter != null) {
124 list.add(abstractField.getter);
125 }
126 if (abstractField.setter != null) {
127 list.add(abstractField.setter);
128 }
129 } else {
130 list.add(element);
131 }
132 };
133 }
134 }
135
136 class LibrarySerializer implements ElementSerializer {
137 const LibrarySerializer();
138
139 SerializedElementKind getSerializedKind(Element element) {
140 if (element.isLibrary) {
141 return SerializedElementKind.LIBRARY;
142 }
143 return null;
144 }
145
146 void serialize(LibraryElement element,
147 ObjectEncoder encoder,
148 SerializedElementKind kind) {
149 encoder.setUri(
150 Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri);
151 encoder.setString(Key.LIBRARY_NAME, element.getLibraryName());
152 SerializerUtil.serializeMembers(element, encoder);
153 encoder.setElement(Key.COMPILATION_UNIT, element.entryCompilationUnit);
154 encoder.setElements(
155 Key.COMPILATION_UNITS, element.compilationUnits.toList());
156 ListEncoder tags = encoder.createList(Key.TAGS);
157
158 void addTags(LibraryElement library) {
159 for (LibraryTag tag in library.tags) {
160 if (tag is Import) {
161 ObjectEncoder importTag = tags.createObject();
162 importTag.setString(Key.KIND, 'import');
163 importTag.setElement(Key.LIBRARY, library.getLibraryFromTag(tag));
164 } else if (tag is Export) {
165 ObjectEncoder exportTag = tags.createObject();
166 exportTag.setString(Key.KIND, 'export');
167 exportTag.setElement(Key.LIBRARY, library.getLibraryFromTag(tag));
168 }
169 }
170 }
171
172 addTags(element);
floitsch 2015/07/03 17:06:25 Since 'addTags' is not reused, why not just inline
Johnni Winther 2015/07/06 08:33:22 Done.
173
174 List<Element> imports = <Element>[];
175 element.forEachImport(SerializerUtil.flattenElements(imports));
176 encoder.setElements(Key.IMPORTS, imports);
177
178 List<Element> exports = <Element>[];
179 element.forEachExport(SerializerUtil.flattenElements(exports));
180 encoder.setElements(Key.EXPORTS, exports);
181 }
182 }
183
184 class CompilationUnitSerializer implements ElementSerializer {
185 const CompilationUnitSerializer();
186
187 SerializedElementKind getSerializedKind(Element element) {
188 if (element.isCompilationUnit) {
189 return SerializedElementKind.COMPILATION_UNIT;
190 }
191 return null;
192 }
193
194 void serialize(CompilationUnitElement element,
195 ObjectEncoder encoder,
196 SerializedElementKind kind) {
197 encoder.setElement(Key.LIBRARY, element.library);
198 encoder.setUri(
199 Key.URI, element.library.canonicalUri, element.script.resourceUri);
200 List<Element> elements = <Element>[];
201 element.forEachLocalMember((e) => elements.add(e));
202 encoder.setElements(Key.ELEMENTS, elements);
203 }
204 }
205
206 class ClassSerializer implements ElementSerializer {
207 const ClassSerializer();
208
209 SerializedElementKind getSerializedKind(Element element) {
210 if (element.isClass) {
211 return SerializedElementKind.CLASS;
212 }
213 return null;
214 }
215
216 void serialize(ClassElement element,
217 ObjectEncoder encoder,
218 SerializedElementKind kind) {
219 encoder.setElement(Key.LIBRARY, element.library);
220 encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
221 encoder.setString(Key.NAME, element.name);
222 SerializerUtil.serializePosition(element, encoder);
223 encoder.setTypes(Key.TYPE_VARIABLES, element.typeVariables);
224 encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
225 if (element.supertype != null) {
226 encoder.setType(Key.SUPERTYPE, element.supertype);
227 }
228 // TODO(johnniwinther): Make [OrderedTypeSet] easier to (de)serialize.
229 ObjectEncoder supertypes = encoder.createObject(Key.SUPERTYPES);
230 supertypes.setTypes(Key.TYPES,
231 element.allSupertypesAndSelf.types.toList());
232 supertypes.setTypes(Key.SUPERTYPES,
233 element.allSupertypesAndSelf.supertypes.toList());
234 supertypes.setInts(Key.OFFSETS, element.allSupertypesAndSelf.levelOffsets);
235 encoder.setTypes(Key.INTERFACES, element.interfaces.toList());
236 SerializerUtil.serializeMembers(element, encoder);
237 }
238 }
239
240 class ConstructorSerializer implements ElementSerializer {
241 const ConstructorSerializer();
242
243 SerializedElementKind getSerializedKind(Element element) {
244 if (element.isGenerativeConstructor) {
245 return SerializedElementKind.GENERATIVE_CONSTRUCTOR;
246 } else if (element.isFactoryConstructor) {
247 return SerializedElementKind.FACTORY_CONSTRUCTOR;
248 }
249 return null;
250 }
251
252 void serialize(ConstructorElement element,
253 ObjectEncoder encoder,
254 SerializedElementKind kind) {
255 encoder.setElement(Key.CLASS, element.enclosingClass);
256 encoder.setType(Key.TYPE, element.type);
257 encoder.setString(Key.NAME, element.name);
258 SerializerUtil.serializePosition(element, encoder);
259 SerializerUtil.serializeParameters(element, encoder);
260 encoder.setBool(Key.IS_CONST, element.isConst);
261 if (element.isConst && !element.isFromEnvironmentConstructor) {
262 ConstantConstructor constantConstructor = element.constantConstructor;
263 ObjectEncoder constantEncoder =
264 encoder.createObject(Key.CONSTRUCTOR);
265 const ConstantConstructorSerializer().visit(
266 constantConstructor, constantEncoder);
267 }
268 }
269 }
270
271 class FieldSerializer implements ElementSerializer {
272 const FieldSerializer();
273
274 SerializedElementKind getSerializedKind(Element element) {
275 if (element.isField) {
276 if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_FIELD;
277 if (element.isStatic) return SerializedElementKind.STATIC_FIELD;
278 if (element.isInstanceMember) return SerializedElementKind.INSTANCE_FIELD;
279 }
280 return null;
281 }
282
283 void serialize(FieldElement element,
284 ObjectEncoder encoder,
285 SerializedElementKind kind) {
286 encoder.setString(Key.NAME, element.name);
287 SerializerUtil.serializePosition(element, encoder);
288 encoder.setType(Key.TYPE, element.type);
289 encoder.setBool(Key.IS_FINAL, element.isFinal);
290 encoder.setBool(Key.IS_CONST, element.isConst);
291 if (element.isConst) {
292 ConstantExpression constant = element.constant;
293 encoder.setConstant(Key.CONSTANT, constant);
294 }
295 if (kind != SerializedElementKind.TOPLEVEL_FIELD) {
296 encoder.setElement(Key.CLASS, element.enclosingClass);
297 } else {
298 encoder.setElement(Key.LIBRARY, element.library);
299 encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
300 }
301 }
302 }
303
304 class FunctionSerializer implements ElementSerializer {
305 const FunctionSerializer();
306
307 SerializedElementKind getSerializedKind(Element element) {
308 if (element.isFunction) {
309 if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_FUNCTION;
310 if (element.isStatic) return SerializedElementKind.STATIC_FUNCTION;
311 if (element.isInstanceMember) {
312 return SerializedElementKind.INSTANCE_FUNCTION;
313 }
314 }
315 if (element.isGetter) {
316 if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_GETTER;
317 if (element.isStatic) return SerializedElementKind.STATIC_GETTER;
318 if (element.isInstanceMember) {
319 return SerializedElementKind.INSTANCE_GETTER;
320 }
321 }
322 if (element.isSetter) {
323 if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_SETTER;
324 if (element.isStatic) return SerializedElementKind.STATIC_SETTER;
325 if (element.isInstanceMember) {
326 return SerializedElementKind.INSTANCE_SETTER;
327 }
328 }
329 return null;
330 }
331
332 void serialize(FunctionElement element,
333 ObjectEncoder encoder,
334 SerializedElementKind kind) {
335 encoder.setString(Key.NAME, element.name);
336 SerializerUtil.serializePosition(element, encoder);
337 SerializerUtil.serializeParameters(element, encoder);
338 encoder.setType(Key.TYPE, element.type);
339 if (element.isFunction) {
340 encoder.setBool(Key.IS_OPERATOR, element.isOperator);
341 }
342 if (element.enclosingClass != null) {
343 encoder.setElement(Key.CLASS, element.enclosingClass);
344 } else {
345 encoder.setElement(Key.LIBRARY, element.library);
346 encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
347 }
348 }
349 }
350
351 class TypedefSerializer implements ElementSerializer {
352 const TypedefSerializer();
353
354 SerializedElementKind getSerializedKind(Element element) {
355 if (element.isTypedef) {
356 return SerializedElementKind.TYPEDEF;
357 }
358 return null;
359 }
360
361 void serialize(TypedefElement element,
362 ObjectEncoder encoder,
363 SerializedElementKind kind) {
364 encoder.setString(Key.NAME, element.name);
365 SerializerUtil.serializePosition(element, encoder);
366 encoder.setType(Key.ALIAS, element.alias);
367 encoder.setElement(Key.LIBRARY, element.library);
368 encoder.setTypes(Key.TYPE_VARIABLES, element.typeVariables);
369 encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
370 }
371 }
372
373 class TypeVariableSerializer implements ElementSerializer {
374 const TypeVariableSerializer();
375
376 SerializedElementKind getSerializedKind(Element element) {
377 if (element.isTypeVariable) {
378 return SerializedElementKind.TYPEVARIABLE;
379 }
380 return null;
381 }
382
383 void serialize(TypeVariableElement element,
384 ObjectEncoder encoder,
385 SerializedElementKind kind) {
386 encoder.setElement(Key.TYPE_DECLARATION, element.typeDeclaration);
387 encoder.setString(Key.NAME, element.name);
388 SerializerUtil.serializePosition(element, encoder);
389 TypeDeclarationElement typeDeclaration = element.typeDeclaration;
390 encoder.setType(Key.TYPE, element.type);
391 encoder.setInt(Key.INDEX, element.index);
392 encoder.setType(Key.BOUND, element.bound);
393 }
394 }
395
396 class ParameterSerializer implements ElementSerializer {
397 const ParameterSerializer();
398
399 SerializedElementKind getSerializedKind(Element element) {
400 if (element.isParameter) {
401 return SerializedElementKind.PARAMETER;
402 } else if (element.isInitializingFormal) {
403 return SerializedElementKind.INITIALIZING_FORMAL;
404 }
405 return null;
406 }
407
408 void serialize(ParameterElement element,
409 ObjectEncoder encoder,
410 SerializedElementKind kind) {
411 encoder.setElement(Key.FUNCTION, element.functionDeclaration);
412 encoder.setString(Key.NAME, element.name);
413 SerializerUtil.serializePosition(element, encoder);
414 encoder.setType(Key.TYPE, element.type);
415 encoder.setBool(Key.IS_OPTIONAL, element.isOptional);
416 encoder.setBool(Key.IS_NAMED, element.isNamed);
417 if (element.isOptional) {
418 encoder.setConstant(Key.CONSTANT, element.constant);
419 }
420 if (element.isInitializingFormal) {
421 InitializingFormalElement initializingFormal = element;
422 encoder.setElement(Key.FIELD, initializingFormal.fieldElement);
423 }
424 }
425 }
426
427 /// Utility class for deserializing [Element]s.
428 ///
429 /// This is used by the [Deserializer].
430 class ElementDeserializer {
431
432 /// Deserializes an [Element] from an [ObjectDecoder].
433 ///
434 /// The class is called from the [Deserializer] when an [Element]
435 /// needs deserialization. The [ObjectDecoder] ensures that any [Element],
436 /// [DartType], and [ConstantExpression] that the deserialized [Element]
437 /// depends upon are available.
438 static Element deserialize(ObjectDecoder decoder) {
439 SerializedElementKind elementKind =
440 decoder.getEnum(Key.KIND, SerializedElementKind.values);
441 switch (elementKind) {
442 case SerializedElementKind.LIBRARY:
443 return new LibraryElementZ(decoder);
444 case SerializedElementKind.COMPILATION_UNIT:
445 return new CompilationUnitElementZ(decoder);
446 case SerializedElementKind.CLASS:
447 return new ClassElementZ(decoder);
448 case SerializedElementKind.TOPLEVEL_FIELD:
449 return new TopLevelFieldElementZ(decoder);
450 case SerializedElementKind.STATIC_FIELD:
451 return new StaticFieldElementZ(decoder);
452 case SerializedElementKind.INSTANCE_FIELD:
453 return new InstanceFieldElementZ(decoder);
454 case SerializedElementKind.GENERATIVE_CONSTRUCTOR:
455 return new GenerativeConstructorElementZ(decoder);
456 case SerializedElementKind.FACTORY_CONSTRUCTOR:
457 return new FactoryConstructorElementZ(decoder);
458 case SerializedElementKind.TOPLEVEL_FUNCTION:
459 return new TopLevelFunctionElementZ(decoder);
460 case SerializedElementKind.STATIC_FUNCTION:
461 return new StaticFunctionElementZ(decoder);
462 case SerializedElementKind.INSTANCE_FUNCTION:
463 return new InstanceFunctionElementZ(decoder);
464 case SerializedElementKind.TOPLEVEL_GETTER:
465 return new TopLevelGetterElementZ(decoder);
466 case SerializedElementKind.STATIC_GETTER:
467 return new StaticGetterElementZ(decoder);
468 case SerializedElementKind.INSTANCE_GETTER:
469 return new InstanceGetterElementZ(decoder);
470 case SerializedElementKind.TOPLEVEL_SETTER:
471 return new TopLevelSetterElementZ(decoder);
472 case SerializedElementKind.STATIC_SETTER:
473 return new StaticSetterElementZ(decoder);
474 case SerializedElementKind.INSTANCE_SETTER:
475 return new InstanceSetterElementZ(decoder);
476 case SerializedElementKind.TYPEDEF:
477 return new TypedefElementZ(decoder);
478 case SerializedElementKind.TYPEVARIABLE:
479 return new TypeVariableElementZ(decoder);
480 case SerializedElementKind.PARAMETER:
481 return new ParameterElementZ(decoder);
482 case SerializedElementKind.INITIALIZING_FORMAL:
483 return new InitializingFormalElementZ(decoder);
484 }
485 throw new UnsupportedError("Unexpected element kind '${elementKind}.");
486 }
487 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698