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

Unified Diff: sdk/lib/_internal/compiler/implementation/dart_backend/outputter.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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: sdk/lib/_internal/compiler/implementation/dart_backend/outputter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/outputter.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/outputter.dart
deleted file mode 100644
index f705c527427c039e7ceb20e6014db99794b2a4bf..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/outputter.dart
+++ /dev/null
@@ -1,562 +0,0 @@
-// Copyright (c) 2014, 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.
-
-part of dart_backend;
-
-typedef bool IsSafeToRemoveTypeDeclarations(
- Map<ClassElement, Iterable<Element>> classMembers);
-typedef void ElementCallback<E>(E element);
-typedef void ElementPostProcessFunction(
- AstElement element, ElementAst elementAst,
- ElementCallback<TypedefElement> typedefCallback,
- ElementCallback<ClassElement> classCallback);
-typedef ElementAst ComputeElementAstFunction(AstElement element);
-typedef bool ElementFilter(Element element);
-typedef List<Element> ElementSorter(Iterable<Element> elements);
-
-/// Output engine for dart2dart that is shared between the dart2js and the
-/// analyzer implementations of dart2dart.
-class DartOutputter {
- final DiagnosticListener listener;
- final CompilerOutputProvider outputProvider;
- final bool forceStripTypes;
-
- // TODO(antonm): make available from command-line options.
- final bool outputAst = false;
- final bool enableMinification;
-
- /// If `true`, libraries are generated into separate files.
- final bool multiFile;
-
- /// Internal structures accessible for tests and logging.
- // TODO(johnniwinther): Clean this up.
- PlaceholderRenamer renamer;
- MainOutputGenerator output;
- LibraryInfo libraryInfo;
- ElementInfo elementInfo;
-
- // TODO(johnniwinther): Support recompilation.
- DartOutputter(this.listener, this.outputProvider,
- {bool this.forceStripTypes: false,
- bool this.enableMinification: false,
- bool this.multiFile: false});
-
- /// Generate Dart code for the program starting at [mainFunction].
- ///
- /// [libraries] is the set of all libraries (user/package/sdk) that are
- /// referenced in the program.
- ///
- /// [instantiatedClasses] is the set of classes that are potentially
- /// instantiated in the program.
- ///
- /// [resolvedElements] is the set of methods, constructors, and fields that
- /// are potentially accessed/called in the program.
- ///
- /// The [sortElements] function is used to sort [instantiatedClasses] and
- /// [resolvedElements] in the generated output.
- String assembleProgram({
- MirrorRenamer mirrorRenamer: const MirrorRenamer(),
- Iterable<LibraryElement> libraries,
- Iterable<Element> instantiatedClasses,
- Iterable<Element> resolvedElements,
- Iterable<ClassElement> usedTypeLiterals: const <ClassElement>[],
- FunctionElement mainFunction,
- Uri outputUri,
- ElementPostProcessFunction postProcessElementAst,
- ComputeElementAstFunction computeElementAst,
- ElementFilter shouldOutput,
- IsSafeToRemoveTypeDeclarations isSafeToRemoveTypeDeclarations,
- ElementSorter sortElements}) {
-
- assert(invariant(NO_LOCATION_SPANNABLE, libraries != null,
- message: "'libraries' must be non-null."));
- assert(invariant(NO_LOCATION_SPANNABLE, instantiatedClasses != null,
- message: "'instantiatedClasses' must be non-null."));
- assert(invariant(NO_LOCATION_SPANNABLE, resolvedElements != null,
- message: "'resolvedElements' must be non-null."));
- assert(invariant(NO_LOCATION_SPANNABLE, mainFunction != null,
- message: "'mainFunction' must be non-null."));
- assert(invariant(NO_LOCATION_SPANNABLE, computeElementAst != null,
- message: "'computeElementAst' must be non-null."));
- assert(invariant(NO_LOCATION_SPANNABLE, shouldOutput != null,
- message: "'shouldOutput' must be non-null."));
- assert(invariant(NO_LOCATION_SPANNABLE,
- isSafeToRemoveTypeDeclarations != null,
- message: "'isSafeToRemoveTypeDeclarations' must be non-null."));
-
- if (sortElements == null) {
- // Ensure deterministic output order.
- sortElements = (Iterable<Element> elements) {
- List<Element> list = elements.toList();
- list.sort((Element a, Element b) => a.name.compareTo(b.name));
- return list;
- };
- }
-
- libraryInfo = LibraryInfo.processLibraries(libraries, resolvedElements);
-
- elementInfo = ElementInfoProcessor.createElementInfo(
- instantiatedClasses,
- resolvedElements,
- usedTypeLiterals,
- postProcessElementAst: postProcessElementAst,
- parseElementAst: computeElementAst,
- shouldOutput: shouldOutput,
- sortElements: sortElements);
-
- PlaceholderCollector collector = collectPlaceholders(
- listener,
- mirrorRenamer,
- mainFunction,
- libraryInfo,
- elementInfo);
-
- renamer = createRenamer(
- collector,
- libraryInfo,
- elementInfo,
- enableMinification: enableMinification,
- forceStripTypes: forceStripTypes,
- isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations);
-
- String assembledCode;
- if (outputAst) {
- assembledCode = astOutput(listener, elementInfo);
- } else {
- output = new MainOutputGenerator();
- assembledCode = output.generateCode(
- libraryInfo,
- elementInfo,
- collector,
- renamer,
- mainFunction,
- outputUri,
- outputProvider,
- mirrorRenamer,
- multiFile: multiFile,
- forceStripTypes: forceStripTypes,
- enableMinification: enableMinification);
- }
- return assembledCode;
- }
-
- static PlaceholderCollector collectPlaceholders(
- DiagnosticListener listener,
- MirrorRenamer mirrorRenamer,
- FunctionElement mainFunction,
- LibraryInfo libraryInfo,
- ElementInfo elementInfo) {
- // Create all necessary placeholders.
- PlaceholderCollector collector = new PlaceholderCollector(
- listener,
- mirrorRenamer,
- libraryInfo.fixedMemberNames,
- elementInfo.elementAsts,
- mainFunction);
-
- makePlaceholders(element) {
- collector.collect(element);
-
- if (element.isClass) {
- elementInfo.classMembers[element].forEach(makePlaceholders);
- }
- }
- elementInfo.topLevelElements.forEach(makePlaceholders);
- return collector;
- }
-
- static PlaceholderRenamer createRenamer(
- PlaceholderCollector collector,
- LibraryInfo libraryInfo,
- ElementInfo elementInfo,
- {bool enableMinification: false,
- bool forceStripTypes: false,
- isSafeToRemoveTypeDeclarations}) {
- // Create renames.
- bool shouldCutDeclarationTypes = forceStripTypes
- || (enableMinification
- && isSafeToRemoveTypeDeclarations(elementInfo.classMembers));
-
- PlaceholderRenamer placeholderRenamer = new PlaceholderRenamer(
- libraryInfo.fixedMemberNames, libraryInfo.reexportingLibraries,
- cutDeclarationTypes: shouldCutDeclarationTypes,
- enableMinification: enableMinification);
-
- placeholderRenamer.computeRenames(collector);
- return placeholderRenamer;
- }
-
- static String astOutput(DiagnosticListener listener,
- ElementInfo elementInfo) {
- // TODO(antonm): Ideally XML should be a separate backend.
- // TODO(antonm): obey renames and minification, at least as an option.
- StringBuffer sb = new StringBuffer();
- outputElement(element) {
- sb.write(element.parseNode(listener).toDebugString());
- }
-
- // Emit XML for AST instead of the program.
- for (Element topLevel in elementInfo.topLevelElements) {
- if (topLevel.isClass &&
- !elementInfo.emitNoMembersFor.contains(topLevel)) {
- // TODO(antonm): add some class info.
- elementInfo.classMembers[topLevel].forEach(outputElement);
- } else {
- outputElement(topLevel);
- }
- }
- return '<Program>\n$sb</Program>\n';
- }
-}
-
-class LibraryInfo {
- final Set<String> fixedMemberNames;
- final Map<Element, LibraryElement> reexportingLibraries;
- final List<LibraryElement> userLibraries;
-
- LibraryInfo(this.fixedMemberNames,
- this.reexportingLibraries,
- this.userLibraries);
-
- static LibraryInfo processLibraries(
- Iterable<LibraryElement> libraries,
- Iterable<AstElement> resolvedElements) {
- Set<String> fixedMemberNames = new Set<String>();
- Map<Element, LibraryElement> reexportingLibraries =
- <Element, LibraryElement>{};
- List<LibraryElement> userLibraries = <LibraryElement>[];
- // Conservatively traverse all platform libraries and collect member names.
- // TODO(antonm): ideally we should only collect names of used members,
- // however as of today there are problems with names of some core library
- // interfaces, most probably for interfaces of literals.
-
- for (LibraryElement library in libraries) {
- if (!library.isPlatformLibrary) {
- userLibraries.add(library);
- continue;
- }
- library.forEachLocalMember((Element element) {
- if (element.isClass) {
- ClassElement classElement = element;
- assert(invariant(classElement, classElement.isResolved,
- message: "Unresolved platform class."));
- classElement.forEachLocalMember((member) {
- String name = member.name;
- // Skip operator names.
- if (!name.startsWith(r'operator$')) {
- // Fetch name of named constructors and factories if any,
- // otherwise store regular name.
- // TODO(antonm): better way to analyze the name.
- fixedMemberNames.add(name.split(r'$').last);
- }
- });
- }
- // Even class names are added due to a delicate problem we have:
- // if one imports dart:core with a prefix, we cannot tell prefix.name
- // from dynamic invocation (alas!). So we'd better err on preserving
- // those names.
- fixedMemberNames.add(element.name);
- });
-
- for (Element export in library.exports) {
- if (!library.isInternalLibrary &&
- export.library.isInternalLibrary) {
- // If an element of an internal library is reexported by a platform
- // library, we have to import the reexporting library instead of the
- // internal library, because the internal library is an
- // implementation detail of dart2js.
- reexportingLibraries[export] = library;
- }
- }
- }
- // As of now names of named optionals are not renamed. Therefore add all
- // field names used as named optionals into [fixedMemberNames].
- for (final element in resolvedElements) {
- if (!element.isConstructor) continue;
- Link<Element> optionalParameters =
- element.functionSignature.optionalParameters;
- for (final optional in optionalParameters) {
- if (!optional.isInitializingFormal) continue;
- fixedMemberNames.add(optional.name);
- }
- }
- // The VM will automatically invoke the call method of objects
- // that are invoked as functions. Make sure to not rename that.
- fixedMemberNames.add('call');
- // TODO(antonm): TypeError.srcType and TypeError.dstType are defined in
- // runtime/lib/error.dart. Overall, all DartVM specific libs should be
- // accounted for.
- fixedMemberNames.add('srcType');
- fixedMemberNames.add('dstType');
-
- return new LibraryInfo(
- fixedMemberNames, reexportingLibraries, userLibraries);
- }
-}
-
-class ElementInfo {
- final Map<Element, ElementAst> elementAsts;
- final Iterable<Element> topLevelElements;
- final Map<ClassElement, Iterable<Element>> classMembers;
- final Iterable<ClassElement> emitNoMembersFor;
-
- ElementInfo(this.elementAsts,
- this.topLevelElements,
- this.classMembers,
- this.emitNoMembersFor);
-}
-
-class ElementInfoProcessor implements ElementInfo {
- final Map<Element, ElementAst> elementAsts = new Map<Element, ElementAst>();
- final Set<Element> topLevelElements = new Set<Element>();
- final Map<ClassElement, Set<Element>> classMembers =
- new Map<ClassElement, Set<Element>>();
- final Set<ClassElement> emitNoMembersFor = new Set<ClassElement>();
- final ElementPostProcessFunction postProcessElementAst;
- final ComputeElementAstFunction parseElementAst;
- final ElementFilter shouldOutput;
-
- ElementInfoProcessor(
- {this.postProcessElementAst,
- this.parseElementAst,
- this.shouldOutput});
-
- static ElementInfo createElementInfo(
- Iterable<ClassElement> instantiatedClasses,
- Iterable<AstElement> resolvedElements,
- Iterable<ClassElement> usedTypeLiterals,
- {ElementPostProcessFunction postProcessElementAst,
- ComputeElementAstFunction parseElementAst,
- ElementFilter shouldOutput,
- ElementSorter sortElements}) {
- ElementInfoProcessor processor = new ElementInfoProcessor(
- postProcessElementAst: postProcessElementAst,
- parseElementAst: parseElementAst,
- shouldOutput: shouldOutput);
- return processor.process(
- instantiatedClasses, resolvedElements, usedTypeLiterals,
- sortElements: sortElements);
- }
-
- ElementInfo process(Iterable<ClassElement> instantiatedClasses,
- Iterable<AstElement> resolvedElements,
- Iterable<ClassElement> usedTypeLiterals,
- {ElementSorter sortElements}) {
- // Build all top level elements to emit and necessary class members.
- instantiatedClasses.where(shouldOutput).forEach(addClass);
- resolvedElements.where(shouldOutput).forEach(addMember);
- usedTypeLiterals.forEach((ClassElement element) {
- if (shouldOutput(element)) {
- if (!topLevelElements.contains(element)) {
- // The class is only referenced by type literals.
- emitNoMembersFor.add(element);
- }
- addClass(element);
- }
- });
-
- // Sort elements.
- List<Element> sortedTopLevels = sortElements(topLevelElements);
- Map<ClassElement, List<Element>> sortedClassMembers =
- new Map<ClassElement, List<Element>>();
- classMembers.forEach((classElement, members) {
- sortedClassMembers[classElement] = sortElements(members);
- });
-
- return new ElementInfo(
- elementAsts, sortedTopLevels, sortedClassMembers, emitNoMembersFor);
- }
-
- void processElement(Element element, ElementAst elementAst) {
- if (postProcessElementAst != null) {
- postProcessElementAst(element, elementAst,
- newTypedefElementCallback,
- newClassElementCallback);
- }
- elementAsts[element] = elementAst;
- }
-
- void addTopLevel(AstElement element, ElementAst elementAst) {
- if (topLevelElements.contains(element)) return;
- topLevelElements.add(element);
- processElement(element, elementAst);
- }
-
- void addClass(ClassElement classElement) {
- TreeElements treeElements = new TreeElementMapping(classElement);
- backend2frontend.TreePrinter treePrinter =
- new backend2frontend.TreePrinter(treeElements);
- Node node = treePrinter.makeNodeForClassElement(classElement);
- addTopLevel(classElement, new ElementAst.internal(node, treeElements));
- classMembers.putIfAbsent(classElement, () => new Set());
- }
-
- void newTypedefElementCallback(TypedefElement element) {
- if (!shouldOutput(element)) return;
- addTopLevel(element, new ElementAst(element));
- }
-
- void newClassElementCallback(ClassElement classElement) {
- if (!shouldOutput(classElement)) return;
- addClass(classElement);
- }
-
- void addMember(element) {
- ElementAst elementAst = parseElementAst(element);
- if (element.isClassMember) {
- ClassElement enclosingClass = element.enclosingClass;
- assert(enclosingClass.isClass);
- assert(enclosingClass.isTopLevel);
- assert(shouldOutput(enclosingClass));
- addClass(enclosingClass);
- classMembers[enclosingClass].add(element);
- processElement(element, elementAst);
- } else {
- if (element.isTopLevel) {
- addTopLevel(element, elementAst);
- }
- }
- }
-}
-
-/// Main output generator for [DartOutputter] that emits dart code through a
-/// [CompilerOutputProvider].
-class MainOutputGenerator {
- final Map<ClassNode, List<Node>> memberNodes =
- new Map<ClassNode, List<Node>>();
- final List<Node> topLevelNodes = <Node>[];
-
- String generateCode(
- LibraryInfo libraryInfo,
- ElementInfo elementInfo,
- PlaceholderCollector collector,
- PlaceholderRenamer placeholderRenamer,
- FunctionElement mainFunction,
- Uri outputUri,
- CompilerOutputProvider outputProvider,
- MirrorRenamer mirrorRenamer,
- {bool multiFile: false,
- bool forceStripTypes: false,
- bool enableMinification: false}) {
- for (Element element in elementInfo.topLevelElements) {
- topLevelNodes.add(elementInfo.elementAsts[element].ast);
- if (element.isClass && !element.isMixinApplication) {
- final members = <Node>[];
- for (Element member in elementInfo.classMembers[element]) {
- members.add(elementInfo.elementAsts[member].ast);
- }
- memberNodes[elementInfo.elementAsts[element].ast] = members;
- }
- }
-
- mirrorRenamer.addRenames(placeholderRenamer.renames,
- topLevelNodes, collector);
-
- Map<LibraryElement, String> outputPaths = new Map<LibraryElement, String>();
- Map<LibraryElement, EmitterUnparser> unparsers =
- new Map<LibraryElement, EmitterUnparser>();
-
- // The single unparser used if we collect all the output in one file.
- EmitterUnparser mainUnparser = multiFile
- ? null
- : new EmitterUnparser(placeholderRenamer.renames,
- stripTypes: forceStripTypes,
- minify: enableMinification);
-
- if (multiFile) {
- // TODO(sigurdm): Factor handling of library-paths out from emitting.
- String mainName = outputUri.pathSegments.last;
- String mainBaseName = mainName.endsWith(".dart")
- ? mainName.substring(0, mainName.length - 5)
- : mainName;
- // Map each library to a path based on the uri of the original
- // library and [compiler.outputUri].
- Set<String> usedLibraryPaths = new Set<String>();
- for (LibraryElement library in libraryInfo.userLibraries) {
- if (library == mainFunction.library) {
- outputPaths[library] = mainBaseName;
- } else {
- List<String> names =
- library.canonicalUri.pathSegments.last.split(".");
- if (names.last == "dart") {
- names = names.sublist(0, names.length - 1);
- }
- outputPaths[library] =
- "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}";
- }
- }
-
- /// Rewrites imports/exports to refer to the paths given in [outputPaths].
- for(LibraryElement outputLibrary in libraryInfo.userLibraries) {
- EmitterUnparser unparser = new EmitterUnparser(
- placeholderRenamer.renames,
- stripTypes: forceStripTypes,
- minify: enableMinification);
- unparsers[outputLibrary] = unparser;
- LibraryName libraryName = outputLibrary.libraryTag;
- if (libraryName != null) {
- unparser.visitLibraryName(libraryName);
- }
- for (LibraryTag tag in outputLibrary.tags) {
- if (tag is! LibraryDependency) continue;
- LibraryDependency dependency = tag;
- LibraryElement libraryElement =
- outputLibrary.getLibraryFromTag(dependency);
- String uri = outputPaths.containsKey(libraryElement)
- ? "${outputPaths[libraryElement]}.dart"
- : libraryElement.canonicalUri.toString();
- if (dependency is Import) {
- unparser.unparseImportTag(uri);
- } else {
- unparser.unparseExportTag(uri);
- }
- }
- }
- } else {
- for(LibraryElement library in placeholderRenamer.platformImports) {
- if (library.isPlatformLibrary && !library.isInternalLibrary) {
- mainUnparser.unparseImportTag(library.canonicalUri.toString());
- }
- }
- }
-
- for (int i = 0; i < elementInfo.topLevelElements.length; i++) {
- Element element = elementInfo.topLevelElements.elementAt(i);
- Node node = topLevelNodes[i];
- Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser;
- if (node is ClassNode) {
- // TODO(smok): Filter out default constructors here.
- unparser.unparseClassWithBody(node, memberNodes[node]);
- } else {
- unparser.unparse(node);
- }
- unparser.newline();
- }
-
- int totalSize = 0;
- String assembledCode;
- if (multiFile) {
- for(LibraryElement outputLibrary in libraryInfo.userLibraries) {
- // TODO(sigurdm): Make the unparser output directly into the buffer
- // instead of caching in `.result`.
- String code = unparsers[outputLibrary].result;
- totalSize += code.length;
- outputProvider(outputPaths[outputLibrary], "dart")
- ..add(code)
- ..close();
- }
- // TODO(sigurdm): We should get rid of compiler.assembledCode.
- assembledCode = unparsers[mainFunction.library].result;
- } else {
- assembledCode = mainUnparser.result;
- outputProvider("", "dart")
- ..add(assembledCode)
- ..close();
-
- totalSize = assembledCode.length;
- }
-
- return assembledCode;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698