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

Unified Diff: pkg/kernel/lib/transformations/closure/info.dart

Issue 2561723003: Merge kernel closure conversion into the Dart SDK (Closed)
Patch Set: Remove path constraint Created 4 years 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
Index: pkg/kernel/lib/transformations/closure/info.dart
diff --git a/pkg/kernel/lib/transformations/closure/info.dart b/pkg/kernel/lib/transformations/closure/info.dart
new file mode 100644
index 0000000000000000000000000000000000000000..acbb3d21535b93c87b12223e41267d102f153623
--- /dev/null
+++ b/pkg/kernel/lib/transformations/closure/info.dart
@@ -0,0 +1,206 @@
+// Copyright (c) 2016, 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.
+
+library kernel.transformations.closure.info;
+
+import '../../ast.dart'
+ show
+ Class,
+ Constructor,
+ Field,
+ FunctionDeclaration,
+ FunctionNode,
+ Member,
+ Name,
+ Procedure,
+ ProcedureKind,
+ PropertyGet,
+ ThisExpression,
+ TypeParameter,
+ TypeParameterType,
+ VariableDeclaration,
+ VariableGet,
+ VariableSet;
+
+import '../../visitor.dart' show RecursiveVisitor;
+
+class ClosureInfo extends RecursiveVisitor {
+ FunctionNode currentFunction;
+ final Map<VariableDeclaration, FunctionNode> function =
+ <VariableDeclaration, FunctionNode>{};
+
+ final Set<VariableDeclaration> variables = new Set<VariableDeclaration>();
+
+ final Map<FunctionNode, Set<TypeParameter>> typeVariables =
+ <FunctionNode, Set<TypeParameter>>{};
+
+ /// Map from members to synthetic variables for accessing `this` in a local
+ /// function.
+ final Map<FunctionNode, VariableDeclaration> thisAccess =
+ <FunctionNode, VariableDeclaration>{};
+
+ final Set<String> currentMemberLocalNames = new Set<String>();
+
+ final Map<FunctionNode, String> localNames = <FunctionNode, String>{};
+
+ /// Contains all names used as getter through a [PropertyGet].
+ final Set<Name> invokedGetters = new Set<Name>();
+
+ /// Contains all names of declared regular instance methods (not including
+ /// accessors and operators).
+ final Set<Name> declaredInstanceMethodNames = new Set<Name>();
+
+ Class currentClass;
+
+ Member currentMember;
+
+ FunctionNode currentMemberFunction;
+
+ bool get isOuterMostContext {
+ return currentFunction == null || currentMemberFunction == currentFunction;
+ }
+
+ /// Maps the names of all instance methods that may be torn off (aka
+ /// implicitly closurized) to `${name.name}#get`.
+ Map<Name, Name> get tearOffGetterNames {
+ Map<Name, Name> result = <Name, Name>{};
+ for (Name name in declaredInstanceMethodNames) {
+ if (invokedGetters.contains(name)) {
+ result[name] = new Name("${name.name}#get", name.library);
+ }
+ }
+ return result;
+ }
+
+ void beginMember(Member member, [FunctionNode function]) {
+ currentMemberLocalNames.clear();
+ if (function != null) {
+ localNames[function] = computeUniqueLocalName(member.name.name);
+ }
+ currentMember = member;
+ currentMemberFunction = function;
+ }
+
+ void endMember() {
+ currentMember = null;
+ currentMemberFunction = null;
+ }
+
+ visitClass(Class node) {
+ currentClass = node;
+ super.visitClass(node);
+ currentClass = null;
+ }
+
+ visitConstructor(Constructor node) {
+ beginMember(node, node.function);
+ super.visitConstructor(node);
+ endMember();
+ }
+
+ visitProcedure(Procedure node) {
+ beginMember(node, node.function);
+ if (node.isInstanceMember && node.kind == ProcedureKind.Method) {
+ // Ignore the `length` method of [File] subclasses for now, as they
+ // will force us to rename the `length` getter (kernel issue #43).
+ // TODO(ahe): remove this condition.
+ Class parent = node.parent;
+ if (node.name.name != "length" ||
+ parent.enclosingLibrary.importUri.toString() != "dart:io") {
+ declaredInstanceMethodNames.add(node.name);
+ }
+ }
+ super.visitProcedure(node);
+ endMember();
+ }
+
+ visitField(Field node) {
+ beginMember(node);
+ super.visitField(node);
+ endMember();
+ }
+
+ String computeUniqueLocalName([String name]) {
+ if (name == null || name.isEmpty) {
+ name = "function";
+ }
+ if (currentFunction == null) {
+ if (currentMember != null) {
+ name = "${currentMember.name.name}#$name";
+ }
+ if (currentClass != null) {
+ name = "${currentClass.name}#$name";
+ }
+ } else {
+ name = "${localNames[currentFunction]}#$name";
+ }
+ int count = 1;
+ String candidate = name;
+ while (currentMemberLocalNames.contains(candidate)) {
+ candidate = "$name#${count++}";
+ }
+ currentMemberLocalNames.add(candidate);
+ return candidate;
+ }
+
+ visitFunctionDeclaration(FunctionDeclaration node) {
+ assert(!localNames.containsKey(node));
+ localNames[node.function] = computeUniqueLocalName(node.variable.name);
+ return super.visitFunctionDeclaration(node);
+ }
+
+ visitFunctionNode(FunctionNode node) {
+ localNames.putIfAbsent(node, computeUniqueLocalName);
+ var saved = currentFunction;
+ currentFunction = node;
+ node.visitChildren(this);
+ currentFunction = saved;
+ Set<TypeParameter> capturedTypeVariables = typeVariables[node];
+ if (capturedTypeVariables != null && !isOuterMostContext) {
+ // Propagate captured type variables to enclosing function.
+ typeVariables
+ .putIfAbsent(currentFunction, () => new Set<TypeParameter>())
+ .addAll(capturedTypeVariables);
+ }
+ }
+
+ visitVariableDeclaration(VariableDeclaration node) {
+ function[node] = currentFunction;
+ node.visitChildren(this);
+ }
+
+ visitVariableGet(VariableGet node) {
+ if (function[node.variable] != currentFunction) {
+ variables.add(node.variable);
+ }
+ node.visitChildren(this);
+ }
+
+ visitVariableSet(VariableSet node) {
+ if (function[node.variable] != currentFunction) {
+ variables.add(node.variable);
+ }
+ node.visitChildren(this);
+ }
+
+ visitTypeParameterType(TypeParameterType node) {
+ if (!isOuterMostContext) {
+ typeVariables
+ .putIfAbsent(currentFunction, () => new Set<TypeParameter>())
+ .add(node.parameter);
+ }
+ }
+
+ visitThisExpression(ThisExpression node) {
+ if (!isOuterMostContext) {
+ thisAccess.putIfAbsent(
+ currentMemberFunction, () => new VariableDeclaration("#self"));
+ }
+ }
+
+ visitPropertyGet(PropertyGet node) {
+ invokedGetters.add(node.name);
+ super.visitPropertyGet(node);
+ }
+}
« no previous file with comments | « pkg/kernel/lib/transformations/closure/converter.dart ('k') | pkg/kernel/lib/transformations/closure/mock.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698