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

Unified 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: Created 5 years, 6 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
Index: pkg/compiler/lib/src/serialization/element_serialization.dart
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7be12449e43da4c4c41c1f8bcd88b86220777bba
--- /dev/null
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -0,0 +1,509 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.serialization.elements;
+
+import '../constants/expressions.dart';
+import '../dart_types.dart';
+import '../dart2jslib.dart' show SourceSpan;
+import '../elements/elements.dart';
+import '../tree/tree.dart';
+import 'constant_serialization.dart';
+import 'keys.dart';
+import 'modelz.dart';
+import 'serialization.dart';
+
+/// Enum kinds used for encoding [Element]s.
+enum SerializedElementKind {
+ LIBRARY,
+ COMPILATION_UNIT,
+ CLASS,
+ GENERATIVE_CONSTRUCTOR,
+ FACTORY_CONSTRUCTOR,
+ TOPLEVEL_FIELD,
+ STATIC_FIELD,
+ INSTANCE_FIELD,
+ TOPLEVEL_FUNCTION,
+ TOPLEVEL_GETTER,
+ TOPLEVEL_SETTER,
+ STATIC_FUNCTION,
+ STATIC_GETTER,
+ STATIC_SETTER,
+ INSTANCE_FUNCTION,
+ INSTANCE_GETTER,
+ INSTANCE_SETTER,
+ TYPEDEF,
+ TYPEVARIABLE,
+ PARAMETER,
+ INITIALIZING_FORMAL,
+}
+
+/// Set serializers used to serialize the different kinds of elements.
+const List<ElementSerializer> ELEMENT_SERIALIZERS = const [
+ const LibrarySerializer(),
+ const CompilationUnitSerializer(),
+ const ClassSerializer(),
+ const ConstructorSerializer(),
+ const FieldSerializer(),
+ const FunctionSerializer(),
+ const TypedefSerializer(),
+ const TypeVariableSerializer(),
+ const ParameterSerializer(),
+];
+
+/// Interface for a function that can serialize a set of element kinds.
+abstract class ElementSerializer {
+ /// Returns the [SerializedElementKind] for [element] if this serializer
+ /// supports serialization of [element] or `null` otherwise.
+ SerializedElementKind getSerializedKind(Element element);
+
+ /// Serializes [element] into the [serializer] using the [kind] computed
+ /// by [getSerializedKind].
+ void serialize(Element element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind);
+}
+
+class SerializerUtil {
floitsch 2015/06/26 20:54:04 generally we don't have utility classes (according
Johnni Winther 2015/07/03 12:13:44 I don't like the mixing of public classes and top
+ /// Serialize the declared members of [element] into [serializer].
+ static void serializeMembers(ScopeContainerElement element,
+ ObjectSerializer serializer) {
+ MapSerializer mapSerializer = serializer.createMap(Key.MEMBERS);
+ element.forEachLocalMember((Element member) {
+ String name = member.name;
+ if (member.isSetter) {
+ name = '$name,=';
+ }
+ mapSerializer.setElement(name, member);
+ });
+ }
+
+ /// Serialize the source position of [element] into [serializer].
+ static void serializePosition(Element element, ObjectSerializer serializer) {
+ if (element.sourcePosition != null) {
+ SourceSpan position = element.sourcePosition;
+ serializer.setInt(Key.OFFSET, position.begin);
+ if (position.uri != element.compilationUnit.script.resourceUri) {
+ // TODO(johnniwinther): What is the base URI in the case?
+ serializer.setUri(Key.URI, element.library.canonicalUri, position.uri);
+ }
+ int length = position.end - position.begin;
+ if (element.name.length != length) {
+ serializer.setInt(Key.LENGTH, length);
+ }
+ }
+ }
+
+ /// Serialize the parameters of [element] into [serializer].
+ static void serializerParameters(FunctionElement element,
floitsch 2015/06/26 20:54:04 serializeParameters
Johnni Winther 2015/07/03 12:13:44 Done.
+ ObjectSerializer serializer) {
+ FunctionType type = element.type;
+ serializer.setType(Key.RETURN_TYPE, type.returnType);
+ serializer.setElements(Key.PARAMETERS, element.parameters);
+ }
+
+ /// Returns a function that addeds the underlying declared elements for a
+ /// particular element into [list].
+ ///
+ /// For instance, for an [AbstractFieldElement] the getter and setter elements
+ /// are added, if available.
+ static flattenElements(List<Element> list) {
+ return (Element element) {
+ // TODO(johnniwinther): Handle ambiguous elements.
+ if (element.isAmbiguous) return;
+ if (element.isAbstractField) {
+ AbstractFieldElement abstractField = element;
+ if (abstractField.getter != null) {
+ list.add(abstractField.getter);
+ }
+ if (abstractField.setter != null) {
+ list.add(abstractField.setter);
+ }
+ } else {
+ list.add(element);
+ }
+ };
+ }
+}
+
+class LibrarySerializer implements ElementSerializer {
+ const LibrarySerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isLibrary) {
+ return SerializedElementKind.LIBRARY;
+ }
+ return null;
+ }
+
+ void serialize(LibraryElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setUri(
+ Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri);
+ serializer.setString(Key.LIBRARY_NAME, element.getLibraryName());
+ SerializerUtil.serializeMembers(element, serializer);
+ serializer.setElement(Key.COMPILATION_UNIT, element.entryCompilationUnit);
+ serializer.setElements(
+ Key.COMPILATION_UNITS, element.compilationUnits.toList());
+ ListSerializer tags = serializer.createList(Key.TAGS);
+ void addTags(LibraryElement library) {
floitsch 2015/06/26 20:54:04 new line before and after nested functions.
Johnni Winther 2015/07/03 12:13:44 Done.
+ for (LibraryTag tag in library.tags) {
+ if (tag is Import) {
+ ObjectSerializer importTag = tags.createObject();
+ importTag.setString(Key.KIND, 'import');
+ importTag.setElement(Key.LIBRARY, library.getLibraryFromTag(tag));
+ } else if (tag is Export) {
+ ObjectSerializer exportTag = tags.createObject();
+ exportTag.setString(Key.KIND, 'export');
+ exportTag.setElement(Key.LIBRARY, library.getLibraryFromTag(tag));
+ }
+ }
+ }
+ addTags(element);
+
+ List<Element> imports = <Element>[];
+ element.forEachImport(SerializerUtil.flattenElements(imports));
+ serializer.setElements(Key.IMPORTS, imports);
+
+ List<Element> exports = <Element>[];
+ element.forEachExport(SerializerUtil.flattenElements(exports));
+ serializer.setElements(Key.EXPORTS, exports);
+ }
+}
+
+class CompilationUnitSerializer implements ElementSerializer {
+ const CompilationUnitSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isCompilationUnit) {
+ return SerializedElementKind.COMPILATION_UNIT;
+ }
+ return null;
+ }
+
+ void serialize(CompilationUnitElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setElement(Key.LIBRARY, element.library);
+ serializer.setUri(
+ Key.URI, element.library.canonicalUri, element.script.resourceUri);
+ List<Element> elements = <Element>[];
+ element.forEachLocalMember((e) => elements.add(e));
+ serializer.setElements(Key.ELEMENTS, elements);
+ }
+}
+
+class ClassSerializer implements ElementSerializer {
+ const ClassSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isClass) {
+ return SerializedElementKind.CLASS;
+ }
+ return null;
+ }
+
+ void serialize(ClassElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setElement(Key.LIBRARY, element.library);
+ serializer.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+ serializer.setString(Key.NAME, element.name);
+ SerializerUtil.serializePosition(element, serializer);
+ serializer.setTypes(Key.TYPE_VARIABLES, element.typeVariables);
+ serializer.setBool(Key.IS_ABSTRACT, element.isAbstract);
+ if (element.supertype != null) {
+ serializer.setType(Key.SUPERTYPE, element.supertype);
+ }
+ // TODO(johnniwinther): Make [OrderedTypeSet] easier to (de)serialize.
+ ObjectSerializer supertypes = serializer.createObject(Key.SUPERTYPES);
+ supertypes.setTypes(Key.TYPES,
+ element.allSupertypesAndSelf.types.toList());
+ supertypes.setTypes(Key.SUPERTYPES,
+ element.allSupertypesAndSelf.supertypes.toList());
+ supertypes.setInts(Key.OFFSETS, element.allSupertypesAndSelf.levelOffsets);
+ serializer.setTypes(Key.INTERFACES, element.interfaces.toList());
+ SerializerUtil.serializeMembers(element, serializer);
+ }
+}
+
+class ConstructorSerializer implements ElementSerializer {
+ const ConstructorSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isGenerativeConstructor) {
+ return SerializedElementKind.GENERATIVE_CONSTRUCTOR;
+ } else if (element.isFactoryConstructor) {
+ return SerializedElementKind.FACTORY_CONSTRUCTOR;
+ }
+ return null;
+ }
+
+ void serialize(ConstructorElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setElement(Key.CLASS, element.enclosingClass);
+ serializer.setType(Key.TYPE, element.type);
+ serializer.setString(Key.NAME, element.name);
+ SerializerUtil.serializePosition(element, serializer);
+ SerializerUtil.serializerParameters(element, serializer);
+ serializer.setBool(Key.IS_CONST, element.isConst);
+ if (element.isConst && !element.isFromEnvironmentConstructor) {
+ ConstantConstructor constantConstructor = element.constantConstructor;
+ ObjectSerializer constantSerializer =
+ serializer.createObject(Key.CONSTRUCTOR);
+ const ConstantConstructorSerializer().visit(
+ constantConstructor, constantSerializer);
+ constantSerializer.setEnum(Key.KIND, constantConstructor.kind);
+ switch (constantConstructor.kind) {
+ case ConstantConstructorKind.GENERATIVE:
+ GenerativeConstantConstructor generativeConstantConstructor =
+ constantConstructor;
+ constantSerializer.setType(
+ Key.TYPE, generativeConstantConstructor.type);
+ MapSerializer defaults = constantSerializer.createMap(Key.DEFAULTS);
+ generativeConstantConstructor.defaultValues.forEach((key, e) {
+ defaults.setConstant('$key', e);
+ });
+ ListSerializer fields = constantSerializer.createList(Key.FIELDS);
+ generativeConstantConstructor.fieldMap.forEach(
+ (FieldElement f, ConstantExpression e) {
+ ObjectSerializer fieldSerializer = fields.createObject();
+ fieldSerializer.setElement(Key.FIELD, f);
+ fieldSerializer.setConstant(Key.CONSTANT, e);
+ });
+ if (generativeConstantConstructor
+ .superConstructorInvocation != null) {
+ constantSerializer.setConstant(Key.CONSTRUCTOR,
+ generativeConstantConstructor.superConstructorInvocation);
+ }
+ break;
+ case ConstantConstructorKind.REDIRECTING_GENERATIVE:
+ RedirectingGenerativeConstantConstructor
+ redirectingGenerativeConstantConstructor =
+ constantConstructor;
+ MapSerializer defaults = constantSerializer.createMap(Key.DEFAULTS);
+ redirectingGenerativeConstantConstructor.defaultValues.forEach(
+ (key, ConstantExpression e) {
+ defaults.setConstant('$key', e);
+ });
+ constantSerializer.setConstant(Key.CONSTRUCTOR,
+ redirectingGenerativeConstantConstructor
+ .thisConstructorInvocation);
+ break;
+ case ConstantConstructorKind.REDIRECTING_FACTORY:
+ RedirectingFactoryConstantConstructor
+ redirectingFactoryConstantConstructor = constantConstructor;
+ constantSerializer.setConstant(Key.CONSTRUCTOR,
+ redirectingFactoryConstantConstructor
+ .targetConstructorInvocation);
+ break;
+ }
+ }
+ }
+}
+
+class FieldSerializer implements ElementSerializer {
+ const FieldSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isField) {
+ if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_FIELD;
+ if (element.isStatic) return SerializedElementKind.STATIC_FIELD;
+ if (element.isInstanceMember) return SerializedElementKind.INSTANCE_FIELD;
+ }
+ return null;
+ }
+
+ void serialize(FieldElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setString(Key.NAME, element.name);
+ SerializerUtil.serializePosition(element, serializer);
+ serializer.setType(Key.TYPE, element.type);
+ serializer.setBool(Key.IS_FINAL, element.isFinal);
+ serializer.setBool(Key.IS_CONST, element.isConst);
+ if (element.isConst) {
+ ConstantExpression constant = element.constant;
+ serializer.setConstant(Key.CONSTANT, constant);
+ }
+ if (kind != SerializedElementKind.TOPLEVEL_FIELD) {
+ serializer.setElement(Key.CLASS, element.enclosingClass);
+ } else {
+ serializer.setElement(Key.LIBRARY, element.library);
+ serializer.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+ }
+ }
+}
+
+class FunctionSerializer implements ElementSerializer {
+ const FunctionSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isFunction) {
+ if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_FUNCTION;
+ if (element.isStatic) return SerializedElementKind.STATIC_FUNCTION;
+ if (element.isInstanceMember) return SerializedElementKind.INSTANCE_FUNCTION;
floitsch 2015/06/26 20:54:04 long lines.
Johnni Winther 2015/07/03 12:13:44 Done.
+ }
+ if (element.isGetter) {
+ if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_GETTER;
+ if (element.isStatic) return SerializedElementKind.STATIC_GETTER;
+ if (element.isInstanceMember) return SerializedElementKind.INSTANCE_GETTER;
+ }
+ if (element.isSetter) {
+ if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_SETTER;
+ if (element.isStatic) return SerializedElementKind.STATIC_SETTER;
+ if (element.isInstanceMember) return SerializedElementKind.INSTANCE_SETTER;
+ }
+ return null;
+ }
+
+ void serialize(FunctionElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setString(Key.NAME, element.name);
+ SerializerUtil.serializePosition(element, serializer);
+ serializer.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+ SerializerUtil.serializerParameters(element, serializer);
+ serializer.setType(Key.TYPE, element.type);
+ if (element.isFunction) {
+ serializer.setBool(Key.IS_OPERATOR, element.isOperator);
+ }
+ if (element.enclosingClass != null) {
+ serializer.setElement(Key.CLASS, element.enclosingClass);
+ } else {
+ serializer.setElement(Key.LIBRARY, element.library);
+ serializer.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+ }
+ }
+}
+
+class TypedefSerializer implements ElementSerializer {
+ const TypedefSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isTypedef) {
+ return SerializedElementKind.TYPEDEF;
+ }
+ return null;
+ }
+
+ void serialize(TypedefElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setString(Key.NAME, element.name);
+ SerializerUtil.serializePosition(element, serializer);
+ serializer.setType(Key.ALIAS, element.alias);
+ serializer.setElement(Key.LIBRARY, element.library);
+ serializer.setTypes(Key.TYPE_VARIABLES, element.typeVariables);
+ serializer.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+ }
+}
+
+class TypeVariableSerializer implements ElementSerializer {
+ const TypeVariableSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isTypeVariable) {
+ return SerializedElementKind.TYPEVARIABLE;
+ }
+ return null;
+ }
+
+ void serialize(TypeVariableElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setElement(Key.TYPE_DECLARATION, element.typeDeclaration);
+ serializer.setString(Key.NAME, element.name);
+ SerializerUtil.serializePosition(element, serializer);
+ TypeDeclarationElement typeDeclaration = element.typeDeclaration;
+ serializer.setType(Key.TYPE, element.type);
+ serializer.setInt(Key.INDEX, element.index);
+ serializer.setType(Key.BOUND, element.bound);
+ }
+}
+
+class ParameterSerializer implements ElementSerializer {
+ const ParameterSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isParameter) {
+ return SerializedElementKind.PARAMETER;
+ } else if (element.isInitializingFormal) {
+ return SerializedElementKind.INITIALIZING_FORMAL;
+ }
+ return null;
+ }
+
+ void serialize(ParameterElement element,
+ ObjectSerializer serializer,
+ SerializedElementKind kind) {
+ serializer.setElement(Key.FUNCTION, element.functionDeclaration);
+ serializer.setString(Key.NAME, element.name);
+ SerializerUtil.serializePosition(element, serializer);
+ serializer.setType(Key.TYPE, element.type);
+ serializer.setBool(Key.IS_OPTIONAL, element.isOptional);
+ serializer.setBool(Key.IS_NAMED, element.isNamed);
+ if (element.isOptional) {
+ serializer.setConstant(Key.CONSTANT, element.constant);
+ }
+ if (element.isInitializingFormal) {
+ InitializingFormalElement initializingFormal = element;
+ serializer.setElement(Key.FIELD, initializingFormal.fieldElement);
+ }
+ }
+}
+
+class ElementDeserializer {
+ static Element deserialize(ObjectDeserializer deserializer) {
+ SerializedElementKind elementKind =
+ deserializer.getEnum(Key.KIND, SerializedElementKind.values);
+ switch (elementKind) {
+ case SerializedElementKind.LIBRARY:
+ return new LibraryElementZ(deserializer);
+ case SerializedElementKind.COMPILATION_UNIT:
+ return new CompilationUnitElementZ(deserializer);
+ case SerializedElementKind.CLASS:
+ return new ClassElementZ(deserializer);
+ case SerializedElementKind.TOPLEVEL_FIELD:
+ return new TopLevelFieldElementZ(deserializer);
+ case SerializedElementKind.STATIC_FIELD:
+ return new StaticFieldElementZ(deserializer);
+ case SerializedElementKind.INSTANCE_FIELD:
+ return new InstanceFieldElementZ(deserializer);
+ case SerializedElementKind.GENERATIVE_CONSTRUCTOR:
+ return new GenerativeConstructorElementZ(deserializer);
+ case SerializedElementKind.FACTORY_CONSTRUCTOR:
+ return new FactoryConstructorElementZ(deserializer);
+ case SerializedElementKind.TOPLEVEL_FUNCTION:
+ return new TopLevelFunctionElementZ(deserializer);
+ case SerializedElementKind.STATIC_FUNCTION:
+ return new StaticFunctionElementZ(deserializer);
+ case SerializedElementKind.INSTANCE_FUNCTION:
+ return new InstanceFunctionElementZ(deserializer);
+ case SerializedElementKind.TOPLEVEL_GETTER:
+ return new TopLevelGetterElementZ(deserializer);
+ case SerializedElementKind.STATIC_GETTER:
+ return new StaticGetterElementZ(deserializer);
+ case SerializedElementKind.INSTANCE_GETTER:
+ return new InstanceGetterElementZ(deserializer);
+ case SerializedElementKind.TOPLEVEL_SETTER:
+ return new TopLevelSetterElementZ(deserializer);
+ case SerializedElementKind.STATIC_SETTER:
+ return new StaticSetterElementZ(deserializer);
+ case SerializedElementKind.INSTANCE_SETTER:
+ return new InstanceSetterElementZ(deserializer);
+ case SerializedElementKind.TYPEDEF:
+ return new TypedefElementZ(deserializer);
+ case SerializedElementKind.TYPEVARIABLE:
+ return new TypeVariableElementZ(deserializer);
+ case SerializedElementKind.PARAMETER:
+ return new ParameterElementZ(deserializer);
+ case SerializedElementKind.INITIALIZING_FORMAL:
+ return new InitializingFormalElementZ(deserializer);
+ }
+ throw new UnsupportedError("Unexpected element kind '${elementKind}.");
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698