| 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.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'; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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(buildClosureBody(), | 125 final function = new FunctionNode(buildClosureBody(), |
| 126 positionalParameters: [iteratorVariable], | 126 positionalParameters: [iteratorVariable], |
| 127 requiredParameterCount: 1, | 127 requiredParameterCount: 1, |
| 128 asyncMarker: AsyncMarker.SyncYielding); | 128 asyncMarker: AsyncMarker.SyncYielding) |
| 129 ..fileOffset = enclosingFunction.fileOffset |
| 130 ..fileEndOffset = enclosingFunction.fileEndOffset; |
| 129 final closureFunction = | 131 final closureFunction = |
| 130 new FunctionDeclaration(nestedClosureVariable, function); | 132 new FunctionDeclaration(nestedClosureVariable, function) |
| 133 ..fileOffset = enclosingFunction.parent.fileOffset; |
| 131 | 134 |
| 132 // return new _SyncIterable(:sync_body); | 135 // return new _SyncIterable(:sync_body); |
| 133 final arguments = new Arguments([new VariableGet(nestedClosureVariable)]); | 136 final arguments = new Arguments([new VariableGet(nestedClosureVariable)]); |
| 134 final returnStatement = new ReturnStatement( | 137 final returnStatement = new ReturnStatement( |
| 135 new ConstructorInvocation(helper.syncIterableConstructor, arguments)); | 138 new ConstructorInvocation(helper.syncIterableConstructor, arguments)); |
| 136 | 139 |
| 137 enclosingFunction.body = new Block([] | 140 enclosingFunction.body = new Block([] |
| 138 ..addAll(variableDeclarations()) | 141 ..addAll(variableDeclarations()) |
| 139 ..addAll([closureFunction, returnStatement])); | 142 ..addAll([closureFunction, returnStatement])); |
| 140 enclosingFunction.body.parent = enclosingFunction; | 143 enclosingFunction.body.parent = enclosingFunction; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 // modified <node.body>; | 205 // modified <node.body>; |
| 203 // } | 206 // } |
| 204 final parameters = <VariableDeclaration>[ | 207 final parameters = <VariableDeclaration>[ |
| 205 expressionRewriter.asyncResult, | 208 expressionRewriter.asyncResult, |
| 206 new VariableDeclaration(':exception'), | 209 new VariableDeclaration(':exception'), |
| 207 new VariableDeclaration(':stack_trace'), | 210 new VariableDeclaration(':stack_trace'), |
| 208 ]; | 211 ]; |
| 209 final function = new FunctionNode(buildWrappedBody(), | 212 final function = new FunctionNode(buildWrappedBody(), |
| 210 positionalParameters: parameters, | 213 positionalParameters: parameters, |
| 211 requiredParameterCount: 0, | 214 requiredParameterCount: 0, |
| 212 asyncMarker: AsyncMarker.SyncYielding); | 215 asyncMarker: AsyncMarker.SyncYielding) |
| 216 ..fileOffset = enclosingFunction.fileOffset |
| 217 ..fileEndOffset = enclosingFunction.fileEndOffset; |
| 213 | 218 |
| 214 // The await expression lifter might have created a number of | 219 // The await expression lifter might have created a number of |
| 215 // [VariableDeclarations]. | 220 // [VariableDeclarations]. |
| 216 // TODO(kustermann): If we didn't need any variables we should not emit | 221 // TODO(kustermann): If we didn't need any variables we should not emit |
| 217 // these. | 222 // these. |
| 218 statements.addAll(variableDeclarations()); | 223 statements.addAll(variableDeclarations()); |
| 219 statements.addAll(expressionRewriter.variables); | 224 statements.addAll(expressionRewriter.variables); |
| 220 | 225 |
| 221 // Now add the closure function itself. | 226 // Now add the closure function itself. |
| 222 final closureFunction = | 227 final closureFunction = |
| 223 new FunctionDeclaration(nestedClosureVariable, function); | 228 new FunctionDeclaration(nestedClosureVariable, function) |
| 229 ..fileOffset = enclosingFunction.parent.fileOffset; |
| 224 statements.add(closureFunction); | 230 statements.add(closureFunction); |
| 225 | 231 |
| 226 // :async_op_then = _asyncThenWrapperHelper(asyncBody); | 232 // :async_op_then = _asyncThenWrapperHelper(asyncBody); |
| 227 final boundThenClosure = new StaticInvocation(helper.asyncThenWrapper, | 233 final boundThenClosure = new StaticInvocation(helper.asyncThenWrapper, |
| 228 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)])); | 234 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)])); |
| 229 final thenClosureVariableAssign = new ExpressionStatement( | 235 final thenClosureVariableAssign = new ExpressionStatement( |
| 230 new VariableSet(thenContinuationVariable, boundThenClosure)); | 236 new VariableSet(thenContinuationVariable, boundThenClosure)); |
| 231 statements.add(thenClosureVariableAssign); | 237 statements.add(thenClosureVariableAssign); |
| 232 | 238 |
| 233 // :async_op_error = _asyncErrorWrapperHelper(asyncBody); | 239 // :async_op_error = _asyncErrorWrapperHelper(asyncBody); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 var iteratorVariable = new VariableDeclaration(':for-iterator', | 534 var iteratorVariable = new VariableDeclaration(':for-iterator', |
| 529 initializer: new ConstructorInvocation( | 535 initializer: new ConstructorInvocation( |
| 530 helper.streamIteratorConstructor, | 536 helper.streamIteratorConstructor, |
| 531 new Arguments(<Expression>[stmt.iterable], | 537 new Arguments(<Expression>[stmt.iterable], |
| 532 types: [const DynamicType()]))); | 538 types: [const DynamicType()]))); |
| 533 | 539 |
| 534 // await iterator.moveNext() | 540 // await iterator.moveNext() |
| 535 var condition = new AwaitExpression(new MethodInvocation( | 541 var condition = new AwaitExpression(new MethodInvocation( |
| 536 new VariableGet(iteratorVariable), | 542 new VariableGet(iteratorVariable), |
| 537 new Name('moveNext'), | 543 new Name('moveNext'), |
| 538 new Arguments(<Expression>[]))); | 544 new Arguments(<Expression>[])))..fileOffset = stmt.fileOffset; |
| 539 | 545 |
| 540 // var <variable> = iterator.current; | 546 // var <variable> = iterator.current; |
| 541 var valueVariable = stmt.variable; | 547 var valueVariable = stmt.variable; |
| 542 valueVariable.initializer = new PropertyGet( | 548 valueVariable.initializer = new PropertyGet( |
| 543 new VariableGet(iteratorVariable), new Name('current')); | 549 new VariableGet(iteratorVariable), new Name('current')); |
| 544 valueVariable.initializer.parent = valueVariable; | 550 valueVariable.initializer.parent = valueVariable; |
| 545 | 551 |
| 546 var whileBody = new Block(<Statement>[valueVariable, stmt.body]); | 552 var whileBody = new Block(<Statement>[valueVariable, stmt.body]); |
| 547 var tryBody = new WhileStatement(condition, whileBody); | 553 var tryBody = new WhileStatement(condition, whileBody); |
| 548 | 554 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 | 658 |
| 653 // var :controller; | 659 // var :controller; |
| 654 controllerVariable = new VariableDeclaration(":controller"); | 660 controllerVariable = new VariableDeclaration(":controller"); |
| 655 statements.add(controllerVariable); | 661 statements.add(controllerVariable); |
| 656 | 662 |
| 657 setupAsyncContinuations(statements); | 663 setupAsyncContinuations(statements); |
| 658 | 664 |
| 659 // :controller = new _AsyncController(:async_op); | 665 // :controller = new _AsyncController(:async_op); |
| 660 var arguments = | 666 var arguments = |
| 661 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)]); | 667 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)]); |
| 662 var buildController = new ConstructorInvocation( | 668 var buildController = |
| 663 helper.streamControllerConstructor, arguments); | 669 new ConstructorInvocation(helper.streamControllerConstructor, arguments) |
| 670 ..fileOffset = enclosingFunction.fileOffset; |
| 664 var setController = new ExpressionStatement( | 671 var setController = new ExpressionStatement( |
| 665 new VariableSet(controllerVariable, buildController)); | 672 new VariableSet(controllerVariable, buildController)); |
| 666 statements.add(setController); | 673 statements.add(setController); |
| 667 | 674 |
| 668 // return :controller.stream; | 675 // return :controller.stream; |
| 669 var completerGet = new VariableGet(controllerVariable); | 676 var completerGet = new VariableGet(controllerVariable); |
| 670 var returnStatement = new ReturnStatement( | 677 var returnStatement = new ReturnStatement( |
| 671 new PropertyGet(completerGet, new Name('stream', helper.asyncLibrary))); | 678 new PropertyGet(completerGet, new Name('stream', helper.asyncLibrary))); |
| 672 statements.add(returnStatement); | 679 statements.add(returnStatement); |
| 673 | 680 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 689 | 696 |
| 690 Statement buildReturn(Statement body) { | 697 Statement buildReturn(Statement body) { |
| 691 // Async* functions cannot return a value. The returns from the function | 698 // Async* functions cannot return a value. The returns from the function |
| 692 // have been translated into breaks from the labeled body. | 699 // have been translated into breaks from the labeled body. |
| 693 return new Block(<Statement>[ | 700 return new Block(<Statement>[ |
| 694 body, | 701 body, |
| 695 new ExpressionStatement(new MethodInvocation( | 702 new ExpressionStatement(new MethodInvocation( |
| 696 new VariableGet(controllerVariable), | 703 new VariableGet(controllerVariable), |
| 697 new Name("close", helper.asyncLibrary), | 704 new Name("close", helper.asyncLibrary), |
| 698 new Arguments(<Expression>[]))), | 705 new Arguments(<Expression>[]))), |
| 699 new ReturnStatement() | 706 new ReturnStatement()..fileOffset = enclosingFunction.fileEndOffset |
| 700 ]); | 707 ]); |
| 701 } | 708 } |
| 702 | 709 |
| 703 TreeNode visitYieldStatement(YieldStatement stmt) { | 710 TreeNode visitYieldStatement(YieldStatement stmt) { |
| 704 Expression expr = expressionRewriter.rewrite(stmt.expression, statements); | 711 Expression expr = expressionRewriter.rewrite(stmt.expression, statements); |
| 705 | 712 |
| 706 var addExpression = new MethodInvocation( | 713 var addExpression = new MethodInvocation( |
| 707 new VariableGet(controllerVariable), | 714 new VariableGet(controllerVariable), |
| 708 new Name(stmt.isYieldStar ? 'addStream' : 'add', helper.asyncLibrary), | 715 new Name(stmt.isYieldStar ? 'addStream' : 'add', helper.asyncLibrary), |
| 709 new Arguments(<Expression>[expr])); | 716 new Arguments(<Expression>[expr]))..fileOffset = stmt.fileOffset; |
| 710 | 717 |
| 711 statements.add(new IfStatement(addExpression, | 718 statements.add(new IfStatement( |
| 712 new ReturnStatement(new NullLiteral()), createContinuationPoint())); | 719 addExpression, |
| 720 new ReturnStatement(new NullLiteral()), |
| 721 createContinuationPoint()..fileOffset = stmt.fileOffset)); |
| 713 return null; | 722 return null; |
| 714 } | 723 } |
| 715 | 724 |
| 716 TreeNode visitReturnStatement(ReturnStatement node) { | 725 TreeNode visitReturnStatement(ReturnStatement node) { |
| 717 // Async* functions cannot return a value. | 726 // Async* functions cannot return a value. |
| 718 assert(node.expression == null || node.expression is NullLiteral); | 727 assert(node.expression == null || node.expression is NullLiteral); |
| 719 statements | 728 statements |
| 720 .add(new BreakStatement(labeledBody)..fileOffset = node.fileOffset); | 729 .add(new BreakStatement(labeledBody)..fileOffset = node.fileOffset); |
| 721 return null; | 730 return null; |
| 722 } | 731 } |
| 723 } | 732 } |
| 724 | 733 |
| 725 class AsyncFunctionRewriter extends AsyncRewriterBase { | 734 class AsyncFunctionRewriter extends AsyncRewriterBase { |
| 726 VariableDeclaration completerVariable; | 735 VariableDeclaration completerVariable; |
| 727 VariableDeclaration returnVariable; | 736 VariableDeclaration returnVariable; |
| 728 | 737 |
| 729 AsyncFunctionRewriter(helper, enclosingFunction) | 738 AsyncFunctionRewriter(helper, enclosingFunction) |
| 730 : super(helper, enclosingFunction); | 739 : super(helper, enclosingFunction); |
| 731 | 740 |
| 732 FunctionNode rewrite() { | 741 FunctionNode rewrite() { |
| 733 var statements = <Statement>[]; | 742 var statements = <Statement>[]; |
| 734 | 743 |
| 735 // var :completer = new Completer.sync(); | 744 // var :completer = new Completer.sync(); |
| 736 completerVariable = new VariableDeclaration(":completer", | 745 completerVariable = new VariableDeclaration(":completer", |
| 737 initializer: new StaticInvocation(helper.completerConstructor, | 746 initializer: new StaticInvocation(helper.completerConstructor, |
| 738 new Arguments([], types: [const DynamicType()])), | 747 new Arguments([], types: [const DynamicType()])) |
| 748 ..fileOffset = enclosingFunction.body.fileOffset, |
| 739 isFinal: true); | 749 isFinal: true); |
| 740 statements.add(completerVariable); | 750 statements.add(completerVariable); |
| 741 | 751 |
| 742 returnVariable = new VariableDeclaration(":return_value"); | 752 returnVariable = new VariableDeclaration(":return_value"); |
| 743 statements.add(returnVariable); | 753 statements.add(returnVariable); |
| 744 | 754 |
| 745 setupAsyncContinuations(statements); | 755 setupAsyncContinuations(statements); |
| 746 | 756 |
| 747 // new Future.microtask(:async_op); | 757 // new Future.microtask(:async_op); |
| 748 var newMicrotaskStatement = new ExpressionStatement(new StaticInvocation( | 758 var newMicrotaskStatement = new ExpressionStatement(new StaticInvocation( |
| 749 helper.futureMicrotaskConstructor, | 759 helper.futureMicrotaskConstructor, |
| 750 new Arguments([new VariableGet(nestedClosureVariable)], | 760 new Arguments([new VariableGet(nestedClosureVariable)], |
| 751 types: [const DynamicType()]))); | 761 types: [const DynamicType()])) |
| 762 ..fileOffset = enclosingFunction.fileOffset); |
| 752 statements.add(newMicrotaskStatement); | 763 statements.add(newMicrotaskStatement); |
| 753 | 764 |
| 754 // return :completer.future; | 765 // return :completer.future; |
| 755 var completerGet = new VariableGet(completerVariable); | 766 var completerGet = new VariableGet(completerVariable); |
| 756 var returnStatement = new ReturnStatement( | 767 var returnStatement = new ReturnStatement( |
| 757 new PropertyGet(completerGet, new Name('future', helper.asyncLibrary))); | 768 new PropertyGet(completerGet, new Name('future', helper.asyncLibrary))); |
| 758 statements.add(returnStatement); | 769 statements.add(returnStatement); |
| 759 | 770 |
| 760 enclosingFunction.body = new Block(statements); | 771 enclosingFunction.body = new Block(statements); |
| 761 enclosingFunction.body.parent = enclosingFunction; | 772 enclosingFunction.body.parent = enclosingFunction; |
| 762 enclosingFunction.asyncMarker = AsyncMarker.Sync; | 773 enclosingFunction.asyncMarker = AsyncMarker.Sync; |
| 774 enclosingFunction.debuggable = false; |
| 763 return enclosingFunction; | 775 return enclosingFunction; |
| 764 } | 776 } |
| 765 | 777 |
| 766 Statement buildCatchBody(exceptionVariable, stackTraceVariable) { | 778 Statement buildCatchBody(exceptionVariable, stackTraceVariable) { |
| 767 return new ExpressionStatement(new MethodInvocation( | 779 return new ExpressionStatement(new MethodInvocation( |
| 768 new VariableGet(completerVariable), | 780 new VariableGet(completerVariable), |
| 769 new Name("completeError", helper.asyncLibrary), | 781 new Name("completeError", helper.asyncLibrary), |
| 770 new Arguments([ | 782 new Arguments([ |
| 771 new VariableGet(exceptionVariable), | 783 new VariableGet(exceptionVariable), |
| 772 new VariableGet(stackTraceVariable) | 784 new VariableGet(stackTraceVariable) |
| 773 ]))); | 785 ]))); |
| 774 } | 786 } |
| 775 | 787 |
| 776 Statement buildReturn(Statement body) { | 788 Statement buildReturn(Statement body) { |
| 777 // Returns from the body have all been translated into assignments to the | 789 // Returns from the body have all been translated into assignments to the |
| 778 // return value variable followed by a break from the labeled body. | 790 // return value variable followed by a break from the labeled body. |
| 779 return new Block(<Statement>[ | 791 return new Block(<Statement>[ |
| 780 body, | 792 body, |
| 781 new ExpressionStatement(new MethodInvocation( | 793 new ExpressionStatement(new MethodInvocation( |
| 782 new VariableGet(completerVariable), | 794 new VariableGet(completerVariable), |
| 783 new Name("complete", helper.asyncLibrary), | 795 new Name("complete", helper.asyncLibrary), |
| 784 new Arguments([new VariableGet(returnVariable)]))), | 796 new Arguments([new VariableGet(returnVariable)]))), |
| 785 new ReturnStatement() | 797 new ReturnStatement()..fileOffset = enclosingFunction.fileEndOffset |
| 786 ]); | 798 ]); |
| 787 } | 799 } |
| 788 | 800 |
| 789 visitReturnStatement(ReturnStatement node) { | 801 visitReturnStatement(ReturnStatement node) { |
| 790 var expr = node.expression == null | 802 var expr = node.expression == null |
| 791 ? new NullLiteral() | 803 ? new NullLiteral() |
| 792 : expressionRewriter.rewrite(node.expression, statements); | 804 : expressionRewriter.rewrite(node.expression, statements); |
| 793 statements | 805 statements |
| 794 .add(new ExpressionStatement(new VariableSet(returnVariable, expr))); | 806 .add(new ExpressionStatement(new VariableSet(returnVariable, expr))); |
| 795 statements | 807 statements |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 findFactoryConstructor(completerClass, 'sync'), | 907 findFactoryConstructor(completerClass, 'sync'), |
| 896 findConstructor(syncIterableClass, ''), | 908 findConstructor(syncIterableClass, ''), |
| 897 findConstructor(streamIteratorClass, ''), | 909 findConstructor(streamIteratorClass, ''), |
| 898 findFactoryConstructor(futureClass, 'microtask'), | 910 findFactoryConstructor(futureClass, 'microtask'), |
| 899 findConstructor(streamControllerClass, ''), | 911 findConstructor(streamControllerClass, ''), |
| 900 findProcedure(asyncLibrary, '_asyncThenWrapperHelper'), | 912 findProcedure(asyncLibrary, '_asyncThenWrapperHelper'), |
| 901 findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'), | 913 findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'), |
| 902 findProcedure(asyncLibrary, '_awaitHelper')); | 914 findProcedure(asyncLibrary, '_awaitHelper')); |
| 903 } | 915 } |
| 904 } | 916 } |
| OLD | NEW |