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

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

Issue 1879373004: Implement modular compilation (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 8 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/element_helpers.dart ('k') | lib/src/compiler/error_helpers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:collection' show HashMap, HashSet;
6
7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:func/func.dart';
10 import '../js_ast/js_ast.dart' as JS;
11
12 typedef void ModuleItemEmitter(AstNode item);
13
14 /// Helper that tracks order of elements visited by the compiler, detecting
15 /// if the top level item can be loaded eagerly or not.
16 class ElementLoader {
17 /// Whether an item has been loaded (emitted) already.
18 final _loaded = new HashSet<Element>();
19
20 final HashMap<Element, AstNode> _declarationNodes;
21
22 /// 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
24 /// not matter for those.
25 final _topLevelElements = new List<Element>();
26
27 /// The current element being loaded.
28 /// We can use this to determine if we're loading top-level code or not:
29 ///
30 /// _currentElements.last == _topLevelElements.last
31 final _currentElements = new List<Element>();
32
33 bool _checkReferences;
34
35 final ModuleItemEmitter _emitModuleItem;
36
37 ElementLoader(this._emitModuleItem, this._declarationNodes) {
38 assert(!_declarationNodes.containsKey(null));
39 }
40
41 Element get currentElement => _currentElements.last;
42
43 bool isLoaded(Element e) =>
44 !_declarationNodes.containsKey(e) || _loaded.contains(e);
45
46 /// True if the element is currently being loaded.
47 bool _isLoading(Element e) => _currentElements.contains(e);
48
49 /// Start generating top-level code for the element [e].
50 ///
51 /// Subsequent [emitDeclaration] calls will cause those elements to be
52 /// generated before this one, until [finishTopLevel] is called.
53 void startTopLevel(Element e) {
54 assert(identical(e, currentElement));
55 _topLevelElements.add(e);
56 }
57
58 /// Finishes the top-level code for the element [e].
59 void finishTopLevel(Element e) {
60 var last = _topLevelElements.removeLast();
61 assert(identical(e, last));
62 }
63
64 /// Starts recording calls to [declareBeforeUse], until
65 /// [finishCheckingReferences] is called.
66 void startCheckingReferences() {
67 // This function should not be reentrant, and we should not current be
68 // emitting top-level code.
69 assert(_checkReferences == null);
70 assert(_topLevelElements.isEmpty ||
71 !identical(currentElement, _topLevelElements.last));
72 // Assume true until proven otherwise
73 _checkReferences = true;
74 }
75
76 /// Finishes recording references, and returns `true` if all referenced
77 /// items were loaded (or if no items were referenced).
78 bool finishCheckingReferences() {
79 var result = _checkReferences;
80 _checkReferences = null;
81 return result;
82 }
83
84 /// Ensures a top-level declaration is generated, and returns `true` if it
85 /// is part of the current module.
86 void emitDeclaration(Element e) {
87 var node = _declarationNodes[e];
88 if (node == null) return; // not from this module.
89
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);
96
97 _emitModuleItem(node);
98
99 var last = _currentElements.removeLast();
100 assert(identical(e, last));
101 }
102
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;
116 }
117
118 /// To emit top-level module items, we sometimes need to reorder them.
119 ///
120 /// 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
122 /// lazy. All elements need to be aware of this possibility and generate code
123 /// accordingly.
124 ///
125 /// If we are not emitting top-level code, this does nothing, because all
126 /// declarations are assumed to be available before we start execution.
127 /// See [startTopLevel].
128 void declareBeforeUse(Element e) {
129 if (e == null) return;
130
131 if (_checkReferences != null) {
132 _checkReferences = _checkReferences && isLoaded(e) && !_isLoading(e);
133 return;
134 }
135
136 var topLevel = _topLevelElements;
137 if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) {
138 // If the item is from our library, try to emit it now.
139 emitDeclaration(e);
140 }
141 }
142 }
OLDNEW
« no previous file with comments | « lib/src/compiler/element_helpers.dart ('k') | lib/src/compiler/error_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698