| OLD | NEW |
| 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.async; | 5 library kernel.transformations.async; |
| 6 | 6 |
| 7 import '../kernel.dart'; | 7 import '../kernel.dart'; |
| 8 import 'continuation.dart'; | 8 import 'continuation.dart'; |
| 9 | 9 |
| 10 /// A transformer that introduces temporary variables for all subexpressions | 10 /// A transformer that introduces temporary variables for all subexpressions |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 seenAwait = true; | 430 seenAwait = true; |
| 431 return result; | 431 return result; |
| 432 } | 432 } |
| 433 | 433 |
| 434 TreeNode visitFunctionExpression(FunctionExpression expr) { | 434 TreeNode visitFunctionExpression(FunctionExpression expr) { |
| 435 expr.transformChildren(this); | 435 expr.transformChildren(this); |
| 436 return expr; | 436 return expr; |
| 437 } | 437 } |
| 438 | 438 |
| 439 TreeNode visitLet(Let expr) { | 439 TreeNode visitLet(Let expr) { |
| 440 return transform(expr, () { | 440 var shouldName = seenAwait; |
| 441 expr.body = expr.body.accept(this)..parent = expr; | 441 |
| 442 VariableDeclaration variable = expr.variable; | 442 seenAwait = false; |
| 443 var body = expr.body.accept(this); |
| 444 |
| 445 VariableDeclaration variable = expr.variable; |
| 446 if (seenAwait) { |
| 447 // The body in `let var x = initializer in body` contained an await. We |
| 448 // will produce the sequence of statements: |
| 449 // |
| 450 // <initializer's statements> |
| 451 // var x = <initializer's value> |
| 452 // <body's statements> |
| 453 // |
| 454 // and return the body's value. |
| 455 // |
| 456 // So x is in scope for all the body's statements and the body's value. |
| 457 // This has the unpleasant consequence that all let-bound variables with |
| 458 // await in the let's body will end up hoisted out the the expression and |
| 459 // allocated to the context in the VM, even if they have no uses |
| 460 // (`let _ = e0 in e1` can be used for sequencing of `e0` and `e1`). |
| 461 statements.add(variable); |
| 462 var index = nameIndex; |
| 463 seenAwait = false; |
| 443 variable.initializer = | 464 variable.initializer = |
| 444 variable.initializer.accept(this)..parent = variable; | 465 variable.initializer.accept(this)..parent = variable; |
| 445 }); | 466 // Temporaries used in the initializer or the body are not live but the |
| 467 // temporary used for the body is. |
| 468 nameIndex = index + 1; |
| 469 seenAwait = true; |
| 470 return body; |
| 471 } else { |
| 472 // The body in `let x = initializer in body` did not contain an await. We |
| 473 // can leave a let expression. |
| 474 seenAwait = shouldName; |
| 475 return transform(expr, () { |
| 476 // The body has already been translated. |
| 477 expr.body = body..parent = expr; |
| 478 variable.initializer = |
| 479 variable.initializer.accept(this)..parent = variable; |
| 480 }); |
| 481 } |
| 446 } | 482 } |
| 447 | 483 |
| 448 visitFunctionNode(FunctionNode node) { | 484 visitFunctionNode(FunctionNode node) { |
| 449 var nestedRewriter = new RecursiveContinuationRewriter( | 485 var nestedRewriter = new RecursiveContinuationRewriter( |
| 450 continuationRewriter.helper); | 486 continuationRewriter.helper); |
| 451 return node.accept(nestedRewriter); | 487 return node.accept(nestedRewriter); |
| 452 } | 488 } |
| 453 } | 489 } |
| OLD | NEW |