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