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

Side by Side Diff: pkg/kernel/lib/transformations/closure/context.dart

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

Powered by Google App Engine
This is Rietveld 408576698