Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 /** The entry point for the command-line version analyzer2dart. */ | 5 /** The entry point for the command-line version analyzer2dart. */ |
| 6 library analyzer2dart.cmdline; | 6 library analyzer2dart.cmdline; |
| 7 | 7 |
| 8 import 'package:analyzer/analyzer.dart'; | 8 import 'package:analyzer/analyzer.dart'; |
| 9 import 'package:compiler/implementation/compiler.dart'; | 9 import 'package:analyzer/src/generated/engine.dart'; |
| 10 import 'package:analyzer/src/generated/sdk_io.dart'; | |
| 11 import 'package:analyzer/src/generated/source_io.dart'; | |
| 12 import 'package:analyzer/src/generated/java_io.dart'; | |
| 13 import 'package:analyzer/src/generated/element.dart'; | |
| 14 | |
| 15 class TreeShakingVisitor extends RecursiveAstVisitor { | |
| 16 final TreeShaker treeShaker; | |
| 17 | |
| 18 TreeShakingVisitor(this.treeShaker); | |
| 19 | |
| 20 @override | |
| 21 void visitFunctionDeclaration(FunctionDeclaration node) { | |
| 22 print('Visiting function ${node.name.name}'); | |
| 23 super.visitFunctionDeclaration(node); | |
| 24 } | |
| 25 | |
| 26 @override | |
| 27 void visitMethodInvocation(MethodInvocation node) { | |
| 28 print('Visiting invocation of ${node.methodName.name}'); | |
| 29 Element staticElement = node.methodName.staticElement; | |
| 30 if (staticElement != null) { | |
| 31 // TODO(paulberry): deal with the case where staticElement is | |
| 32 // not necessarily the exact target. (Dart2js calls this a | |
| 33 // "dynamic invocation"). We need a notion of "selector". Maybe | |
| 34 // we can use Dart2js selectors. | |
| 35 treeShaker.add(staticElement); | |
| 36 } else { | |
| 37 // TODO(paulberry): deal with this case. | |
| 38 } | |
| 39 super.visitMethodInvocation(node); | |
| 40 } | |
| 41 | |
| 42 } | |
| 43 | |
| 44 class CpsGeneratingVisitor extends RecursiveAstVisitor { | |
| 45 // TODO(johnniwinther) | |
| 46 } | |
| 47 | |
| 48 class ClosedWorld { | |
| 49 // TODO(paulberry): is it a problem to hold on to all the AST's for the | |
| 50 // duration of tree shaking & CPS generation? | |
| 51 Map<Element, AstNode> elements = <Element, AstNode>{}; | |
| 52 ClosedWorld(); | |
| 53 } | |
| 54 | |
| 55 class TreeShaker { | |
| 56 List<Element> _queue = <Element>[]; | |
| 57 Set<Element> _alreadyEnqueued = new Set<Element>(); | |
|
scheglov
2014/08/28 16:52:49
new HashSet<Element>() ?
| |
| 58 ClosedWorld _world = new ClosedWorld(); | |
| 59 | |
| 60 void add(Element e) { | |
| 61 if (!_alreadyEnqueued.contains(e)) { | |
|
scheglov
2014/08/28 16:52:49
You could use if (!_alreadyEnqueued.add(e)) instea
| |
| 62 _queue.add(e); | |
| 63 _alreadyEnqueued.add(e); | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 ClosedWorld shake(AnalysisContext context) { | |
| 68 while (_queue.isNotEmpty) { | |
| 69 Element e = _queue.removeAt(0); | |
|
scheglov
2014/08/28 16:52:49
List.removeLast() is much faster.
So, if the order
| |
| 70 print('Tree shaker handling $e'); | |
| 71 CompilationUnit compilationUnit = | |
| 72 context.getResolvedCompilationUnit(e.source, e.library); | |
| 73 AstNode identifier = | |
| 74 new NodeLocator.con1(e.nameOffset).searchWithin(compilationUnit); | |
| 75 FunctionDeclaration declaration = | |
| 76 identifier.getAncestor((node) => node is FunctionDeclaration); | |
| 77 _world.elements[e] = declaration; | |
| 78 declaration.accept(new TreeShakingVisitor(this)); | |
| 79 } | |
| 80 print('Tree shaking done'); | |
| 81 return _world; | |
| 82 } | |
| 83 } | |
| 10 | 84 |
| 11 void main(List<String> args) { | 85 void main(List<String> args) { |
| 12 // TODO(brianwilkerson,paulberry): Run the analyzer `args[0]` and provide | 86 // Create the analysis context |
| 13 // access to the element model/ast of the `main` method. | 87 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); |
| 88 | |
| 89 // Set up the source factory. | |
| 90 // TODO(paulberry): do we want to use ExplicitPackageUriResolver? | |
| 91 List<UriResolver> uriResolvers = [ | |
| 92 new FileUriResolver(), | |
| 93 new DartUriResolver(DirectoryBasedDartSdk.defaultSdk) /* , | |
| 94 new PackageUriResolver(packagesDirectories) */ | |
| 95 ]; | |
| 96 context.sourceFactory = new SourceFactory(uriResolvers); | |
| 97 | |
| 98 // Tell the analysis server about the root | |
| 99 JavaFile javaFile = new JavaFile(args[0]); // TODO(paulberry): hacky | |
| 100 Source source = new FileBasedSource.con1(javaFile); | |
| 101 ChangeSet changeSet = new ChangeSet(); | |
| 102 changeSet.addedSources.add(source); | |
| 103 context.applyChanges(changeSet); | |
| 104 | |
| 105 // Get the library element associated with the source. | |
| 106 LibraryElement libraryElement = context.computeLibraryElement(source); | |
| 107 | |
| 108 // Get the resolved AST for main | |
| 109 FunctionElement entryPointElement = libraryElement.entryPoint; | |
| 110 if (entryPointElement == null) { | |
| 111 throw new Exception('No main()!'); | |
| 112 } | |
| 14 | 113 |
| 15 // TODO(brianwilkerson,paulberry,johnniwinther): Perform tree-growing by | 114 // TODO(brianwilkerson,paulberry,johnniwinther): Perform tree-growing by |
| 16 // visiting the ast and feeding the dependencies into a work queue (enqueuer). | 115 // visiting the ast and feeding the dependencies into a work queue (enqueuer). |
| 116 TreeShaker treeShaker = new TreeShaker(); | |
| 117 treeShaker.add(entryPointElement); | |
| 118 ClosedWorld world = treeShaker.shake(context); | |
| 17 | 119 |
| 18 // TODO(brianwilkerson,paulberry,johnniwinther): Convert the ast into cps by | 120 // TODO(brianwilkerson,paulberry,johnniwinther): Convert the ast into cps by |
| 19 // visiting the ast and invoking the ir builder. | 121 // visiting the ast and invoking the ir builder. |
| 122 new CpsGeneratingVisitor(); | |
| 20 | 123 |
| 21 // TODO(johnniwinther): Convert the analyzer element model into the dart2js | 124 // TODO(johnniwinther): Convert the analyzer element model into the dart2js |
| 22 // element model to fit the needs of the cps encoding above. | 125 // element model to fit the needs of the cps encoding above. |
| 23 | 126 |
| 24 // TODO(johnniwinther): Feed the cps ir into the new dart2dart backend to | 127 // TODO(johnniwinther): Feed the cps ir into the new dart2dart backend to |
| 25 // generate dart file(s). | 128 // generate dart file(s). |
| 26 } | 129 } |
| OLD | NEW |