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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/compiler/element_loader.dart
diff --git a/lib/src/compiler/element_loader.dart b/lib/src/compiler/element_loader.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e782103623affc666f93d6881abf65dea7599385
--- /dev/null
+++ b/lib/src/compiler/element_loader.dart
@@ -0,0 +1,142 @@
+// Copyright (c) 2015, 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.
+
+import 'dart:collection' show HashMap, HashSet;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:func/func.dart';
+import '../js_ast/js_ast.dart' as JS;
+
+typedef void ModuleItemEmitter(AstNode item);
+
+/// Helper that tracks order of elements visited by the compiler, detecting
+/// if the top level item can be loaded eagerly or not.
+class ElementLoader {
+ /// Whether an item has been loaded (emitted) already.
+ final _loaded = new HashSet<Element>();
+
+ final HashMap<Element, AstNode> _declarationNodes;
+
+ /// The stack of currently emitting elements, if generating top-level code
+ /// for them. This is not used when inside method bodies, because order does
+ /// not matter for those.
+ final _topLevelElements = new List<Element>();
+
+ /// The current element being loaded.
+ /// We can use this to determine if we're loading top-level code or not:
+ ///
+ /// _currentElements.last == _topLevelElements.last
+ final _currentElements = new List<Element>();
+
+ bool _checkReferences;
+
+ final ModuleItemEmitter _emitModuleItem;
+
+ ElementLoader(this._emitModuleItem, this._declarationNodes) {
+ assert(!_declarationNodes.containsKey(null));
+ }
+
+ Element get currentElement => _currentElements.last;
+
+ bool isLoaded(Element e) =>
+ !_declarationNodes.containsKey(e) || _loaded.contains(e);
+
+ /// True if the element is currently being loaded.
+ bool _isLoading(Element e) => _currentElements.contains(e);
+
+ /// Start generating top-level code for the element [e].
+ ///
+ /// Subsequent [emitDeclaration] calls will cause those elements to be
+ /// generated before this one, until [finishTopLevel] is called.
+ void startTopLevel(Element e) {
+ assert(identical(e, currentElement));
+ _topLevelElements.add(e);
+ }
+
+ /// Finishes the top-level code for the element [e].
+ void finishTopLevel(Element e) {
+ var last = _topLevelElements.removeLast();
+ assert(identical(e, last));
+ }
+
+ /// Starts recording calls to [declareBeforeUse], until
+ /// [finishCheckingReferences] is called.
+ void startCheckingReferences() {
+ // This function should not be reentrant, and we should not current be
+ // emitting top-level code.
+ assert(_checkReferences == null);
+ assert(_topLevelElements.isEmpty ||
+ !identical(currentElement, _topLevelElements.last));
+ // Assume true until proven otherwise
+ _checkReferences = true;
+ }
+
+ /// Finishes recording references, and returns `true` if all referenced
+ /// items were loaded (or if no items were referenced).
+ bool finishCheckingReferences() {
+ var result = _checkReferences;
+ _checkReferences = null;
+ return result;
+ }
+
+ /// Ensures a top-level declaration is generated, and returns `true` if it
+ /// is part of the current module.
+ void emitDeclaration(Element e) {
+ var node = _declarationNodes[e];
+ if (node == null) return; // not from this module.
+
+ // If we already tried to load it, see if we succeeded or not.
+ // Otherwise try and load now.
+ if (_loaded.contains(e)) return;
+
+ _loaded.add(e);
+ _currentElements.add(e);
+
+ _emitModuleItem(node);
+
+ var last = _currentElements.removeLast();
+ assert(identical(e, last));
+ }
+
+ /// Used to immediately emit a declaration and return the result.
+ ///
+ /// This will operate regardless of whether the node is currently loaded.
+ /// We use this when we encounter a getter/setter, to immediately emit the
+ /// pair and combine them.
+ /*=T*/ customEmitDeclaration/*<T extends JS.Node>*/(
+ Element e, Func1<AstNode, JS.Node/*=T*/ > visit) {
+ _loaded.add(e);
+ _currentElements.add(e);
+ var result = visit(_declarationNodes[e]);
+ var last = _currentElements.removeLast();
+ assert(identical(e, last));
+ return result;
+ }
+
+ /// To emit top-level module items, we sometimes need to reorder them.
+ ///
+ /// This function takes care of that, and also detects cases where reordering
+ /// failed, and we need to resort to lazy loading, by marking the element as
+ /// lazy. All elements need to be aware of this possibility and generate code
+ /// accordingly.
+ ///
+ /// If we are not emitting top-level code, this does nothing, because all
+ /// declarations are assumed to be available before we start execution.
+ /// See [startTopLevel].
+ void declareBeforeUse(Element e) {
+ if (e == null) return;
+
+ if (_checkReferences != null) {
+ _checkReferences = _checkReferences && isLoaded(e) && !_isLoading(e);
+ return;
+ }
+
+ var topLevel = _topLevelElements;
+ if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) {
+ // If the item is from our library, try to emit it now.
+ emitDeclaration(e);
+ }
+ }
+}
« 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