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

Side by Side Diff: lib/transformations/continuation.dart

Issue 2460373002: Remove BlockExpression from the Kernel language. (Closed)
Patch Set: Incorporate review comments, format continuation.dart. Created 4 years, 1 month 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
« no previous file with comments | « lib/transformations/async.dart ('k') | lib/type_propagation/builder.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library kernel.transformations.continuation; 5 library kernel.transformations.continuation;
6 6
7 import 'dart:math' as math; 7 import 'dart:math' as math;
8 8
9 import '../ast.dart'; 9 import '../ast.dart';
10 import '../visitor.dart'; 10 import '../visitor.dart';
11 11
12 import 'async.dart'; 12 import 'async.dart';
13 13
14 Program transformProgram(Program program) { 14 Program transformProgram(Program program) {
15 var helper = new HelperNodes.fromProgram(program); 15 var helper = new HelperNodes.fromProgram(program);
16 var rewriter = new RecursiveContinuationRewriter(helper); 16 var rewriter = new RecursiveContinuationRewriter(helper);
17 return rewriter.rewriteProgram(program); 17 return rewriter.rewriteProgram(program);
18 } 18 }
19 19
20 class RecursiveContinuationRewriter extends Transformer { 20 class RecursiveContinuationRewriter extends Transformer {
21 final HelperNodes helper; 21 final HelperNodes helper;
22 final VariableDeclaration asyncJumpVariable = 22 final VariableDeclaration asyncJumpVariable = new VariableDeclaration(
23 new VariableDeclaration(":await_jump_var", initializer: new IntLiteral(0)) ; 23 ":await_jump_var",
24 initializer: new IntLiteral(0));
24 final VariableDeclaration asyncContextVariable = 25 final VariableDeclaration asyncContextVariable =
25 new VariableDeclaration(":await_ctx_var"); 26 new VariableDeclaration(":await_ctx_var");
26 27
27 RecursiveContinuationRewriter(this.helper); 28 RecursiveContinuationRewriter(this.helper);
28 29
29 Program rewriteProgram(Program node) { 30 Program rewriteProgram(Program node) {
30 return node.accept(this); 31 return node.accept(this);
31 } 32 }
32 33
33 visitFunctionNode(FunctionNode node) { 34 visitFunctionNode(FunctionNode node) {
34 switch (node.asyncMarker) { 35 switch (node.asyncMarker) {
35 case AsyncMarker.Sync: 36 case AsyncMarker.Sync:
36 return super.visitFunctionNode(node); 37 case AsyncMarker.SyncYielding:
38 node.transformChildren(new RecursiveContinuationRewriter(helper));
39 return node;
37 case AsyncMarker.SyncStar: 40 case AsyncMarker.SyncStar:
38 return new SyncStarFunctionRewriter(helper, node).rewrite(); 41 return new SyncStarFunctionRewriter(helper, node).rewrite();
39 case AsyncMarker.Async: 42 case AsyncMarker.Async:
40 return new AsyncFunctionRewriter(helper, node).rewrite(); 43 return new AsyncFunctionRewriter(helper, node).rewrite();
41 case AsyncMarker.AsyncStar: 44 case AsyncMarker.AsyncStar:
42 return new AsyncStarFunctionRewriter(helper, node).rewrite(); 45 return new AsyncStarFunctionRewriter(helper, node).rewrite();
43 case AsyncMarker.SyncYielding:
44 return super.visitFunctionNode(node);
45 } 46 }
46 } 47 }
47 } 48 }
48 49
49 abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter { 50 abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
50 final FunctionNode enclosingFunction; 51 final FunctionNode enclosingFunction;
51 52
52 int currentTryDepth; // Nesting depth for try-blocks. 53 int currentTryDepth; // Nesting depth for try-blocks.
53 int currentCatchDepth = 0; // Nesting depth for catch-blocks. 54 int currentCatchDepth = 0; // Nesting depth for catch-blocks.
54 int capturedTryDepth = 0; // Deepest yield point within a try-block. 55 int capturedTryDepth = 0; // Deepest yield point within a try-block.
55 int capturedCatchDepth = 0; // Deepest yield point within a catch-block. 56 int capturedCatchDepth = 0; // Deepest yield point within a catch-block.
56 57
57 ContinuationRewriterBase(HelperNodes helper, 58 ContinuationRewriterBase(HelperNodes helper, this.enclosingFunction,
58 this.enclosingFunction, 59 {this.currentTryDepth: 0})
59 {this.currentTryDepth: 0})
60 : super(helper); 60 : super(helper);
61 61
62 Statement createContinuationPoint([value]) { 62 Statement createContinuationPoint([Expression value]) {
63 if (value == null) value = new NullLiteral(); 63 if (value == null) value = new NullLiteral();
64 capturedTryDepth = math.max(capturedTryDepth, currentTryDepth); 64 capturedTryDepth = math.max(capturedTryDepth, currentTryDepth);
65 capturedCatchDepth = math.max(capturedCatchDepth, currentCatchDepth); 65 capturedCatchDepth = math.max(capturedCatchDepth, currentCatchDepth);
66 return new YieldStatement(value, isNative: true); 66 return new YieldStatement(value, isNative: true);
67 } 67 }
68 68
69 TreeNode visitTryCatch(TryCatch node) { 69 TreeNode visitTryCatch(TryCatch node) {
70 if (node.body != null) { 70 if (node.body != null) {
71 currentTryDepth++; 71 currentTryDepth++;
72 node.body = node.body.accept(this); 72 node.body = node.body.accept(this);
(...skipping 15 matching lines...) Expand all
88 currentTryDepth--; 88 currentTryDepth--;
89 } 89 }
90 if (node.finalizer != null) { 90 if (node.finalizer != null) {
91 node.finalizer = node.finalizer.accept(this); 91 node.finalizer = node.finalizer.accept(this);
92 node.finalizer?.parent = node; 92 node.finalizer?.parent = node;
93 } 93 }
94 return node; 94 return node;
95 } 95 }
96 96
97 Iterable<VariableDeclaration> createCapturedTryVariables() => 97 Iterable<VariableDeclaration> createCapturedTryVariables() =>
98 new Iterable.generate(capturedTryDepth, (depth) => 98 new Iterable.generate(capturedTryDepth,
99 new VariableDeclaration(":saved_try_context_var${depth}")); 99 (depth) => new VariableDeclaration(":saved_try_context_var${depth}"));
100 100
101 Iterable<VariableDeclaration> createCapturedCatchVariables() => 101 Iterable<VariableDeclaration> createCapturedCatchVariables() =>
102 new Iterable.generate(capturedCatchDepth).expand((depth) => [ 102 new Iterable.generate(capturedCatchDepth).expand((depth) => [
103 new VariableDeclaration(":exception${depth}"), 103 new VariableDeclaration(":exception${depth}"),
104 new VariableDeclaration(":stack_trace${depth}"), 104 new VariableDeclaration(":stack_trace${depth}"),
105 ]); 105 ]);
106 106
107 List<VariableDeclaration> variableDeclarations() => 107 List<VariableDeclaration> variableDeclarations() =>
108 [asyncJumpVariable, asyncContextVariable] 108 [asyncJumpVariable, asyncContextVariable]
109 ..addAll(createCapturedTryVariables()) 109 ..addAll(createCapturedTryVariables())
110 ..addAll(createCapturedCatchVariables()); 110 ..addAll(createCapturedCatchVariables());
111 } 111 }
112 112
113 class SyncStarFunctionRewriter extends ContinuationRewriterBase { 113 class SyncStarFunctionRewriter extends ContinuationRewriterBase {
114 final VariableDeclaration iteratorVariable = 114 final VariableDeclaration iteratorVariable =
115 new VariableDeclaration(":iterator"); 115 new VariableDeclaration(":iterator");
116 116
117 SyncStarFunctionRewriter(helper, enclosingFunction) 117 SyncStarFunctionRewriter(helper, enclosingFunction)
118 : super(helper, enclosingFunction); 118 : super(helper, enclosingFunction);
119 119
120 FunctionNode rewrite() { 120 FunctionNode rewrite() {
121 // :sync_body(:iterator) { 121 // :sync_body(:iterator) {
122 // modified <node.body>; 122 // modified <node.body>;
123 // } 123 // }
124 final nestedClosureVariable = new VariableDeclaration(":sync_op"); 124 final nestedClosureVariable = new VariableDeclaration(":sync_op");
125 final function = new FunctionNode( 125 final function = new FunctionNode(buildClosureBody(),
126 buildClosureBody(),
127 positionalParameters: [iteratorVariable], 126 positionalParameters: [iteratorVariable],
128 requiredParameterCount: 1, 127 requiredParameterCount: 1,
129 asyncMarker: AsyncMarker.SyncYielding); 128 asyncMarker: AsyncMarker.SyncYielding);
130 final closureFunction = 129 final closureFunction =
131 new FunctionDeclaration(nestedClosureVariable, function); 130 new FunctionDeclaration(nestedClosureVariable, function);
132 131
133 // return new _SyncIterable(:sync_body); 132 // return new _SyncIterable(:sync_body);
134 final arguments = new Arguments([new VariableGet(nestedClosureVariable)]); 133 final arguments = new Arguments([new VariableGet(nestedClosureVariable)]);
135 final returnStatement = new ReturnStatement(new ConstructorInvocation( 134 final returnStatement = new ReturnStatement(
136 helper.syncIterableConstructor, arguments)); 135 new ConstructorInvocation(helper.syncIterableConstructor, arguments));
137 136
138 enclosingFunction.body = new Block([] 137 enclosingFunction.body = new Block([]
139 ..addAll(variableDeclarations()) 138 ..addAll(variableDeclarations())
140 ..addAll([closureFunction, returnStatement])); 139 ..addAll([closureFunction, returnStatement]));
141 enclosingFunction.body.parent = enclosingFunction; 140 enclosingFunction.body.parent = enclosingFunction;
142 enclosingFunction.asyncMarker = AsyncMarker.Sync; 141 enclosingFunction.asyncMarker = AsyncMarker.Sync;
143 return enclosingFunction; 142 return enclosingFunction;
144 } 143 }
145 144
146 Statement buildClosureBody() { 145 Statement buildClosureBody() {
147 // The body will insert calls to 146 // The body will insert calls to
148 // :iterator.current_= 147 // :iterator.current_=
149 // :iterator.isYieldEach= 148 // :iterator.isYieldEach=
150 // and return `true` as long as it did something and `false` when it's done. 149 // and return `true` as long as it did something and `false` when it's done.
151 return enclosingFunction.body.accept(this); 150 return enclosingFunction.body.accept(this);
152 } 151 }
153 152
154 visitYieldStatement(YieldStatement node) { 153 visitYieldStatement(YieldStatement node) {
155 var transformedExpression = node.expression.accept(this); 154 var transformedExpression = node.expression.accept(this);
156 155
157 var statements = []; 156 var statements = [];
158 if (node.isYieldStar) { 157 if (node.isYieldStar) {
159 var markYieldEach = new ExpressionStatement(new PropertySet( 158 var markYieldEach = new ExpressionStatement(new PropertySet(
160 new VariableGet(iteratorVariable), 159 new VariableGet(iteratorVariable),
161 new Name("isYieldEach", helper.coreLibrary), 160 new Name("isYieldEach", helper.coreLibrary),
162 new BoolLiteral(true))); 161 new BoolLiteral(true)));
163 statements.add(markYieldEach); 162 statements.add(markYieldEach);
164 } 163 }
165 164
166 var setCurrentIteratorValue = new ExpressionStatement(new PropertySet( 165 var setCurrentIteratorValue = new ExpressionStatement(new PropertySet(
167 new VariableGet(iteratorVariable), 166 new VariableGet(iteratorVariable),
168 new Name("_current", helper.coreLibrary), 167 new Name("_current", helper.coreLibrary),
169 transformedExpression)); 168 transformedExpression));
170 169
171 statements.add(setCurrentIteratorValue); 170 statements.add(setCurrentIteratorValue);
172 statements.add(createContinuationPoint(new BoolLiteral(true))); 171 statements.add(createContinuationPoint(new BoolLiteral(true)));
173 return new Block(statements); 172 return new Block(statements);
174 } 173 }
175 } 174 }
176 175
177 abstract class AsyncRewriterBase extends ContinuationRewriterBase { 176 abstract class AsyncRewriterBase extends ContinuationRewriterBase {
178 final VariableDeclaration nestedClosureVariable = 177 final VariableDeclaration nestedClosureVariable =
179 new VariableDeclaration(":async_op"); 178 new VariableDeclaration(":async_op");
180 final VariableDeclaration thenContinuationVariable = 179 final VariableDeclaration thenContinuationVariable =
181 new VariableDeclaration(":async_op_then"); 180 new VariableDeclaration(":async_op_then");
182 final VariableDeclaration catchErrorContinuationVariable = 181 final VariableDeclaration catchErrorContinuationVariable =
183 new VariableDeclaration(":async_op_error"); 182 new VariableDeclaration(":async_op_error");
184 183
185 ExpressionLifter expressionRewriter; 184 ExpressionLifter expressionRewriter;
186 185
187 AsyncRewriterBase(helper, enclosingFunction) 186 AsyncRewriterBase(helper, enclosingFunction)
188 // Body is wrapped in the try-catch so initial currentTryDepth is 1. 187 // Body is wrapped in the try-catch so initial currentTryDepth is 1.
189 : super(helper, enclosingFunction, currentTryDepth: 1) { 188 : super(helper, enclosingFunction, currentTryDepth: 1) {}
190 }
191 189
192 setupAsyncContinuations(List<Statement> statements) { 190 void setupAsyncContinuations(List<Statement> statements) {
193 expressionRewriter = new ExpressionLifter(this); 191 expressionRewriter = new ExpressionLifter(this);
194 192
195 // var :async_op_then; 193 // var :async_op_then;
196 statements.add(thenContinuationVariable); 194 statements.add(thenContinuationVariable);
197 195
198 // var :async_op_error; 196 // var :async_op_error;
199 statements.add(catchErrorContinuationVariable); 197 statements.add(catchErrorContinuationVariable);
200 198
201 // :async_op([:result, :exception, :stack_trace]) { 199 // :async_op([:result, :exception, :stack_trace]) {
202 // modified <node.body>; 200 // modified <node.body>;
203 // } 201 // }
204 final parameters = [ 202 final parameters = <VariableDeclaration>[
205 expressionRewriter.asyncResult, 203 expressionRewriter.asyncResult,
206 new VariableDeclaration(':exception'), 204 new VariableDeclaration(':exception'),
207 new VariableDeclaration(':stack_trace'), 205 new VariableDeclaration(':stack_trace'),
208 ]; 206 ];
209 final function = new FunctionNode( 207 final function = new FunctionNode(buildWrappedBody(),
210 buildWrappedBody(),
211 positionalParameters: parameters, 208 positionalParameters: parameters,
212 requiredParameterCount: 0, 209 requiredParameterCount: 0,
213 asyncMarker: AsyncMarker.SyncYielding); 210 asyncMarker: AsyncMarker.SyncYielding);
214 211
215 // The await expression lifter might have created a number of 212 // The await expression lifter might have created a number of
216 // [VariableDeclarations]. 213 // [VariableDeclarations].
217 // TODO(kustermann): If we didn't need any variables we should not emit 214 // TODO(kustermann): If we didn't need any variables we should not emit
218 // these. 215 // these.
219 statements.addAll(variableDeclarations()); 216 statements.addAll(variableDeclarations());
220 statements.addAll(expressionRewriter.variables); 217 statements.addAll(expressionRewriter.variables);
221 218
222 // Now add the closure function itself. 219 // Now add the closure function itself.
223 final closureFunction = 220 final closureFunction =
224 new FunctionDeclaration(nestedClosureVariable, function); 221 new FunctionDeclaration(nestedClosureVariable, function);
225 statements.add(closureFunction); 222 statements.add(closureFunction);
226 223
227 // :async_op_then = _asyncThenWrapperHelper(asyncBody); 224 // :async_op_then = _asyncThenWrapperHelper(asyncBody);
228 final boundThenClosure = new StaticInvocation( 225 final boundThenClosure = new StaticInvocation(helper.asyncThenWrapper,
229 helper.asyncThenWrapper, 226 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)]));
230 new Arguments([new VariableGet(nestedClosureVariable)])); 227 final thenClosureVariableAssign = new ExpressionStatement(
231 final thenClosureVariableAssign = new ExpressionStatement(new VariableSet( 228 new VariableSet(thenContinuationVariable, boundThenClosure));
232 thenContinuationVariable, boundThenClosure));
233 statements.add(thenClosureVariableAssign); 229 statements.add(thenClosureVariableAssign);
234 230
235 // :async_op_error = _asyncErrorWrapperHelper(asyncBody); 231 // :async_op_error = _asyncErrorWrapperHelper(asyncBody);
236 final boundCatchErrorClosure = new StaticInvocation( 232 final boundCatchErrorClosure = new StaticInvocation(
237 helper.asyncErrorWrapper, 233 helper.asyncErrorWrapper,
238 new Arguments([new VariableGet(nestedClosureVariable)])); 234 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)]));
239 final catchErrorClosureVariableAssign = 235 final catchErrorClosureVariableAssign = new ExpressionStatement(
240 new ExpressionStatement(new VariableSet( 236 new VariableSet(
241 catchErrorContinuationVariable , boundCatchErrorClosure)); 237 catchErrorContinuationVariable, boundCatchErrorClosure));
242 statements.add(catchErrorClosureVariableAssign); 238 statements.add(catchErrorClosureVariableAssign);
243 } 239 }
244 240
245 Statement buildWrappedBody() { 241 Statement buildWrappedBody() {
246 // No explicit return at the end of the body => we will add one! 242 // No explicit return at the end of the body => we will add one!
247 var body = addReturnStatementIfNecessary(enclosingFunction.body); 243 var body = addReturnStatementIfNecessary(enclosingFunction.body);
248 var userBody = buildClosureBody(body); 244 var userBody = visitDelimited(body);
249 245
250 var exceptionVariable = new VariableDeclaration(":exception"); 246 var exceptionVariable = new VariableDeclaration(":exception");
251 var stackTraceVariable = new VariableDeclaration(":stack_trace"); 247 var stackTraceVariable = new VariableDeclaration(":stack_trace");
252 248
253 var completeErrorStatement = 249 var completeErrorStatement =
254 buildCatchBody(exceptionVariable, stackTraceVariable); 250 buildCatchBody(exceptionVariable, stackTraceVariable);
255 251
256 var catchBody = new Block(<Statement>[completeErrorStatement]); 252 var catchBody = new Block(<Statement>[completeErrorStatement]);
257 var catches = [new Catch(exceptionVariable, 253 var catches = <Catch>[
258 catchBody, 254 new Catch(exceptionVariable, catchBody, stackTrace: stackTraceVariable)
259 stackTrace: stackTraceVariable)]; 255 ];
260 return new TryCatch(userBody, catches); 256 return new TryCatch(userBody, catches);
261 } 257 }
262 258
263 addReturnStatementIfNecessary(Statement body) { 259 Statement addReturnStatementIfNecessary(Statement body) {
264 if (body is Block) { 260 if (body is Block) {
265 Block block = body; 261 Block block = body;
266 if (block.statements.isEmpty || 262 if (block.statements.isEmpty ||
267 block.statements.last is! ReturnStatement) { 263 block.statements.last is! ReturnStatement) {
268 var returnStatement = new ReturnStatement(); 264 var returnStatement = new ReturnStatement();
269 block.statements.add(returnStatement); 265 block.statements.add(returnStatement);
270 returnStatement.parent = block; 266 returnStatement.parent = block;
271 } 267 }
272 } else if (body is! ReturnStatement) { 268 } else if (body is! ReturnStatement) {
273 var returnStatement = new ReturnStatement(); 269 var returnStatement = new ReturnStatement();
274 body = new Block([body, returnStatement]); 270 body = new Block(<Statement>[body, returnStatement]);
275 } 271 }
276 return body; 272 return body;
277 } 273 }
278 274
279 Statement buildClosureBody(Statement node); 275 Statement buildCatchBody(
280 276 Statement exceptionVariable, Statement stackTraceVariable);
281 Statement buildCatchBody(Statement exceptionVariable, 277
282 Statement stackTraceVariable); 278 List<Statement> statements = <Statement>[];
283 279
284 visitForInStatement(ForInStatement node) { 280 TreeNode visitInvalidStatement(InvalidStatement stmt) {
285 if (node.isAsync) { 281 statements.add(stmt);
282 return null;
283 }
284
285 TreeNode visitExpressionStatement(ExpressionStatement stmt) {
286 stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
287 ..parent = stmt;
288 statements.add(stmt);
289 return null;
290 }
291
292 TreeNode visitBlock(Block stmt) {
293 var saved = statements;
294 statements = <Statement>[];
295 for (var statement in stmt.statements) {
296 statement.accept(this);
297 }
298 saved.add(new Block(statements));
299 statements = saved;
300 return null;
301 }
302
303 TreeNode visitEmptyStatement(EmptyStatement stmt) {
304 statements.add(stmt);
305 return null;
306 }
307
308 TreeNode visitAssertStatement(AssertStatement stmt) {
309 // TODO!
310 return null;
311 }
312
313 Statement visitDelimited(Statement stmt) {
314 var saved = statements;
315 statements = <Statement>[];
316 stmt.accept(this);
317 Statement result =
318 statements.length == 1 ? statements.first : new Block(statements);
319 statements = saved;
320 return result;
321 }
322
323 Statement visitLabeledStatement(LabeledStatement stmt) {
324 stmt.body = visitDelimited(stmt.body)..parent = stmt;
325 statements.add(stmt);
326 return null;
327 }
328
329 Statement visitBreakStatement(BreakStatement stmt) {
330 statements.add(stmt);
331 return null;
332 }
333
334 TreeNode visitWhileStatement(WhileStatement stmt) {
335 Statement body = visitDelimited(stmt.body);
336 List<Statement> effects = <Statement>[];
337 Expression cond = expressionRewriter.rewrite(stmt.condition, effects);
338 if (effects.isEmpty) {
339 stmt.condition = cond..parent = stmt;
340 stmt.body = body..parent = stmt;
341 statements.add(stmt);
342 } else {
343 // The condition rewrote to a non-empty sequence of statements S* and
344 // value V. Rewrite the loop to:
345 //
346 // L: while (true) {
347 // S*
348 // if (V) {
349 // [body]
350 // else {
351 // break L;
352 // }
353 // }
354 LabeledStatement labeled = new LabeledStatement(stmt);
355 stmt.condition = new BoolLiteral(true)..parent = stmt;
356 effects.add(new IfStatement(cond, body, new BreakStatement(labeled)));
357 stmt.body = new Block(effects)..parent = stmt;
358 statements.add(labeled);
359 }
360 return null;
361 }
362
363 TreeNode visitDoStatement(DoStatement stmt) {
364 Statement body = visitDelimited(stmt.body);
365 List<Statement> effects = <Statement>[];
366 stmt.condition = expressionRewriter.rewrite(stmt.condition, effects)
367 ..parent = stmt;
368 if (effects.isNotEmpty) {
369 // The condition rewrote to a non-empty sequence of statements S* and
370 // value V. Add the statements to the end of the loop body.
371 Block block = body is Block ? body : body = new Block(<Statement>[body]);
372 for (var effect in effects) {
373 block.statements.add(effect);
374 effect.parent = body;
375 }
376 }
377 stmt.body = body..parent = stmt;
378 statements.add(stmt);
379 return null;
380 }
381
382 TreeNode visitForStatement(ForStatement stmt) {
383 // Because of for-loop scoping and variable capture, it is tricky to deal
384 // with await in the loop's variable initializers or update expressions.
385 bool isSimple = true;
386 int length = stmt.variables.length;
387 List<List<Statement>> initEffects = new List<List<Statement>>(length);
388 for (int i = 0; i < length; ++i) {
389 VariableDeclaration decl = stmt.variables[i];
390 initEffects[i] = <Statement>[];
391 if (decl.initializer != null) {
392 decl.initializer = expressionRewriter.rewrite(
393 decl.initializer, initEffects[i])..parent = decl;
394 }
395 isSimple = isSimple && initEffects[i].isEmpty;
396 }
397
398 length = stmt.updates.length;
399 List<List<Statement>> updateEffects = new List<List<Statement>>(length);
400 for (int i = 0; i < length; ++i) {
401 updateEffects[i] = <Statement>[];
402 stmt.updates[i] = expressionRewriter.rewrite(
403 stmt.updates[i], updateEffects[i])..parent = stmt;
404 isSimple = isSimple && updateEffects[i].isEmpty;
405 }
406
407 Statement body = visitDelimited(stmt.body);
408 Expression cond = stmt.condition;
409 List<Statement> condEffects;
410 if (cond != null) {
411 condEffects = <Statement>[];
412 cond = expressionRewriter.rewrite(stmt.condition, condEffects);
413 }
414
415 if (isSimple) {
416 // If the condition contains await, we use a translation like the one for
417 // while loops, but leaving the variable declarations and the update
418 // expressions in place.
419 if (condEffects == null || condEffects.isEmpty) {
420 if (cond != null) stmt.condition = cond..parent = stmt;
421 stmt.body = body..parent = stmt;
422 statements.add(stmt);
423 } else {
424 LabeledStatement labeled = new LabeledStatement(stmt);
425 // No condition in a for loop is the same as true.
426 stmt.condition = null;
427 condEffects
428 .add(new IfStatement(cond, body, new BreakStatement(labeled)));
429 stmt.body = new Block(condEffects)..parent = stmt;
430 statements.add(labeled);
431 }
432 return null;
433 }
434
435 // If the rewrite of the initializer or update expressions produces a
436 // non-empty sequence of statements then the loop is desugared. If the loop
437 // has the form:
438 //
439 // label: for (Type x = init; cond; update) body
440 //
441 // it is translated as if it were:
442 //
443 // {
444 // bool first = true;
445 // Type temp;
446 // label: while (true) {
447 // Type x;
448 // if (first) {
449 // first = false;
450 // x = init;
451 // } else {
452 // x = temp;
453 // update;
454 // }
455 // if (cond) {
456 // body;
457 // temp = x;
458 // } else {
459 // break;
460 // }
461 // }
462 // }
463
464 // Place the loop variable declarations at the beginning of the body
465 // statements and move their initializers to a guarded list of statements.
466 // Add assignments to the loop variables from the previous iteration's temp
467 // variables before the updates.
468 //
469 // temps.first is the flag 'first'.
470 // TODO(kmillikin) bool type for first.
471 List<VariableDeclaration> temps = <VariableDeclaration>[
472 new VariableDeclaration.forValue(new BoolLiteral(true), isFinal: false)
473 ];
474 List<Statement> loopBody = <Statement>[];
475 List<Statement> initializers = <Statement>[
476 new ExpressionStatement(
477 new VariableSet(temps.first, new BoolLiteral(false)))
478 ];
479 List<Statement> updates = <Statement>[];
480 List<Statement> newBody = <Statement>[body];
481 for (int i = 0; i < stmt.variables.length; ++i) {
482 VariableDeclaration decl = stmt.variables[i];
483 temps.add(new VariableDeclaration(null, type: decl.type));
484 loopBody.add(decl);
485 if (decl.initializer != null) {
486 initializers.addAll(initEffects[i]);
487 initializers.add(
488 new ExpressionStatement(new VariableSet(decl, decl.initializer)));
489 decl.initializer = null;
490 }
491 updates.add(new ExpressionStatement(
492 new VariableSet(decl, new VariableGet(temps.last))));
493 newBody.add(new ExpressionStatement(
494 new VariableSet(temps.last, new VariableGet(decl))));
495 }
496 // Add the updates to their guarded list of statements.
497 for (int i = 0; i < stmt.updates.length; ++i) {
498 updates.addAll(updateEffects[i]);
499 updates.add(new ExpressionStatement(stmt.updates[i]));
500 }
501 // Initializers or updates could be empty.
502 loopBody.add(new IfStatement(new VariableGet(temps.first),
503 new Block(initializers), new Block(updates)));
504
505 LabeledStatement labeled = new LabeledStatement(null);
506 if (cond != null) {
507 loopBody.addAll(condEffects);
508 } else {
509 cond = new BoolLiteral(true);
510 }
511 loopBody.add(
512 new IfStatement(cond, new Block(newBody), new BreakStatement(labeled)));
513 labeled.body =
514 new WhileStatement(new BoolLiteral(true), new Block(loopBody));
515 statements.add(new Block(<Statement>[]
516 ..addAll(temps)
517 ..add(labeled)));
518 return null;
519 }
520
521 TreeNode visitForInStatement(ForInStatement stmt) {
522 if (stmt.isAsync) {
286 // Transform 523 // Transform
287 // 524 //
288 // await for (var variable in <stream-expression>) { ... } 525 // await for (var variable in <stream-expression>) { ... }
289 // 526 //
290 // To: 527 // To:
291 // 528 //
292 // { 529 // {
293 // var :for-iterator = new StreamIterator(<stream-expression>); 530 // var :for-iterator = new StreamIterator(<stream-expression>);
294 // try { 531 // try {
295 // while (await :for-iterator.moveNext()) { 532 // while (await :for-iterator.moveNext()) {
296 // var <variable> = :for-iterator.current; 533 // var <variable> = :for-iterator.current;
297 // ... 534 // ...
298 // } 535 // }
299 // } finally { 536 // } finally {
300 // :for-iterator.cancel(); 537 // :for-iterator.cancel();
301 // } 538 // }
302 // } 539 // }
303 var iteratorVariable = new VariableDeclaration( 540 var iteratorVariable = new VariableDeclaration(':for-iterator',
304 ':for-iterator',
305 initializer: new ConstructorInvocation( 541 initializer: new ConstructorInvocation(
306 helper.streamIteratorConstructor, 542 helper.streamIteratorConstructor,
307 new Arguments([expressionRewriter.rewrite(node.iterable)]))); 543 new Arguments(<Expression>[stmt.iterable])));
308 544
309 // await iterator.moveNext() 545 // await iterator.moveNext()
310 var condition = new AwaitExpression(new MethodInvocation( 546 var condition = new AwaitExpression(new MethodInvocation(
311 new VariableGet(iteratorVariable), 547 new VariableGet(iteratorVariable),
312 new Name('moveNext'), 548 new Name('moveNext'),
313 new Arguments([]))); 549 new Arguments(<Expression>[])));
314 550
315 // var <variable> = iterator.current; 551 // var <variable> = iterator.current;
316 var valueVariable = node.variable; 552 var valueVariable = stmt.variable;
317 valueVariable.initializer = new PropertyGet( 553 valueVariable.initializer = new PropertyGet(
318 new VariableGet(iteratorVariable), 554 new VariableGet(iteratorVariable), new Name('current'));
319 new Name('current'));
320 valueVariable.initializer.parent = valueVariable; 555 valueVariable.initializer.parent = valueVariable;
321 556
322 var whileBody = new Block([valueVariable, node.body]); 557 var whileBody = new Block(<Statement>[valueVariable, stmt.body]);
323 var tryBody = new WhileStatement(condition, whileBody); 558 var tryBody = new WhileStatement(condition, whileBody);
324 559
325 // iterator.cancel(); 560 // iterator.cancel();
326 var tryFinalizer = new ExpressionStatement( 561 var tryFinalizer = new ExpressionStatement(new MethodInvocation(
327 new MethodInvocation( 562 new VariableGet(iteratorVariable),
328 new VariableGet(iteratorVariable), 563 new Name('cancel'),
329 new Name('cancel'), 564 new Arguments(<Expression>[])));
330 new Arguments([])));
331 565
332 var tryFinally = new TryFinally(tryBody, tryFinalizer); 566 var tryFinally = new TryFinally(tryBody, tryFinalizer);
333 567
334 var block = new Block([ 568 var block = new Block(<Statement>[iteratorVariable, tryFinally]);
335 iteratorVariable, 569 block.accept(this);
336 tryFinally,
337 ]);
338 return block.accept(this);
339 } else { 570 } else {
340 return super.visitForInStatement(node); 571 stmt.iterable = expressionRewriter.rewrite(stmt.iterable, statements)
572 ..parent = stmt;
573 stmt.body = visitDelimited(stmt.body)..parent = stmt;
574 statements.add(stmt);
341 } 575 }
576 return null;
342 } 577 }
343 578
344 defaultExpression(TreeNode node) { 579 TreeNode visitSwitchStatement(SwitchStatement stmt) {
345 return expressionRewriter.rewrite(node); 580 stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
581 ..parent = stmt;
582 for (var switchCase in stmt.cases) {
583 // Expressions in switch cases cannot contain await so they do not need to
584 // be translated.
585 switchCase.body = visitDelimited(switchCase.body)..parent = switchCase;
586 }
587 statements.add(stmt);
588 return null;
346 } 589 }
590
591 TreeNode visitContinueSwitchStatement(ContinueSwitchStatement stmt) {
592 statements.add(stmt);
593 return null;
594 }
595
596 TreeNode visitIfStatement(IfStatement stmt) {
597 stmt.condition = expressionRewriter.rewrite(stmt.condition, statements)
598 ..parent = stmt;
599 stmt.then = visitDelimited(stmt.then)..parent = stmt;
600 if (stmt.otherwise != null) {
601 stmt.otherwise = visitDelimited(stmt.otherwise)..parent = stmt;
602 }
603 statements.add(stmt);
604 return null;
605 }
606
607 TreeNode visitReturnStatement(ReturnStatement stmt) {
608 if (stmt.expression != null) {
609 stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
610 ..parent = stmt;
611 }
612 statements.add(stmt);
613 return null;
614 }
615
616 TreeNode visitTryCatch(TryCatch stmt) {
617 ++currentTryDepth;
618 stmt.body = visitDelimited(stmt.body)..parent = stmt;
619 --currentTryDepth;
620
621 ++currentCatchDepth;
622 for (var clause in stmt.catches) {
623 clause.body = visitDelimited(clause.body)..parent = clause;
624 }
625 --currentCatchDepth;
626 statements.add(stmt);
627 return null;
628 }
629
630 TreeNode visitTryFinally(TryFinally stmt) {
631 ++currentTryDepth;
632 stmt.body = visitDelimited(stmt.body)..parent = stmt;
633 --currentTryDepth;
634 stmt.finalizer = visitDelimited(stmt.finalizer)..parent = stmt;
635 statements.add(stmt);
636 return null;
637 }
638
639 TreeNode visitYieldStatement(YieldStatement stmt) {
640 stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
641 ..parent = stmt;
642 statements.add(stmt);
643 return null;
644 }
645
646 TreeNode visitVariableDeclaration(VariableDeclaration stmt) {
647 if (stmt.initializer != null) {
648 stmt.initializer = expressionRewriter.rewrite(
649 stmt.initializer, statements)..parent = stmt;
650 }
651 statements.add(stmt);
652 return null;
653 }
654
655 TreeNode visitFunctionDeclaration(FunctionDeclaration stmt) {
656 stmt.function = stmt.function.accept(this)..parent = stmt;
657 statements.add(stmt);
658 return null;
659 }
660
661 defaultExpression(TreeNode node) => throw 'unreachable';
347 } 662 }
348 663
349 class AsyncStarFunctionRewriter extends AsyncRewriterBase { 664 class AsyncStarFunctionRewriter extends AsyncRewriterBase {
350 VariableDeclaration controllerVariable; 665 VariableDeclaration controllerVariable;
351 666
352 AsyncStarFunctionRewriter(helper, enclosingFunction) 667 AsyncStarFunctionRewriter(helper, enclosingFunction)
353 : super(helper, enclosingFunction); 668 : super(helper, enclosingFunction);
354 669
355 FunctionNode rewrite() { 670 FunctionNode rewrite() {
356 var statements = <Statement>[]; 671 var statements = <Statement>[];
357 672
358 // var :controller; 673 // var :controller;
359 controllerVariable = new VariableDeclaration(":controller"); 674 controllerVariable = new VariableDeclaration(":controller");
360 statements.add(controllerVariable); 675 statements.add(controllerVariable);
361 676
362 super.setupAsyncContinuations(statements); 677 super.setupAsyncContinuations(statements);
363 678
364 // :controller = new _AsyncController(:async_op); 679 // :controller = new _AsyncController(:async_op);
365 var arguments = new Arguments([new VariableGet(nestedClosureVariable)]); 680 var arguments =
681 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)]);
366 var buildController = new ConstructorInvocation( 682 var buildController = new ConstructorInvocation(
367 helper.streamControllerConstructor, arguments); 683 helper.streamControllerConstructor, arguments);
368 var setController = new ExpressionStatement( 684 var setController = new ExpressionStatement(
369 new VariableSet(controllerVariable, buildController)); 685 new VariableSet(controllerVariable, buildController));
370 statements.add(setController); 686 statements.add(setController);
371 687
372 // return :controller.stream; 688 // return :controller.stream;
373 var completerGet = new VariableGet(controllerVariable); 689 var completerGet = new VariableGet(controllerVariable);
374 var returnStatement = new ReturnStatement( 690 var returnStatement = new ReturnStatement(
375 new PropertyGet(completerGet, new Name('stream', helper.asyncLibrary))); 691 new PropertyGet(completerGet, new Name('stream', helper.asyncLibrary)));
376 statements.add(returnStatement); 692 statements.add(returnStatement);
377 693
378 enclosingFunction.body = new Block(statements); 694 enclosingFunction.body = new Block(statements);
379 enclosingFunction.body.parent = enclosingFunction; 695 enclosingFunction.body.parent = enclosingFunction;
380 enclosingFunction.asyncMarker = AsyncMarker.Sync; 696 enclosingFunction.asyncMarker = AsyncMarker.Sync;
381 return enclosingFunction; 697 return enclosingFunction;
382 } 698 }
383 699
384 Statement buildClosureBody(Statement node) { 700 Statement buildCatchBody(exceptionVariable, stackTraceVariable) {
385 // The body will insert calls to 701 return new ExpressionStatement(new MethodInvocation(
386 // :controller.add() 702 new VariableGet(controllerVariable),
387 // :controller.addStream() 703 new Name("completeError", helper.asyncLibrary),
388 // :controller.addError() 704 new Arguments(<Expression>[
389 // :controller.close() 705 new VariableGet(exceptionVariable),
390 return node.accept(this); 706 new VariableGet(stackTraceVariable)
707 ])));
391 } 708 }
392 709
393 Statement buildCatchBody(exceptionVariable, stackTraceVariable) { 710 TreeNode visitYieldStatement(YieldStatement stmt) {
394 return new ExpressionStatement( 711 Expression expr = expressionRewriter.rewrite(stmt.expression, statements);
395 new MethodInvocation( 712
396 new VariableGet(controllerVariable), 713 var addExpression = new MethodInvocation(
397 new Name("completeError", helper.asyncLibrary), 714 new VariableGet(controllerVariable),
398 new Arguments([new VariableGet(exceptionVariable), 715 new Name(stmt.isYieldStar ? 'addStream' : 'add', helper.asyncLibrary),
399 new VariableGet(stackTraceVariable)]))); 716 new Arguments(<Expression>[expr]));
717
718 statements.add(new IfStatement(addExpression,
719 new ReturnStatement(new NullLiteral()), createContinuationPoint()));
720 return null;
400 } 721 }
401 722
402 visitYieldStatement(YieldStatement node) { 723 TreeNode visitReturnStatement(ReturnStatement node) {
403 var transformedExpression = node.expression.accept(this);
404
405 var addExpression = new MethodInvocation(
406 new VariableGet(controllerVariable),
407 new Name(node.isYieldStar ? 'addStream' : 'add', helper.asyncLibrary),
408 new Arguments([transformedExpression]));
409
410 var addAndReturnOrYield = new IfStatement(
411 addExpression,
412 new ReturnStatement(new NullLiteral()),
413 createContinuationPoint());
414 return new Block([addAndReturnOrYield]);
415 }
416
417 visitReturnStatement(ReturnStatement node) {
418 // async* functions cannot have normal [ReturnStatement]s in them. 724 // async* functions cannot have normal [ReturnStatement]s in them.
419 assert(node.expression == null || node.expression is NullLiteral); 725 assert(node.expression == null || node.expression is NullLiteral);
420 726
421 var close = new ExpressionStatement( 727 statements.add(new ExpressionStatement(new MethodInvocation(
422 new MethodInvocation( 728 new VariableGet(controllerVariable),
423 new VariableGet(controllerVariable), 729 new Name("close", helper.asyncLibrary),
424 new Name("close", helper.asyncLibrary), 730 new Arguments(<Expression>[]))));
425 new Arguments([]))); 731 statements.add(new ReturnStatement());
426 var returnStatement = new ReturnStatement(); 732 return null;
427 return new Block([close, returnStatement]);
428 } 733 }
429 } 734 }
430 735
431 class AsyncFunctionRewriter extends AsyncRewriterBase { 736 class AsyncFunctionRewriter extends AsyncRewriterBase {
432 VariableDeclaration completerVariable; 737 VariableDeclaration completerVariable;
433 738
434 AsyncFunctionRewriter(helper, enclosingFunction) 739 AsyncFunctionRewriter(helper, enclosingFunction)
435 : super(helper, enclosingFunction); 740 : super(helper, enclosingFunction);
436 741
437 FunctionNode rewrite() { 742 FunctionNode rewrite() {
438 var statements = <Statement>[]; 743 var statements = <Statement>[];
439 744
440 // var :completer = new Completer.sync(); 745 // var :completer = new Completer.sync();
441 completerVariable = new VariableDeclaration( 746 completerVariable = new VariableDeclaration(":completer",
442 ":completer", 747 initializer: new StaticInvocation(
443 initializer: new StaticInvocation(helper.completerConstructor, 748 helper.completerConstructor, new Arguments([])),
444 new Arguments([])),
445 isFinal: true); 749 isFinal: true);
446 statements.add(completerVariable); 750 statements.add(completerVariable);
447 751
448 super.setupAsyncContinuations(statements); 752 super.setupAsyncContinuations(statements);
449 753
450 // new Future.microtask(:async_op); 754 // new Future.microtask(:async_op);
451 var newMicrotaskStatement = new ExpressionStatement( 755 var newMicrotaskStatement = new ExpressionStatement(new StaticInvocation(
452 new StaticInvocation( 756 helper.futureMicrotaskConstructor,
453 helper.futureMicrotaskConstructor, 757 new Arguments([new VariableGet(nestedClosureVariable)])));
454 new Arguments([new VariableGet(nestedClosureVariable)])));
455 statements.add(newMicrotaskStatement); 758 statements.add(newMicrotaskStatement);
456 759
457 // return :completer.future; 760 // return :completer.future;
458 var completerGet = new VariableGet(completerVariable); 761 var completerGet = new VariableGet(completerVariable);
459 var returnStatement = new ReturnStatement( 762 var returnStatement = new ReturnStatement(
460 new PropertyGet(completerGet, new Name('future', helper.asyncLibrary))); 763 new PropertyGet(completerGet, new Name('future', helper.asyncLibrary)));
461 statements.add(returnStatement); 764 statements.add(returnStatement);
462 765
463 enclosingFunction.body = new Block(statements); 766 enclosingFunction.body = new Block(statements);
464 enclosingFunction.body.parent = enclosingFunction; 767 enclosingFunction.body.parent = enclosingFunction;
465 enclosingFunction.asyncMarker = AsyncMarker.Sync; 768 enclosingFunction.asyncMarker = AsyncMarker.Sync;
466 return enclosingFunction; 769 return enclosingFunction;
467 } 770 }
468 771
469 Statement buildClosureBody(Statement node) {
470 // TODO(kustermann): Can we assume the frontend will insert proper
471 // [ReturnStatement]s?
472
473 // Translating the body will insert calls to
474 // :completer.completeError()
475 // :completer.complete()
476 return node.accept(this);
477 }
478
479 Statement buildCatchBody(exceptionVariable, stackTraceVariable) { 772 Statement buildCatchBody(exceptionVariable, stackTraceVariable) {
480 return new ExpressionStatement( 773 return new ExpressionStatement(new MethodInvocation(
481 new MethodInvocation( 774 new VariableGet(completerVariable),
482 new VariableGet(completerVariable), 775 new Name("completeError", helper.asyncLibrary),
483 new Name("completeError", helper.asyncLibrary), 776 new Arguments([
484 new Arguments([new VariableGet(exceptionVariable), 777 new VariableGet(exceptionVariable),
485 new VariableGet(stackTraceVariable)]))); 778 new VariableGet(stackTraceVariable)
779 ])));
486 } 780 }
487 781
488 visitReturnStatement(ReturnStatement node) { 782 visitReturnStatement(ReturnStatement node) {
489 var transformedExpression; 783 var expr;
490 if (node.expression == null) { 784 if (node.expression == null) {
491 transformedExpression = new NullLiteral(); 785 expr = new NullLiteral();
492 } else { 786 } else {
493 transformedExpression = expressionRewriter.rewrite(node.expression); 787 expr = expressionRewriter.rewrite(node.expression, statements);
494 } 788 }
495 789
496 // Note: transformed expression can't be used directly as part of the 790 statements.add(new ExpressionStatement(new MethodInvocation(
497 // method invocation because it might contain yield points and 791 new VariableGet(completerVariable),
498 // expression stack might not be empty. 792 new Name("complete", helper.asyncLibrary),
499 var resultVar = new VariableDeclaration(':async_temp', 793 new Arguments([expr]))));
500 initializer: transformedExpression); 794 statements.add(new ReturnStatement(new NullLiteral()));
501 var completeCompleter = new ExpressionStatement( 795 return null;
502 new MethodInvocation(
503 new VariableGet(completerVariable),
504 new Name("complete", helper.asyncLibrary),
505 new Arguments([new VariableGet(resultVar)])));
506 var returnStatement = new ReturnStatement(new NullLiteral());
507 return new Block([resultVar, completeCompleter, returnStatement]);
508 } 796 }
509 } 797 }
510 798
511 class HelperNodes { 799 class HelperNodes {
512 final Library asyncLibrary; 800 final Library asyncLibrary;
513 final Library coreLibrary; 801 final Library coreLibrary;
514 final Procedure printProcedure; 802 final Procedure printProcedure;
515 final Procedure completerConstructor; 803 final Procedure completerConstructor;
516 final Procedure futureMicrotaskConstructor; 804 final Procedure futureMicrotaskConstructor;
517 final Constructor streamControllerConstructor; 805 final Constructor streamControllerConstructor;
518 final Constructor syncIterableConstructor; 806 final Constructor syncIterableConstructor;
519 final Constructor streamIteratorConstructor; 807 final Constructor streamIteratorConstructor;
520 final Procedure asyncThenWrapper; 808 final Procedure asyncThenWrapper;
521 final Procedure asyncErrorWrapper; 809 final Procedure asyncErrorWrapper;
522 final Procedure awaitHelper; 810 final Procedure awaitHelper;
523 811
524 HelperNodes( 812 HelperNodes(
525 this.asyncLibrary, 813 this.asyncLibrary,
526 this.coreLibrary, 814 this.coreLibrary,
527 this.printProcedure, 815 this.printProcedure,
528 this.completerConstructor, 816 this.completerConstructor,
529 this.syncIterableConstructor, 817 this.syncIterableConstructor,
530 this.streamIteratorConstructor, 818 this.streamIteratorConstructor,
531 this.futureMicrotaskConstructor, 819 this.futureMicrotaskConstructor,
532 this.streamControllerConstructor, 820 this.streamControllerConstructor,
533 this.asyncThenWrapper, 821 this.asyncThenWrapper,
534 this.asyncErrorWrapper, 822 this.asyncErrorWrapper,
535 this.awaitHelper 823 this.awaitHelper);
536 );
537 824
538 factory HelperNodes.fromProgram(Program program) { 825 factory HelperNodes.fromProgram(Program program) {
539 Library findLibrary(String name) { 826 Library findLibrary(String name) {
540 Uri uri = Uri.parse(name); 827 Uri uri = Uri.parse(name);
541 for (var library in program.libraries) { 828 for (var library in program.libraries) {
542 if (library.importUri == uri) return library; 829 if (library.importUri == uri) return library;
543 } 830 }
544 throw 'Library "$name" not found'; 831 throw 'Library "$name" not found';
545 } 832 }
546 Class findClass(Library library, String name) { 833 Class findClass(Library library, String name) {
(...skipping 24 matching lines...) Expand all
571 throw 'Procedure "$name" not found'; 858 throw 'Procedure "$name" not found';
572 } 859 }
573 860
574 var asyncLibrary = findLibrary('dart:async'); 861 var asyncLibrary = findLibrary('dart:async');
575 var coreLibrary = findLibrary('dart:core'); 862 var coreLibrary = findLibrary('dart:core');
576 863
577 var completerClass = findClass(asyncLibrary, 'Completer'); 864 var completerClass = findClass(asyncLibrary, 'Completer');
578 var futureClass = findClass(asyncLibrary, 'Future'); 865 var futureClass = findClass(asyncLibrary, 'Future');
579 var streamIteratorClass = findClass(asyncLibrary, '_StreamIterator'); 866 var streamIteratorClass = findClass(asyncLibrary, '_StreamIterator');
580 var syncIterableClass = findClass(coreLibrary, '_SyncIterable'); 867 var syncIterableClass = findClass(coreLibrary, '_SyncIterable');
581 var streamControllerClass = findClass( 868 var streamControllerClass =
582 asyncLibrary, '_AsyncStarStreamController'); 869 findClass(asyncLibrary, '_AsyncStarStreamController');
583 870
584 return new HelperNodes( 871 return new HelperNodes(
585 asyncLibrary, 872 asyncLibrary,
586 coreLibrary, 873 coreLibrary,
587 findProcedure(coreLibrary, 'print'), 874 findProcedure(coreLibrary, 'print'),
588 findFactoryConstructor(completerClass, 'sync'), 875 findFactoryConstructor(completerClass, 'sync'),
589 findConstructor(syncIterableClass, ''), 876 findConstructor(syncIterableClass, ''),
590 findConstructor(streamIteratorClass , ''), 877 findConstructor(streamIteratorClass, ''),
591 findFactoryConstructor(futureClass, 'microtask'), 878 findFactoryConstructor(futureClass, 'microtask'),
592 findConstructor(streamControllerClass, ''), 879 findConstructor(streamControllerClass, ''),
593 findProcedure(asyncLibrary, '_asyncThenWrapperHelper'), 880 findProcedure(asyncLibrary, '_asyncThenWrapperHelper'),
594 findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'), 881 findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'),
595 findProcedure(asyncLibrary, '_awaitHelper')); 882 findProcedure(asyncLibrary, '_awaitHelper'));
596 } 883 }
597 } 884 }
OLDNEW
« no previous file with comments | « lib/transformations/async.dart ('k') | lib/type_propagation/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698