Chromium Code Reviews| 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}."); |
| + } |
| +} |