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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, 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 library kernel.transformations.closure.context;
6
7 import '../../ast.dart'
8 show
9 Arguments,
10 Class,
11 ConstructorInvocation,
12 Expression,
13 ExpressionStatement,
14 IntLiteral,
15 InterfaceType,
16 MethodInvocation,
17 Name,
18 NullLiteral,
19 PropertyGet,
20 PropertySet,
21 StringLiteral,
22 Throw,
23 VariableDeclaration,
24 VariableGet,
25 VariableSet;
26
27 import '../../frontend/accessors.dart'
28 show Accessor, IndexAccessor, VariableAccessor;
29
30 import 'converter.dart' show ClosureConverter;
31
32 abstract class Context {
33 /// Returns a new expression for accessing this context.
34 Expression get expression;
35
36 /// Returns an accessor (or null) for accessing this context.
37 Accessor get accessor;
38
39 /// Extend the context to include [variable] initialized to [value]. For
40 /// example, this replaces the [VariableDeclaration] node of a captured local
41 /// variable.
42 ///
43 /// This may create a new context and update the `context` field of the
44 /// current [ClosureConverter].
45 // TODO(ahe): Return context instead?
46 void extend(VariableDeclaration variable, Expression value);
47
48 /// Update the initializer [value] of [variable] which was previously added
49 /// with [extend]. This is used when [value] isn't available when the context
50 /// was extended.
51 void update(VariableDeclaration variable, Expression value) {
52 throw "not supported $runtimeType";
53 }
54
55 /// Returns a new expression for reading the value of [variable] from this
56 /// context. For example, for replacing a [VariableGet] of a captured local
57 /// variable.
58 Expression lookup(VariableDeclaration variable);
59
60 /// Returns a new expression which stores [value] in [variable] in this
61 /// context. For example, for replacing a [VariableSet] of a captured local
62 /// variable.
63 Expression assign(VariableDeclaration variable, Expression value,
64 {bool voidContext: false});
65
66 /// Returns a new context whose parent is this context. The optional argument
67 /// [accessor] controls how the nested context access this context. This is
68 /// used, for example, when hoisting a local function. In this case, access
69 /// to this context can't be accessed directly via [expression]. In other
70 /// cases, for example, a for-loop, this context is still in scope and can be
71 /// accessed directly (with [accessor]).
72 Context toNestedContext([Accessor accessor]);
73
74 /// Returns a new expression which will copy this context and store the copy
75 /// in the local variable currently holding this context.
76 Expression clone() {
77 return new Throw(
78 new StringLiteral("Context clone not implemented for ${runtimeType}"));
79 }
80 }
81
82 class NoContext extends Context {
83 final ClosureConverter converter;
84
85 NoContext(this.converter);
86
87 Expression get expression => new NullLiteral();
88
89 Accessor get accessor => null;
90
91 void extend(VariableDeclaration variable, Expression value) {
92 converter.context = new LocalContext(converter, this)
93 ..extend(variable, value);
94 }
95
96 Expression lookup(VariableDeclaration variable) {
97 throw 'Unbound NoContext.lookup($variable)';
98 }
99
100 Expression assign(VariableDeclaration variable, Expression value,
101 {bool voidContext: false}) {
102 throw 'Unbound NoContext.assign($variable, ...)';
103 }
104
105 Context toNestedContext([Accessor accessor]) {
106 return new NestedContext(
107 converter, accessor, <List<VariableDeclaration>>[]);
108 }
109 }
110
111 class LocalContext extends Context {
112 final ClosureConverter converter;
113 final Context parent;
114 final VariableDeclaration self;
115 final IntLiteral size;
116 final List<VariableDeclaration> variables = <VariableDeclaration>[];
117 final Map<VariableDeclaration, Arguments> initializers =
118 <VariableDeclaration, Arguments>{};
119
120 LocalContext._internal(this.converter, this.parent, this.self, this.size);
121
122 factory LocalContext(ClosureConverter converter, Context parent) {
123 Class contextClass = converter.contextClass;
124 assert(contextClass.constructors.length == 1);
125 IntLiteral zero = new IntLiteral(0);
126 VariableDeclaration declaration = new VariableDeclaration.forValue(
127 new ConstructorInvocation(
128 contextClass.constructors.first, new Arguments(<Expression>[zero])),
129 type: new InterfaceType(contextClass));
130 declaration.name = "#context";
131 converter.insert(declaration);
132 converter.insert(new ExpressionStatement(new PropertySet(
133 new VariableGet(declaration), new Name('parent'), parent.expression)));
134
135 return new LocalContext._internal(converter, parent, declaration, zero);
136 }
137
138 Expression get expression => accessor.buildSimpleRead();
139
140 Accessor get accessor => new VariableAccessor(self);
141
142 void extend(VariableDeclaration variable, Expression value) {
143 Arguments arguments =
144 new Arguments(<Expression>[new IntLiteral(variables.length), value]);
145 converter.insert(new ExpressionStatement(
146 new MethodInvocation(expression, new Name('[]='), arguments)));
147 ++size.value;
148 variables.add(variable);
149 initializers[variable] = arguments;
150 }
151
152 void update(VariableDeclaration variable, Expression value) {
153 Arguments arguments = initializers[variable];
154 arguments.positional[1] = value;
155 value.parent = arguments;
156 }
157
158 Expression lookup(VariableDeclaration variable) {
159 var index = variables.indexOf(variable);
160 return index == -1
161 ? parent.lookup(variable)
162 : new MethodInvocation(expression, new Name('[]'),
163 new Arguments(<Expression>[new IntLiteral(index)]));
164 }
165
166 Expression assign(VariableDeclaration variable, Expression value,
167 {bool voidContext: false}) {
168 var index = variables.indexOf(variable);
169 return index == -1
170 ? parent.assign(variable, value, voidContext: voidContext)
171 : IndexAccessor
172 .make(expression, new IntLiteral(index), null, null)
173 .buildAssignment(value, voidContext: voidContext);
174 }
175
176 Context toNestedContext([Accessor accessor]) {
177 accessor ??= this.accessor;
178 List<List<VariableDeclaration>> variabless = <List<VariableDeclaration>>[];
179 var current = this;
180 while (current != null && current is! NoContext) {
181 if (current is LocalContext) {
182 variabless.add(current.variables);
183 current = current.parent;
184 } else if (current is NestedContext) {
185 variabless.addAll((current as NestedContext).variabless);
186 current = null;
187 }
188 }
189 return new NestedContext(converter, accessor, variabless);
190 }
191
192 Expression clone() {
193 self.isFinal = false;
194 return new VariableSet(
195 self,
196 new MethodInvocation(
197 new VariableGet(self), new Name("copy"), new Arguments.empty()));
198 }
199 }
200
201 class NestedContext extends Context {
202 final ClosureConverter converter;
203 final Accessor accessor;
204 final List<List<VariableDeclaration>> variabless;
205
206 NestedContext(this.converter, this.accessor, this.variabless);
207
208 Expression get expression {
209 return accessor?.buildSimpleRead() ?? new NullLiteral();
210 }
211
212 void extend(VariableDeclaration variable, Expression value) {
213 converter.context = new LocalContext(converter, this)
214 ..extend(variable, value);
215 }
216
217 Expression lookup(VariableDeclaration variable) {
218 var context = expression;
219 for (var variables in variabless) {
220 var index = variables.indexOf(variable);
221 if (index != -1) {
222 return new MethodInvocation(context, new Name('[]'),
223 new Arguments(<Expression>[new IntLiteral(index)]));
224 }
225 context = new PropertyGet(context, new Name('parent'));
226 }
227 throw 'Unbound NestedContext.lookup($variable)';
228 }
229
230 Expression assign(VariableDeclaration variable, Expression value,
231 {bool voidContext: false}) {
232 var context = expression;
233 for (var variables in variabless) {
234 var index = variables.indexOf(variable);
235 if (index != -1) {
236 return IndexAccessor
237 .make(context, new IntLiteral(index), null, null)
238 .buildAssignment(value, voidContext: voidContext);
239 }
240 context = new PropertyGet(context, new Name('parent'));
241 }
242 throw 'Unbound NestedContext.lookup($variable)';
243 }
244
245 Context toNestedContext([Accessor accessor]) {
246 return new NestedContext(converter, accessor ?? this.accessor, variabless);
247 }
248 }
OLDNEW
« 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