Chromium Code Reviews| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 return new AsyncFunctionRewriter(helper, node).rewrite(); | 43 return new AsyncFunctionRewriter(helper, node).rewrite(); |
| 44 case AsyncMarker.AsyncStar: | 44 case AsyncMarker.AsyncStar: |
| 45 return new AsyncStarFunctionRewriter(helper, node).rewrite(); | 45 return new AsyncStarFunctionRewriter(helper, node).rewrite(); |
| 46 } | 46 } |
| 47 } | 47 } |
| 48 } | 48 } |
| 49 | 49 |
| 50 abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter { | 50 abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter { |
| 51 final FunctionNode enclosingFunction; | 51 final FunctionNode enclosingFunction; |
| 52 | 52 |
| 53 int currentTryDepth; // Nesting depth for try-blocks. | 53 int currentTryDepth = 0; // Nesting depth for try-blocks. |
| 54 int currentCatchDepth = 0; // Nesting depth for catch-blocks. | 54 int currentCatchDepth = 0; // Nesting depth for catch-blocks. |
| 55 int capturedTryDepth = 0; // Deepest yield point within a try-block. | 55 int capturedTryDepth = 0; // Deepest yield point within a try-block. |
| 56 int capturedCatchDepth = 0; // Deepest yield point within a catch-block. | 56 int capturedCatchDepth = 0; // Deepest yield point within a catch-block. |
| 57 | 57 |
| 58 ContinuationRewriterBase(HelperNodes helper, this.enclosingFunction, | 58 ContinuationRewriterBase(HelperNodes helper, this.enclosingFunction) |
| 59 {this.currentTryDepth: 0}) | |
| 60 : super(helper); | 59 : super(helper); |
| 61 | 60 |
| 62 Statement createContinuationPoint([Expression value]) { | 61 Statement createContinuationPoint([Expression value]) { |
| 63 if (value == null) value = new NullLiteral(); | 62 if (value == null) value = new NullLiteral(); |
| 64 capturedTryDepth = math.max(capturedTryDepth, currentTryDepth); | 63 capturedTryDepth = math.max(capturedTryDepth, currentTryDepth); |
| 65 capturedCatchDepth = math.max(capturedCatchDepth, currentCatchDepth); | 64 capturedCatchDepth = math.max(capturedCatchDepth, currentCatchDepth); |
| 66 return new YieldStatement(value, isNative: true); | 65 return new YieldStatement(value, isNative: true); |
| 67 } | 66 } |
| 68 | 67 |
| 69 TreeNode visitTryCatch(TryCatch node) { | 68 TreeNode visitTryCatch(TryCatch node) { |
| 70 if (node.body != null) { | 69 if (node.body != null) { |
| 71 currentTryDepth++; | 70 currentTryDepth++; |
|
Vyacheslav Egorov (Google)
2017/01/11 17:54:05
Please use prefix and postfix increment consistent
kustermann
2017/01/11 18:34:54
Done.
| |
| 72 node.body = node.body.accept(this); | 71 node.body = node.body.accept(this); |
| 73 node.body?.parent = node; | 72 node.body?.parent = node; |
| 74 currentTryDepth--; | 73 currentTryDepth--; |
| 75 } | 74 } |
| 76 | 75 |
| 77 currentCatchDepth++; | 76 ++currentCatchDepth; |
| 78 transformList(node.catches, this, node); | 77 transformList(node.catches, this, node); |
| 79 currentCatchDepth--; | 78 --currentCatchDepth; |
| 80 return node; | 79 return node; |
| 81 } | 80 } |
| 82 | 81 |
| 83 TreeNode visitTryFinally(TryFinally node) { | 82 TreeNode visitTryFinally(TryFinally node) { |
| 84 if (node.body != null) { | 83 if (node.body != null) { |
| 85 currentTryDepth++; | 84 currentTryDepth++; |
|
Vyacheslav Egorov (Google)
2017/01/11 17:54:05
ditto
kustermann
2017/01/11 18:34:54
Done.
| |
| 86 node.body = node.body.accept(this); | 85 node.body = node.body.accept(this); |
| 87 node.body?.parent = node; | 86 node.body?.parent = node; |
| 88 currentTryDepth--; | 87 currentTryDepth--; |
| 89 } | 88 } |
| 90 if (node.finalizer != null) { | 89 if (node.finalizer != null) { |
| 90 ++currentCatchDepth; | |
| 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 --currentCatchDepth; | |
| 93 } | 94 } |
| 94 return node; | 95 return node; |
| 95 } | 96 } |
| 96 | 97 |
| 97 Iterable<VariableDeclaration> createCapturedTryVariables() => | 98 Iterable<VariableDeclaration> createCapturedTryVariables() => |
| 98 new Iterable.generate(capturedTryDepth, | 99 new Iterable.generate(capturedTryDepth, |
| 99 (depth) => new VariableDeclaration(":saved_try_context_var${depth}")); | 100 (depth) => new VariableDeclaration(":saved_try_context_var${depth}")); |
| 100 | 101 |
| 101 Iterable<VariableDeclaration> createCapturedCatchVariables() => | 102 Iterable<VariableDeclaration> createCapturedCatchVariables() => |
| 102 new Iterable.generate(capturedCatchDepth).expand((depth) => [ | 103 new Iterable.generate(capturedCatchDepth).expand((depth) => [ |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 final VariableDeclaration thenContinuationVariable = | 183 final VariableDeclaration thenContinuationVariable = |
| 183 new VariableDeclaration(":async_op_then"); | 184 new VariableDeclaration(":async_op_then"); |
| 184 final VariableDeclaration catchErrorContinuationVariable = | 185 final VariableDeclaration catchErrorContinuationVariable = |
| 185 new VariableDeclaration(":async_op_error"); | 186 new VariableDeclaration(":async_op_error"); |
| 186 | 187 |
| 187 LabeledStatement labeledBody; | 188 LabeledStatement labeledBody; |
| 188 | 189 |
| 189 ExpressionLifter expressionRewriter; | 190 ExpressionLifter expressionRewriter; |
| 190 | 191 |
| 191 AsyncRewriterBase(helper, enclosingFunction) | 192 AsyncRewriterBase(helper, enclosingFunction) |
| 192 // Body is wrapped in the try-catch so initial currentTryDepth is 1. | 193 : super(helper, enclosingFunction) {} |
| 193 : super(helper, enclosingFunction, currentTryDepth: 1) {} | |
| 194 | 194 |
| 195 void setupAsyncContinuations(List<Statement> statements) { | 195 void setupAsyncContinuations(List<Statement> statements) { |
| 196 expressionRewriter = new ExpressionLifter(this); | 196 expressionRewriter = new ExpressionLifter(this); |
| 197 | 197 |
| 198 // var :async_op_then; | 198 // var :async_op_then; |
| 199 statements.add(thenContinuationVariable); | 199 statements.add(thenContinuationVariable); |
| 200 | 200 |
| 201 // var :async_op_error; | 201 // var :async_op_error; |
| 202 statements.add(catchErrorContinuationVariable); | 202 statements.add(catchErrorContinuationVariable); |
| 203 | 203 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 final boundCatchErrorClosure = new StaticInvocation( | 240 final boundCatchErrorClosure = new StaticInvocation( |
| 241 helper.asyncErrorWrapper, | 241 helper.asyncErrorWrapper, |
| 242 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)])); | 242 new Arguments(<Expression>[new VariableGet(nestedClosureVariable)])); |
| 243 final catchErrorClosureVariableAssign = new ExpressionStatement( | 243 final catchErrorClosureVariableAssign = new ExpressionStatement( |
| 244 new VariableSet( | 244 new VariableSet( |
| 245 catchErrorContinuationVariable, boundCatchErrorClosure)); | 245 catchErrorContinuationVariable, boundCatchErrorClosure)); |
| 246 statements.add(catchErrorClosureVariableAssign); | 246 statements.add(catchErrorClosureVariableAssign); |
| 247 } | 247 } |
| 248 | 248 |
| 249 Statement buildWrappedBody() { | 249 Statement buildWrappedBody() { |
| 250 ++currentTryDepth; | |
| 250 labeledBody = new LabeledStatement(null); | 251 labeledBody = new LabeledStatement(null); |
| 251 labeledBody.body = visitDelimited(enclosingFunction.body) | 252 labeledBody.body = visitDelimited(enclosingFunction.body) |
| 252 ..parent = labeledBody; | 253 ..parent = labeledBody; |
| 254 --currentTryDepth; | |
| 253 | 255 |
| 254 var exceptionVariable = new VariableDeclaration(":exception"); | 256 var exceptionVariable = new VariableDeclaration(":exception"); |
| 255 var stackTraceVariable = new VariableDeclaration(":stack_trace"); | 257 var stackTraceVariable = new VariableDeclaration(":stack_trace"); |
| 256 | 258 |
| 257 return new TryCatch(buildReturn(labeledBody), <Catch>[ | 259 return new TryCatch(buildReturn(labeledBody), <Catch>[ |
| 258 new Catch( | 260 new Catch( |
| 259 exceptionVariable, | 261 exceptionVariable, |
| 260 new Block(<Statement>[ | 262 new Block(<Statement>[ |
| 261 buildCatchBody(exceptionVariable, stackTraceVariable) | 263 buildCatchBody(exceptionVariable, stackTraceVariable) |
| 262 ]), | 264 ]), |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 610 } | 612 } |
| 611 --currentCatchDepth; | 613 --currentCatchDepth; |
| 612 statements.add(stmt); | 614 statements.add(stmt); |
| 613 return null; | 615 return null; |
| 614 } | 616 } |
| 615 | 617 |
| 616 TreeNode visitTryFinally(TryFinally stmt) { | 618 TreeNode visitTryFinally(TryFinally stmt) { |
| 617 ++currentTryDepth; | 619 ++currentTryDepth; |
| 618 stmt.body = visitDelimited(stmt.body)..parent = stmt; | 620 stmt.body = visitDelimited(stmt.body)..parent = stmt; |
| 619 --currentTryDepth; | 621 --currentTryDepth; |
| 622 ++currentCatchDepth; | |
| 620 stmt.finalizer = visitDelimited(stmt.finalizer)..parent = stmt; | 623 stmt.finalizer = visitDelimited(stmt.finalizer)..parent = stmt; |
| 624 --currentCatchDepth; | |
| 621 statements.add(stmt); | 625 statements.add(stmt); |
| 622 return null; | 626 return null; |
| 623 } | 627 } |
| 624 | 628 |
| 625 TreeNode visitYieldStatement(YieldStatement stmt) { | 629 TreeNode visitYieldStatement(YieldStatement stmt) { |
| 626 stmt.expression = expressionRewriter.rewrite(stmt.expression, statements) | 630 stmt.expression = expressionRewriter.rewrite(stmt.expression, statements) |
| 627 ..parent = stmt; | 631 ..parent = stmt; |
| 628 statements.add(stmt); | 632 statements.add(stmt); |
| 629 return null; | 633 return null; |
| 630 } | 634 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 677 var returnStatement = new ReturnStatement( | 681 var returnStatement = new ReturnStatement( |
| 678 new PropertyGet(completerGet, new Name('stream', helper.asyncLibrary))); | 682 new PropertyGet(completerGet, new Name('stream', helper.asyncLibrary))); |
| 679 statements.add(returnStatement); | 683 statements.add(returnStatement); |
| 680 | 684 |
| 681 enclosingFunction.body = new Block(statements); | 685 enclosingFunction.body = new Block(statements); |
| 682 enclosingFunction.body.parent = enclosingFunction; | 686 enclosingFunction.body.parent = enclosingFunction; |
| 683 enclosingFunction.asyncMarker = AsyncMarker.Sync; | 687 enclosingFunction.asyncMarker = AsyncMarker.Sync; |
| 684 return enclosingFunction; | 688 return enclosingFunction; |
| 685 } | 689 } |
| 686 | 690 |
| 691 Statement buildWrappedBody() { | |
| 692 ++currentTryDepth; | |
| 693 Statement body = super.buildWrappedBody(); | |
| 694 --currentTryDepth; | |
| 695 | |
| 696 var finallyBody = new ExpressionStatement(new MethodInvocation( | |
| 697 new VariableGet(controllerVariable), | |
| 698 new Name("close", helper.asyncLibrary), | |
| 699 new Arguments(<Expression>[]))); | |
| 700 | |
| 701 var tryFinally = new TryFinally(body, new Block(<Statement>[finallyBody])); | |
| 702 return tryFinally; | |
| 703 } | |
| 704 | |
| 687 Statement buildCatchBody(exceptionVariable, stackTraceVariable) { | 705 Statement buildCatchBody(exceptionVariable, stackTraceVariable) { |
| 688 return new ExpressionStatement(new MethodInvocation( | 706 return new ExpressionStatement(new MethodInvocation( |
| 689 new VariableGet(controllerVariable), | 707 new VariableGet(controllerVariable), |
| 690 new Name("completeError", helper.asyncLibrary), | 708 new Name("addError", helper.asyncLibrary), |
| 691 new Arguments(<Expression>[ | 709 new Arguments(<Expression>[ |
| 692 new VariableGet(exceptionVariable), | 710 new VariableGet(exceptionVariable), |
| 693 new VariableGet(stackTraceVariable) | 711 new VariableGet(stackTraceVariable) |
| 694 ]))); | 712 ]))); |
| 695 } | 713 } |
| 696 | 714 |
| 697 Statement buildReturn(Statement body) { | 715 Statement buildReturn(Statement body) { |
| 698 // Async* functions cannot return a value. The returns from the function | 716 // Async* functions cannot return a value. The returns from the function |
| 699 // have been translated into breaks from the labeled body. | 717 // have been translated into breaks from the labeled body. |
| 700 return new Block(<Statement>[ | 718 return new Block(<Statement>[ |
| 701 body, | 719 body, |
| 702 new ExpressionStatement(new MethodInvocation( | 720 new ReturnStatement()..fileOffset = enclosingFunction.fileEndOffset, |
| 703 new VariableGet(controllerVariable), | |
| 704 new Name("close", helper.asyncLibrary), | |
| 705 new Arguments(<Expression>[]))), | |
| 706 new ReturnStatement()..fileOffset = enclosingFunction.fileEndOffset | |
| 707 ]); | 721 ]); |
| 708 } | 722 } |
| 709 | 723 |
| 710 TreeNode visitYieldStatement(YieldStatement stmt) { | 724 TreeNode visitYieldStatement(YieldStatement stmt) { |
| 711 Expression expr = expressionRewriter.rewrite(stmt.expression, statements); | 725 Expression expr = expressionRewriter.rewrite(stmt.expression, statements); |
| 712 | 726 |
| 713 var addExpression = new MethodInvocation( | 727 var addExpression = new MethodInvocation( |
| 714 new VariableGet(controllerVariable), | 728 new VariableGet(controllerVariable), |
| 715 new Name(stmt.isYieldStar ? 'addStream' : 'add', helper.asyncLibrary), | 729 new Name(stmt.isYieldStar ? 'addStream' : 'add', helper.asyncLibrary), |
| 716 new Arguments(<Expression>[expr]))..fileOffset = stmt.fileOffset; | 730 new Arguments(<Expression>[expr]))..fileOffset = stmt.fileOffset; |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 907 findFactoryConstructor(completerClass, 'sync'), | 921 findFactoryConstructor(completerClass, 'sync'), |
| 908 findConstructor(syncIterableClass, ''), | 922 findConstructor(syncIterableClass, ''), |
| 909 findConstructor(streamIteratorClass, ''), | 923 findConstructor(streamIteratorClass, ''), |
| 910 findFactoryConstructor(futureClass, 'microtask'), | 924 findFactoryConstructor(futureClass, 'microtask'), |
| 911 findConstructor(streamControllerClass, ''), | 925 findConstructor(streamControllerClass, ''), |
| 912 findProcedure(asyncLibrary, '_asyncThenWrapperHelper'), | 926 findProcedure(asyncLibrary, '_asyncThenWrapperHelper'), |
| 913 findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'), | 927 findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'), |
| 914 findProcedure(asyncLibrary, '_awaitHelper')); | 928 findProcedure(asyncLibrary, '_awaitHelper')); |
| 915 } | 929 } |
| 916 } | 930 } |
| OLD | NEW |