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

Unified Diff: pkg/kernel/lib/transformations/closure/context.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/context.dart
diff --git a/pkg/kernel/lib/transformations/closure/context.dart b/pkg/kernel/lib/transformations/closure/context.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3a3495e1aea04876b9755b211af885b076eb25c7
--- /dev/null
+++ b/pkg/kernel/lib/transformations/closure/context.dart
@@ -0,0 +1,248 @@
+// 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.context;
+
+import '../../ast.dart'
+ show
+ Arguments,
+ Class,
+ ConstructorInvocation,
+ Expression,
+ ExpressionStatement,
+ IntLiteral,
+ InterfaceType,
+ MethodInvocation,
+ Name,
+ NullLiteral,
+ PropertyGet,
+ PropertySet,
+ StringLiteral,
+ Throw,
+ VariableDeclaration,
+ VariableGet,
+ VariableSet;
+
+import '../../frontend/accessors.dart'
+ show Accessor, IndexAccessor, VariableAccessor;
+
+import 'converter.dart' show ClosureConverter;
+
+abstract class Context {
+ /// Returns a new expression for accessing this context.
+ Expression get expression;
+
+ /// Returns an accessor (or null) for accessing this context.
+ Accessor get accessor;
+
+ /// Extend the context to include [variable] initialized to [value]. For
+ /// example, this replaces the [VariableDeclaration] node of a captured local
+ /// variable.
+ ///
+ /// This may create a new context and update the `context` field of the
+ /// current [ClosureConverter].
+ // TODO(ahe): Return context instead?
+ void extend(VariableDeclaration variable, Expression value);
+
+ /// Update the initializer [value] of [variable] which was previously added
+ /// with [extend]. This is used when [value] isn't available when the context
+ /// was extended.
+ void update(VariableDeclaration variable, Expression value) {
+ throw "not supported $runtimeType";
+ }
+
+ /// Returns a new expression for reading the value of [variable] from this
+ /// context. For example, for replacing a [VariableGet] of a captured local
+ /// variable.
+ Expression lookup(VariableDeclaration variable);
+
+ /// Returns a new expression which stores [value] in [variable] in this
+ /// context. For example, for replacing a [VariableSet] of a captured local
+ /// variable.
+ Expression assign(VariableDeclaration variable, Expression value,
+ {bool voidContext: false});
+
+ /// Returns a new context whose parent is this context. The optional argument
+ /// [accessor] controls how the nested context access this context. This is
+ /// used, for example, when hoisting a local function. In this case, access
+ /// to this context can't be accessed directly via [expression]. In other
+ /// cases, for example, a for-loop, this context is still in scope and can be
+ /// accessed directly (with [accessor]).
+ Context toNestedContext([Accessor accessor]);
+
+ /// Returns a new expression which will copy this context and store the copy
+ /// in the local variable currently holding this context.
+ Expression clone() {
+ return new Throw(
+ new StringLiteral("Context clone not implemented for ${runtimeType}"));
+ }
+}
+
+class NoContext extends Context {
+ final ClosureConverter converter;
+
+ NoContext(this.converter);
+
+ Expression get expression => new NullLiteral();
+
+ Accessor get accessor => null;
+
+ void extend(VariableDeclaration variable, Expression value) {
+ converter.context = new LocalContext(converter, this)
+ ..extend(variable, value);
+ }
+
+ Expression lookup(VariableDeclaration variable) {
+ throw 'Unbound NoContext.lookup($variable)';
+ }
+
+ Expression assign(VariableDeclaration variable, Expression value,
+ {bool voidContext: false}) {
+ throw 'Unbound NoContext.assign($variable, ...)';
+ }
+
+ Context toNestedContext([Accessor accessor]) {
+ return new NestedContext(
+ converter, accessor, <List<VariableDeclaration>>[]);
+ }
+}
+
+class LocalContext extends Context {
+ final ClosureConverter converter;
+ final Context parent;
+ final VariableDeclaration self;
+ final IntLiteral size;
+ final List<VariableDeclaration> variables = <VariableDeclaration>[];
+ final Map<VariableDeclaration, Arguments> initializers =
+ <VariableDeclaration, Arguments>{};
+
+ LocalContext._internal(this.converter, this.parent, this.self, this.size);
+
+ factory LocalContext(ClosureConverter converter, Context parent) {
+ Class contextClass = converter.contextClass;
+ assert(contextClass.constructors.length == 1);
+ IntLiteral zero = new IntLiteral(0);
+ VariableDeclaration declaration = new VariableDeclaration.forValue(
+ new ConstructorInvocation(
+ contextClass.constructors.first, new Arguments(<Expression>[zero])),
+ type: new InterfaceType(contextClass));
+ declaration.name = "#context";
+ converter.insert(declaration);
+ converter.insert(new ExpressionStatement(new PropertySet(
+ new VariableGet(declaration), new Name('parent'), parent.expression)));
+
+ return new LocalContext._internal(converter, parent, declaration, zero);
+ }
+
+ Expression get expression => accessor.buildSimpleRead();
+
+ Accessor get accessor => new VariableAccessor(self);
+
+ void extend(VariableDeclaration variable, Expression value) {
+ Arguments arguments =
+ new Arguments(<Expression>[new IntLiteral(variables.length), value]);
+ converter.insert(new ExpressionStatement(
+ new MethodInvocation(expression, new Name('[]='), arguments)));
+ ++size.value;
+ variables.add(variable);
+ initializers[variable] = arguments;
+ }
+
+ void update(VariableDeclaration variable, Expression value) {
+ Arguments arguments = initializers[variable];
+ arguments.positional[1] = value;
+ value.parent = arguments;
+ }
+
+ Expression lookup(VariableDeclaration variable) {
+ var index = variables.indexOf(variable);
+ return index == -1
+ ? parent.lookup(variable)
+ : new MethodInvocation(expression, new Name('[]'),
+ new Arguments(<Expression>[new IntLiteral(index)]));
+ }
+
+ Expression assign(VariableDeclaration variable, Expression value,
+ {bool voidContext: false}) {
+ var index = variables.indexOf(variable);
+ return index == -1
+ ? parent.assign(variable, value, voidContext: voidContext)
+ : IndexAccessor
+ .make(expression, new IntLiteral(index), null, null)
+ .buildAssignment(value, voidContext: voidContext);
+ }
+
+ Context toNestedContext([Accessor accessor]) {
+ accessor ??= this.accessor;
+ List<List<VariableDeclaration>> variabless = <List<VariableDeclaration>>[];
+ var current = this;
+ while (current != null && current is! NoContext) {
+ if (current is LocalContext) {
+ variabless.add(current.variables);
+ current = current.parent;
+ } else if (current is NestedContext) {
+ variabless.addAll((current as NestedContext).variabless);
+ current = null;
+ }
+ }
+ return new NestedContext(converter, accessor, variabless);
+ }
+
+ Expression clone() {
+ self.isFinal = false;
+ return new VariableSet(
+ self,
+ new MethodInvocation(
+ new VariableGet(self), new Name("copy"), new Arguments.empty()));
+ }
+}
+
+class NestedContext extends Context {
+ final ClosureConverter converter;
+ final Accessor accessor;
+ final List<List<VariableDeclaration>> variabless;
+
+ NestedContext(this.converter, this.accessor, this.variabless);
+
+ Expression get expression {
+ return accessor?.buildSimpleRead() ?? new NullLiteral();
+ }
+
+ void extend(VariableDeclaration variable, Expression value) {
+ converter.context = new LocalContext(converter, this)
+ ..extend(variable, value);
+ }
+
+ Expression lookup(VariableDeclaration variable) {
+ var context = expression;
+ for (var variables in variabless) {
+ var index = variables.indexOf(variable);
+ if (index != -1) {
+ return new MethodInvocation(context, new Name('[]'),
+ new Arguments(<Expression>[new IntLiteral(index)]));
+ }
+ context = new PropertyGet(context, new Name('parent'));
+ }
+ throw 'Unbound NestedContext.lookup($variable)';
+ }
+
+ Expression assign(VariableDeclaration variable, Expression value,
+ {bool voidContext: false}) {
+ var context = expression;
+ for (var variables in variabless) {
+ var index = variables.indexOf(variable);
+ if (index != -1) {
+ return IndexAccessor
+ .make(context, new IntLiteral(index), null, null)
+ .buildAssignment(value, voidContext: voidContext);
+ }
+ context = new PropertyGet(context, new Name('parent'));
+ }
+ throw 'Unbound NestedContext.lookup($variable)';
+ }
+
+ Context toNestedContext([Accessor accessor]) {
+ return new NestedContext(converter, accessor ?? this.accessor, variabless);
+ }
+}
« no previous file with comments | « pkg/kernel/lib/transformations/closure/clone_without_body.dart ('k') | pkg/kernel/lib/transformations/closure/converter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698