OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart_backend; | 5 part of dart_backend; |
6 | 6 |
7 // TODO(ahe): This class is simply wrong. This backend should use | 7 // TODO(ahe): This class is simply wrong. This backend should use |
8 // elements when it can, not AST nodes. Perhaps a [Map<Element, | 8 // elements when it can, not AST nodes. Perhaps a [Map<Element, |
9 // TreeElements>] is what is needed. | 9 // TreeElements>] is what is needed. |
10 class ElementAst { | 10 class ElementAst { |
11 final Node ast; | 11 final Node ast; |
12 final TreeElements treeElements; | 12 final TreeElements treeElements; |
13 | 13 |
14 ElementAst(AstElement element) | 14 ElementAst(AstElement element) |
15 : this.internal(element.resolvedAst.node, element.resolvedAst.elements); | 15 : this.internal(element.resolvedAst.node, element.resolvedAst.elements); |
16 | 16 |
17 ElementAst.internal(this.ast, this.treeElements); | 17 ElementAst.internal(this.ast, this.treeElements); |
18 } | 18 } |
19 | 19 |
20 class DartBackend extends Backend { | 20 class DartBackend extends Backend { |
21 final List<CompilerTask> tasks; | 21 final List<CompilerTask> tasks; |
22 final bool forceStripTypes; | 22 final bool forceStripTypes; |
23 final bool stripAsserts; | 23 final bool stripAsserts; |
24 // TODO(antonm): make available from command-line options. | 24 // TODO(antonm): make available from command-line options. |
25 final bool outputAst = false; | 25 final bool outputAst = false; |
26 final Map<ClassNode, List<Node>> memberNodes; | 26 final Map<ClassNode, List<Node>> memberNodes; |
27 | 27 |
28 /// If `true`, libraries are generated into separate files. | |
29 final bool multiFile; | |
30 | |
28 PlaceholderRenamer placeholderRenamer; | 31 PlaceholderRenamer placeholderRenamer; |
29 | 32 |
30 // TODO(zarah) Maybe change this to a command-line option. | 33 // TODO(zarah) Maybe change this to a command-line option. |
31 // Right now, it is set by the tests. | 34 // Right now, it is set by the tests. |
32 bool useMirrorHelperLibrary = false; | 35 bool useMirrorHelperLibrary = false; |
33 | 36 |
34 /// Initialized if the useMirrorHelperLibrary field is set. | 37 /// Initialized if the useMirrorHelperLibrary field is set. |
35 MirrorRenamer mirrorRenamer; | 38 MirrorRenamer mirrorRenamer; |
36 | 39 |
37 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary | 40 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
95 ClassElement element = type.element; | 98 ClassElement element = type.element; |
96 // Check all supertypes. | 99 // Check all supertypes. |
97 if (element.allSupertypes != null) { | 100 if (element.allSupertypes != null) { |
98 element.allSupertypes.forEach(workQueue.add); | 101 element.allSupertypes.forEach(workQueue.add); |
99 } | 102 } |
100 } | 103 } |
101 } | 104 } |
102 return true; | 105 return true; |
103 } | 106 } |
104 | 107 |
105 DartBackend(Compiler compiler, List<String> strips) | 108 DartBackend(Compiler compiler, List<String> strips, {this.multiFile}) |
106 : tasks = <CompilerTask>[], | 109 : tasks = <CompilerTask>[], |
107 memberNodes = new Map<ClassNode, List<Node>>(), | 110 memberNodes = new Map<ClassNode, List<Node>>(), |
108 forceStripTypes = strips.indexOf('types') != -1, | 111 forceStripTypes = strips.indexOf('types') != -1, |
109 stripAsserts = strips.indexOf('asserts') != -1, | 112 stripAsserts = strips.indexOf('asserts') != -1, |
110 constantCompilerTask = new DartConstantTask(compiler), | 113 constantCompilerTask = new DartConstantTask(compiler), |
111 super(compiler) { | 114 super(compiler) { |
112 resolutionCallbacks = new DartResolutionCallbacks(this); | 115 resolutionCallbacks = new DartResolutionCallbacks(this); |
113 } | 116 } |
114 | 117 |
115 bool classNeedsRti(ClassElement cls) => false; | 118 bool classNeedsRti(ClassElement cls) => false; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 compiler.tracer.traceGraph('Unshadow parameters', definition); | 260 compiler.tracer.traceGraph('Unshadow parameters', definition); |
258 | 261 |
259 TreeElementMapping treeElements = new TreeElementMapping(element); | 262 TreeElementMapping treeElements = new TreeElementMapping(element); |
260 backend_ast.Node backendAst = | 263 backend_ast.Node backendAst = |
261 backend_ast_emitter.emit(definition); | 264 backend_ast_emitter.emit(definition); |
262 Node frontend_ast = backend2frontend.emit(treeElements, backendAst); | 265 Node frontend_ast = backend2frontend.emit(treeElements, backendAst); |
263 return new ElementAst.internal(frontend_ast, treeElements); | 266 return new ElementAst.internal(frontend_ast, treeElements); |
264 } | 267 } |
265 } | 268 } |
266 | 269 |
270 List<LibraryElement> userLibraries = | |
271 compiler.libraryLoader.libraries.where(isUserLibrary).toList(); | |
272 | |
267 Set<Element> topLevelElements = new Set<Element>(); | 273 Set<Element> topLevelElements = new Set<Element>(); |
268 Map<ClassElement, Set<Element>> classMembers = | 274 Map<ClassElement, Set<Element>> classMembers = |
269 new Map<ClassElement, Set<Element>>(); | 275 new Map<ClassElement, Set<Element>>(); |
270 | 276 |
271 // Build all top level elements to emit and necessary class members. | 277 // Build all top level elements to emit and necessary class members. |
272 var newTypedefElementCallback, newClassElementCallback; | 278 var newTypedefElementCallback, newClassElementCallback; |
273 | 279 |
274 void processElement(Element element, ElementAst elementAst) { | 280 void processElement(Element element, ElementAst elementAst) { |
275 ReferencedElementCollector collector = | 281 ReferencedElementCollector collector = |
276 new ReferencedElementCollector(compiler, | 282 new ReferencedElementCollector(compiler, |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
445 } | 451 } |
446 memberNodes[elementAsts[element].ast] = members; | 452 memberNodes[elementAsts[element].ast] = members; |
447 } | 453 } |
448 } | 454 } |
449 | 455 |
450 if (useMirrorHelperLibrary) { | 456 if (useMirrorHelperLibrary) { |
451 mirrorRenamer.addRenames(placeholderRenamer.renames, | 457 mirrorRenamer.addRenames(placeholderRenamer.renames, |
452 topLevelNodes, collector); | 458 topLevelNodes, collector); |
453 } | 459 } |
454 | 460 |
455 final EmitterUnparser unparser = | 461 Map<LibraryElement, String> outputPaths = new Map<LibraryElement, String>(); |
456 new EmitterUnparser(placeholderRenamer.renames, | 462 Map<LibraryElement, EmitterUnparser> unparsers = |
457 stripTypes: forceStripTypes, | 463 new Map<LibraryElement, EmitterUnparser>(); |
458 minify: compiler.enableMinification); | 464 |
459 for (LibraryElement library in placeholderRenamer.platformImports) { | 465 // The single unparser used if we collect all the output in one file |
460 if (library.isPlatformLibrary && !library.isInternalLibrary) { | 466 EmitterUnparser mainUnparser = multiFile |
461 unparser.unparseImportTag(library.canonicalUri.toString()); | 467 ? null |
468 : new EmitterUnparser(placeholderRenamer.renames, | |
469 stripTypes: forceStripTypes, | |
470 minify: compiler.enableMinification); | |
471 | |
472 if (multiFile) { | |
473 String mainName = compiler.outputUri.pathSegments.last; | |
474 String mainBaseName = mainName.endsWith(".dart") | |
475 ? mainName.substring(0, mainName.length - 5) | |
476 : mainName; | |
477 // Map each library to a path based on the uri of the original | |
478 // library and [compiler.outputUri]. | |
479 Set<String> usedLibraryPaths = new Set<String>(); | |
480 for (LibraryElement library in userLibraries) { | |
481 if (library == compiler.mainApp) { | |
482 outputPaths[library] = mainBaseName; | |
483 } else { | |
484 List<String> names = | |
485 library.canonicalUri.pathSegments.last.split("."); | |
486 if (names.last == "dart") { | |
487 names = names.sublist(0, names.length - 1); | |
488 } | |
489 outputPaths[library] = | |
490 "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}"; | |
491 } | |
492 } | |
493 | |
494 for(LibraryElement outputLibrary in userLibraries) { | |
floitsch
2014/08/28 20:10:07
Add comment explaining that you rewrite the import
sigurdm
2014/09/03 08:24:16
Done.
| |
495 EmitterUnparser unparser = new EmitterUnparser( | |
496 placeholderRenamer.renames, | |
497 stripTypes: forceStripTypes, | |
498 minify: compiler.enableMinification); | |
499 unparsers[outputLibrary] = unparser; | |
500 LibraryName libraryName = outputLibrary.libraryTag; | |
501 if (libraryName != null) { | |
502 unparser.visitLibraryName(libraryName); | |
503 } | |
504 for (LibraryTag tag in outputLibrary.tags) { | |
505 if (tag is! LibraryDependency) continue; | |
506 LibraryDependency dependency = tag; | |
507 LibraryElement libraryElement = | |
508 outputLibrary.getLibraryFromTag(dependency); | |
509 String uri = outputPaths.containsKey(libraryElement) | |
510 ? "${outputPaths[libraryElement]}.dart" | |
511 : libraryElement.canonicalUri.toString(); | |
512 if (dependency is Import) { | |
513 unparser.unparseImportTag(uri); | |
514 } else { | |
515 unparser.unparseExportTag(uri); | |
516 } | |
517 } | |
518 } | |
519 } else { | |
520 for(LibraryElement library in placeholderRenamer.platformImports) { | |
521 if (library.isPlatformLibrary && !library.isInternalLibrary) { | |
522 mainUnparser.unparseImportTag(library.canonicalUri.toString()); | |
523 } | |
462 } | 524 } |
463 } | 525 } |
526 | |
464 for (int i = 0; i < sortedTopLevels.length; i++) { | 527 for (int i = 0; i < sortedTopLevels.length; i++) { |
465 Element element = sortedTopLevels[i]; | 528 Element element = sortedTopLevels[i]; |
466 Node node = topLevelNodes[i]; | 529 Node node = topLevelNodes[i]; |
530 Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser; | |
467 if (node is ClassNode) { | 531 if (node is ClassNode) { |
468 // TODO(smok): Filter out default constructors here. | 532 // TODO(smok): Filter out default constructors here. |
469 unparser.unparseClassWithBody(node, memberNodes[node]); | 533 unparser.unparseClassWithBody(node, memberNodes[node]); |
470 } else { | 534 } else { |
471 unparser.unparse(node); | 535 unparser.unparse(node); |
472 } | 536 } |
473 unparser.newline(); | 537 unparser.newline(); |
474 } | 538 } |
475 | 539 |
476 compiler.assembledCode = unparser.result; | 540 if (multiFile) { |
477 compiler.outputProvider("", "dart") | 541 for(LibraryElement outputLibrary in userLibraries) { |
478 ..add(compiler.assembledCode) | 542 compiler.outputProvider(outputPaths[outputLibrary], "dart") |
479 ..close(); | 543 // TODO(sigurdm): Make the unparser output directly into the buffer instead |
floitsch
2014/08/28 20:10:06
Write comment before statement.
sigurdm
2014/09/03 08:24:16
Done.
| |
480 // Output verbose info about size ratio of resulting bundle to all | 544 // of caching in `.result`. |
481 // referenced non-platform sources. | 545 ..add(unparsers[outputLibrary].result) |
482 logResultBundleSizeInfo(topLevelElements); | 546 ..close(); |
547 } | |
548 // TODO(sigurdm): What to do here? Probably we should get rid of | |
floitsch
2014/08/28 20:10:06
Agreed.
Until then we usually write the main unit
sigurdm
2014/09/03 08:24:16
Done.
| |
549 // compiler.assembledCode | |
550 compiler.assembledCode = ""; | |
551 } else { | |
552 compiler.assembledCode = mainUnparser.result; | |
553 compiler.outputProvider("", "dart") | |
554 ..add(compiler.assembledCode) | |
555 ..close(); | |
556 | |
557 // Output verbose info about size ratio of resulting bundle to all | |
558 // referenced non-platform sources. | |
559 logResultBundleSizeInfo(topLevelElements); | |
floitsch
2014/08/28 20:10:07
Can we do something similar?
sigurdm
2014/09/03 08:24:16
Done.
| |
560 } | |
483 } | 561 } |
484 | 562 |
485 void logResultBundleSizeInfo(Set<Element> topLevelElements) { | 563 void logResultBundleSizeInfo(Set<Element> topLevelElements) { |
486 Iterable<LibraryElement> referencedLibraries = | 564 Iterable<LibraryElement> referencedLibraries = |
487 compiler.libraryLoader.libraries.where(isUserLibrary); | 565 compiler.libraryLoader.libraries.where(isUserLibrary); |
488 // Sum total size of scripts in each referenced library. | 566 // Sum total size of scripts in each referenced library. |
489 int nonPlatformSize = 0; | 567 int nonPlatformSize = 0; |
490 for (LibraryElement lib in referencedLibraries) { | 568 for (LibraryElement lib in referencedLibraries) { |
491 for (CompilationUnitElement compilationUnit in lib.compilationUnits) { | 569 for (CompilationUnitElement compilationUnit in lib.compilationUnits) { |
492 nonPlatformSize += compilationUnit.script.file.length; | 570 nonPlatformSize += compilationUnit.script.file.length; |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
694 } | 772 } |
695 | 773 |
696 Constant compileMetadata(MetadataAnnotation metadata, | 774 Constant compileMetadata(MetadataAnnotation metadata, |
697 Node node, | 775 Node node, |
698 TreeElements elements) { | 776 TreeElements elements) { |
699 return measure(() { | 777 return measure(() { |
700 return constantCompiler.compileMetadata(metadata, node, elements); | 778 return constantCompiler.compileMetadata(metadata, node, elements); |
701 }); | 779 }); |
702 } | 780 } |
703 } | 781 } |
OLD | NEW |