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

Side by Side Diff: lib/src/compiler/element_loader.dart

Issue 1992373002: Simplify ordering of top-level declarations. (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 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 unified diff | Download patch
« no previous file with comments | « lib/src/compiler/code_generator.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 import 'dart:collection' show HashMap, HashSet; 5 import 'dart:collection' show HashMap;
6 6
7 import 'package:analyzer/dart/ast/ast.dart'; 7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/element/element.dart'; 8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:func/func.dart'; 9 import 'package:func/func.dart';
10 import '../js_ast/js_ast.dart' as JS; 10 import '../js_ast/js_ast.dart' as JS;
11 11
12 typedef void ModuleItemEmitter(AstNode item);
13
14 /// Helper that tracks order of elements visited by the compiler, detecting 12 /// Helper that tracks order of elements visited by the compiler, detecting
15 /// if the top level item can be loaded eagerly or not. 13 /// if the top level item can be loaded eagerly or not.
16 class ElementLoader { 14 class ElementLoader {
17 /// Whether an item has been loaded (emitted) already.
18 final _loaded = new HashSet<Element>();
19
20 final HashMap<Element, AstNode> _declarationNodes; 15 final HashMap<Element, AstNode> _declarationNodes;
21 16
22 /// The stack of currently emitting elements, if generating top-level code 17 /// The stack of currently emitting elements, if generating top-level code
23 /// for them. This is not used when inside method bodies, because order does 18 /// for them. This is not used when inside method bodies, because order does
24 /// not matter for those. 19 /// not matter for those.
25 final _topLevelElements = new List<Element>(); 20 final _topLevelElements = new List<Element>();
26 21
27 /// The current element being loaded. 22 /// The current element being loaded.
28 /// We can use this to determine if we're loading top-level code or not: 23 /// We can use this to determine if we're loading top-level code or not:
29 /// 24 ///
30 /// _currentElements.last == _topLevelElements.last 25 /// _currentElements.last == _topLevelElements.last
31 final _currentElements = new List<Element>(); 26 final _currentElements = new List<Element>();
32 27
33 bool _checkReferences; 28 bool _checkReferences;
34 29
35 final ModuleItemEmitter _emitModuleItem; 30 ElementLoader(this._declarationNodes) {
36
37 ElementLoader(this._emitModuleItem, this._declarationNodes) {
38 assert(!_declarationNodes.containsKey(null)); 31 assert(!_declarationNodes.containsKey(null));
39 } 32 }
40 33
41 Element get currentElement => _currentElements.last; 34 Element get currentElement => _currentElements.last;
42 35
43 bool isLoaded(Element e) => 36 bool isLoaded(Element e) => !_declarationNodes.containsKey(e);
44 !_declarationNodes.containsKey(e) || _loaded.contains(e);
45 37
46 /// True if the element is currently being loaded. 38 /// True if the element is currently being loaded.
47 bool _isLoading(Element e) => _currentElements.contains(e); 39 bool _isLoading(Element e) => _currentElements.contains(e);
48 40
49 /// Start generating top-level code for the element [e]. 41 /// Start generating top-level code for the element [e].
50 /// 42 ///
51 /// Subsequent [emitDeclaration] calls will cause those elements to be 43 /// Subsequent [emitDeclaration] calls will cause those elements to be
52 /// generated before this one, until [finishTopLevel] is called. 44 /// generated before this one, until [finishTopLevel] is called.
53 void startTopLevel(Element e) { 45 void startTopLevel(Element e) {
54 assert(identical(e, currentElement)); 46 assert(identical(e, currentElement));
(...skipping 21 matching lines...) Expand all
76 /// Finishes recording references, and returns `true` if all referenced 68 /// Finishes recording references, and returns `true` if all referenced
77 /// items were loaded (or if no items were referenced). 69 /// items were loaded (or if no items were referenced).
78 bool finishCheckingReferences() { 70 bool finishCheckingReferences() {
79 var result = _checkReferences; 71 var result = _checkReferences;
80 _checkReferences = null; 72 _checkReferences = null;
81 return result; 73 return result;
82 } 74 }
83 75
84 /// Ensures a top-level declaration is generated, and returns `true` if it 76 /// Ensures a top-level declaration is generated, and returns `true` if it
85 /// is part of the current module. 77 /// is part of the current module.
86 void emitDeclaration(Element e) { 78 /*=T*/ emitDeclaration/*<T extends JS.Node>*/(
87 var node = _declarationNodes[e]; 79 Element e, Func1<AstNode, JS.Node/*=T*/ > visit) {
88 if (node == null) return; // not from this module. 80 var node = _declarationNodes.remove(e);
81 if (node == null) return null; // not from this module or already loaded.
89 82
90 // If we already tried to load it, see if we succeeded or not.
91 // Otherwise try and load now.
92 if (_loaded.contains(e)) return;
93
94 _loaded.add(e);
95 _currentElements.add(e); 83 _currentElements.add(e);
96 84
97 _emitModuleItem(node); 85 var result = visit(node);
98 86
99 var last = _currentElements.removeLast(); 87 var last = _currentElements.removeLast();
100 assert(identical(e, last)); 88 assert(identical(e, last));
101 }
102 89
103 /// Used to immediately emit a declaration and return the result.
104 ///
105 /// This will operate regardless of whether the node is currently loaded.
106 /// We use this when we encounter a getter/setter, to immediately emit the
107 /// pair and combine them.
108 /*=T*/ customEmitDeclaration/*<T extends JS.Node>*/(
109 Element e, Func1<AstNode, JS.Node/*=T*/ > visit) {
110 _loaded.add(e);
111 _currentElements.add(e);
112 var result = visit(_declarationNodes[e]);
113 var last = _currentElements.removeLast();
114 assert(identical(e, last));
115 return result; 90 return result;
116 } 91 }
117 92
118 /// To emit top-level module items, we sometimes need to reorder them. 93 /// To emit top-level module items, we sometimes need to reorder them.
119 /// 94 ///
120 /// This function takes care of that, and also detects cases where reordering 95 /// This function takes care of that, and also detects cases where reordering
121 /// failed, and we need to resort to lazy loading, by marking the element as 96 /// failed, and we need to resort to lazy loading, by marking the element as
122 /// lazy. All elements need to be aware of this possibility and generate code 97 /// lazy. All elements need to be aware of this possibility and generate code
123 /// accordingly. 98 /// accordingly.
124 /// 99 ///
125 /// If we are not emitting top-level code, this does nothing, because all 100 /// If we are not emitting top-level code, this does nothing, because all
126 /// declarations are assumed to be available before we start execution. 101 /// declarations are assumed to be available before we start execution.
127 /// See [startTopLevel]. 102 /// See [startTopLevel].
128 void declareBeforeUse(Element e) { 103 void declareBeforeUse(Element e, VoidFunc1<Element> emit) {
129 if (e == null) return; 104 if (e == null) return;
130 105
131 if (_checkReferences != null) { 106 if (_checkReferences != null) {
132 _checkReferences = _checkReferences && isLoaded(e) && !_isLoading(e); 107 _checkReferences = _checkReferences && isLoaded(e) && !_isLoading(e);
133 return; 108 return;
134 } 109 }
135 110
136 var topLevel = _topLevelElements; 111 var topLevel = _topLevelElements;
137 if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) { 112 if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) {
138 // If the item is from our library, try to emit it now. 113 // If the item is from our library, try to emit it now.
139 emitDeclaration(e); 114 emit(e);
140 } 115 }
141 } 116 }
142 } 117 }
OLDNEW
« no previous file with comments | « lib/src/compiler/code_generator.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698