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

Side by Side Diff: pkg/compiler/lib/src/js/rewrite_async.dart

Issue 932053002: Support for interpolated declarations in the js parser. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review Created 5 years, 10 months 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 | Annotate | Revision Log
« no previous file with comments | « pkg/compiler/lib/src/js/printer.dart ('k') | pkg/compiler/lib/src/js/template.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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 rewrite_async; 5 library rewrite_async;
6 6
7 // TODO(sigurdm): Avoid using variables in templates. It could blow up memory
8 // use.
9 // TODO(sigurdm): Move the try/catch expression to a js_helper function. 7 // TODO(sigurdm): Move the try/catch expression to a js_helper function.
10 // That would also simplify the sync* case, where the error can just be thrown. 8 // That would also simplify the sync* case, where the error can just be thrown.
11 9
12 import "dart:math" show max; 10 import "dart:math" show max;
13 import 'dart:collection'; 11 import 'dart:collection';
14 12
15 import 'package:_internal/compiler/js_lib/shared/async_await_error_codes.dart' 13 import 'package:_internal/compiler/js_lib/shared/async_await_error_codes.dart'
16 as error_codes; 14 as error_codes;
17 15
18 import "js.dart" as js; 16 import "js.dart" as js;
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 /// Returning from an async* function calls the [streamHelper] with an 592 /// Returning from an async* function calls the [streamHelper] with an
595 /// [endOfIteration] marker. 593 /// [endOfIteration] marker.
596 void addExit() { 594 void addExit() {
597 if (analysis.hasExplicitReturns || isAsyncStar) { 595 if (analysis.hasExplicitReturns || isAsyncStar) {
598 beginLabel(exitLabel); 596 beginLabel(exitLabel);
599 } else { 597 } else {
600 addStatement(new js.Comment("implicit return")); 598 addStatement(new js.Comment("implicit return"));
601 } 599 }
602 switch (async) { 600 switch (async) {
603 case const js.AsyncModifier.async(): 601 case const js.AsyncModifier.async():
604 String returnValue =
605 analysis.hasExplicitReturns ? returnValueName : "null";
606 addStatement(js.js.statement( 602 addStatement(js.js.statement(
607 "return #thenHelper($returnValue, #successCode, " 603 "return #runtimeHelper(#returnValue, #successCode, "
608 "$completerName, null)", { 604 "#completer, null)", {
609 "thenHelper": asyncHelper, 605 "runtimeHelper": asyncHelper,
610 "successCode": js.number(error_codes.SUCCESS)})); 606 "successCode": js.number(error_codes.SUCCESS),
607 "returnValue": analysis.hasExplicitReturns
608 ? returnValueName
609 : new js.LiteralNull(),
610 "completer": completerName}));
611 break; 611 break;
612 case const js.AsyncModifier.syncStar(): 612 case const js.AsyncModifier.syncStar():
613 addStatement(new js.Return(new js.Call(endOfIteration, []))); 613 addStatement(new js.Return(new js.Call(endOfIteration, [])));
614 break; 614 break;
615 case const js.AsyncModifier.asyncStar(): 615 case const js.AsyncModifier.asyncStar():
616 addStatement(js.js.statement( 616 addStatement(js.js.statement(
617 "return #streamHelper(null, #successCode, $controllerName)", { 617 "return #streamHelper(null, #successCode, #controller)", {
618 "streamHelper": streamHelper, 618 "streamHelper": streamHelper,
619 "successCode": js.number(error_codes.SUCCESS)})); 619 "successCode": js.number(error_codes.SUCCESS),
620 "controller": controllerName}));
620 break; 621 break;
621 default: 622 default:
622 diagnosticListener.internalError( 623 diagnosticListener.internalError(
623 spannable, "Internal error, unexpected asyncmodifier $async"); 624 spannable, "Internal error, unexpected asyncmodifier $async");
624 } 625 }
625 if (isAsync || isAsyncStar) { 626 if (isAsync || isAsyncStar) {
626 beginLabel(rethrowLabel); 627 beginLabel(rethrowLabel);
627 addStatement(js.js.statement( 628 addStatement(js.js.statement(
628 "return #thenHelper($currentErrorName, #errorCode, " 629 "return #thenHelper(#currentError, #errorCode, #controller)", {
629 "${isAsync ? completerName : controllerName})", {
630 "thenHelper": isAsync ? asyncHelper : streamHelper, 630 "thenHelper": isAsync ? asyncHelper : streamHelper,
631 "errorCode": js.number(error_codes.ERROR)})); 631 "errorCode": js.number(error_codes.ERROR),
632 "currentError": currentErrorName,
633 "controller": isAsync ? completerName : controllerName}));
632 } else { 634 } else {
633 assert(isSyncStar); 635 assert(isSyncStar);
634 beginLabel(rethrowLabel); 636 beginLabel(rethrowLabel);
635 addStatement(new js.Return(new js.Call(uncaughtErrorExpression, 637 addStatement(new js.Return(new js.Call(uncaughtErrorExpression,
636 [new js.VariableUse(currentErrorName)]))); 638 [new js.VariableUse(currentErrorName)])));
637 } 639 }
638 } 640 }
639 641
640 /// The initial call to [asyncHelper]/[streamHelper]. 642 /// The initial call to [asyncHelper]/[streamHelper].
641 /// 643 ///
642 /// There is no value to await/yield, so the first argument is `null` and 644 /// There is no value to await/yield, so the first argument is `null` and
643 /// also the errorCallback is `null`. 645 /// also the errorCallback is `null`.
644 /// 646 ///
645 /// Returns the [Future]/[Stream] coming from [completerName]/ 647 /// Returns the [Future]/[Stream] coming from [completerName]/
646 /// [controllerName]. 648 /// [controllerName].
647 js.Statement generateInitializer() { 649 js.Statement generateInitializer() {
648 if (isAsync) { 650 if (isAsync) {
649 return js.js.statement( 651 return js.js.statement(
650 "return #asyncHelper(null, $bodyName, $completerName, null);", { 652 "return #asyncHelper(null, #body, #completer, null);", {
651 "asyncHelper": asyncHelper 653 "asyncHelper": asyncHelper,
654 "body": bodyName,
655 "completer": completerName,
652 }); 656 });
653 } else if (isAsyncStar) { 657 } else if (isAsyncStar) {
654 return js.js.statement( 658 return js.js.statement(
655 "return #streamOfController($controllerName);", { 659 "return #streamOfController(#controller);", {
656 "streamOfController": streamOfController 660 "streamOfController": streamOfController,
661 "controller": controllerName,
657 }); 662 });
658 } else { 663 } else {
659 throw diagnosticListener.internalError( 664 throw diagnosticListener.internalError(
660 spannable, "Unexpected asyncModifier: $async"); 665 spannable, "Unexpected asyncModifier: $async");
661 } 666 }
662 } 667 }
663 668
664 /// Rewrites an async/sync*/async* function to a normal Javascript function. 669 /// Rewrites an async/sync*/async* function to a normal Javascript function.
665 /// 670 ///
666 /// The control flow is flattened by simulating 'goto' using a switch in a 671 /// The control flow is flattened by simulating 'goto' using a switch in a
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 visitStatement(body); 826 visitStatement(body);
822 jumpTargets.removeLast(); 827 jumpTargets.removeLast();
823 addExit(); 828 addExit();
824 829
825 List<js.SwitchClause> clauses = labelledParts.keys.map((label) { 830 List<js.SwitchClause> clauses = labelledParts.keys.map((label) {
826 return new js.Case(js.number(label), new js.Block(labelledParts[label])); 831 return new js.Case(js.number(label), new js.Block(labelledParts[label]));
827 }).toList(); 832 }).toList();
828 js.Statement helperBody = 833 js.Statement helperBody =
829 new js.Switch(new js.VariableUse(gotoName), clauses); 834 new js.Switch(new js.VariableUse(gotoName), clauses);
830 if (hasJumpThoughOuterLabel) { 835 if (hasJumpThoughOuterLabel) {
831 helperBody = js.js.statement("$outerLabelName: #", [helperBody]); 836 helperBody = new js.LabeledStatement(outerLabelName, helperBody);
832 } 837 }
833 helperBody = js.js.statement(""" 838 helperBody = js.js.statement("""
834 try { 839 try {
835 #body 840 #body
836 } catch ($errorName){ 841 } catch (#error){
837 $currentErrorName = $errorName; 842 #currentError = #error;
838 $gotoName = $handlerName; 843 #goto = #handler;
839 }""", {"body": helperBody}); 844 }""", {
845 "body": helperBody,
846 "goto": gotoName,
847 "error": errorName,
848 "currentError": currentErrorName,
849 "handler": handlerName,
850 });
840 List<js.VariableInitialization> inits = <js.VariableInitialization>[]; 851 List<js.VariableInitialization> inits = <js.VariableInitialization>[];
841 852
842 js.VariableInitialization makeInit(String name, js.Expression initValue) { 853 js.VariableInitialization makeInit(String name, js.Expression initValue) {
843 return new js.VariableInitialization( 854 return new js.VariableInitialization(
844 new js.VariableDeclaration(name), initValue); 855 new js.VariableDeclaration(name), initValue);
845 } 856 }
846 857
847 inits.add(makeInit(gotoName, js.number(0))); 858 inits.add(makeInit(gotoName, js.number(0)));
848 if (isAsync) { 859 if (isAsync) {
849 inits.add(makeInit(completerName, new js.New(newCompleter, []))); 860 inits.add(makeInit(completerName, new js.New(newCompleter, [])));
(...skipping 21 matching lines...) Expand all
871 return new js.VariableInitialization(decl, null); 882 return new js.VariableInitialization(decl, null);
872 })); 883 }));
873 inits.addAll(new Iterable.generate(tempVarHighWaterMark, 884 inits.addAll(new Iterable.generate(tempVarHighWaterMark,
874 (int i) => makeInit(useTempVar(i + 1).name, null))); 885 (int i) => makeInit(useTempVar(i + 1).name, null)));
875 js.VariableDeclarationList varDecl = new js.VariableDeclarationList(inits); 886 js.VariableDeclarationList varDecl = new js.VariableDeclarationList(inits);
876 // TODO(sigurdm): Explain the difference between these cases. 887 // TODO(sigurdm): Explain the difference between these cases.
877 if (isSyncStar) { 888 if (isSyncStar) {
878 return js.js(""" 889 return js.js("""
879 function (#params) { 890 function (#params) {
880 if (#needsThis) 891 if (#needsThis)
881 var $selfName = this; 892 var #self = this;
882 return new #newIterable(function () { 893 return new #newIterable(function () {
883 #varDecl; 894 #varDecl;
884 return function $bodyName() { 895 return function #body() {
885 while (true) 896 while (true)
886 #helperBody; 897 #helperBody;
887 }; 898 };
888 }); 899 });
889 } 900 }
890 """, { 901 """, {
891 "params": node.params, 902 "params": node.params,
892 "needsThis": analysis.hasThis, 903 "needsThis": analysis.hasThis,
893 "helperBody": helperBody, 904 "helperBody": helperBody,
894 "varDecl": varDecl, 905 "varDecl": varDecl,
895 "newIterable": newIterable 906 "newIterable": newIterable,
907 "body": bodyName,
908 "self": selfName,
896 }); 909 });
897 } 910 }
898 return js.js(""" 911 return js.js("""
899 function (#params) { 912 function (#params) {
900 #varDecl; 913 #varDecl;
901 function $bodyName($errorCodeName, $resultName) { 914 function #bodyName(#errorCode, #result) {
902 if (#hasYield) 915 if (#hasYield)
903 switch ($errorCodeName) { 916 switch (#errorCode) {
904 case #streamWasCanceled: 917 case #STREAM_WAS_CANCELED:
905 $nextName = $nextWhenCanceledName; 918 #next = #nextWhenCanceled;
906 $gotoName = $nextName.pop(); 919 #goto = #next.pop();
907 break; 920 break;
908 case #errorCode: 921 case #ERROR:
909 $currentErrorName = $resultName; 922 #currentError = #result;
910 $gotoName = $handlerName; 923 #goto = #handler;
911 } 924 }
912 else 925 else
913 if ($errorCodeName == #errorCode) { 926 if (#errorCode == #ERROR) {
914 $currentErrorName = $resultName; 927 #currentError = #result;
915 $gotoName = $handlerName; 928 #goto = #handler;
916 } 929 }
917 while (true) 930 while (true)
918 #helperBody; 931 #helperBody;
919 } 932 }
920 #init; 933 #init;
921 }""", { 934 }""", {
922 "params": node.params, 935 "params": node.params,
923 "varDecl": varDecl, 936 "varDecl": varDecl,
924 "streamWasCanceled": js.number(error_codes.STREAM_WAS_CANCELED), 937 "STREAM_WAS_CANCELED": js.number(error_codes.STREAM_WAS_CANCELED),
925 "errorCode": js.number(error_codes.ERROR), 938 "ERROR": js.number(error_codes.ERROR),
926 "hasYield": analysis.hasYield, 939 "hasYield": analysis.hasYield,
927 "helperBody": helperBody, 940 "helperBody": helperBody,
928 "init": generateInitializer() 941 "init": generateInitializer(),
942 "bodyName": bodyName,
943 "currentError": currentErrorName,
944 "goto": gotoName,
945 "handler": handlerName,
946 "next": nextName,
947 "nextWhenCanceled": nextWhenCanceledName,
948 "errorCode": errorCodeName,
949 "result": resultName,
929 }); 950 });
930 } 951 }
931 952
932 @override 953 @override
933 js.Expression visitAccess(js.PropertyAccess node) { 954 js.Expression visitAccess(js.PropertyAccess node) {
934 return withExpression2(node.receiver, node.selector, 955 return withExpression2(node.receiver, node.selector,
935 (receiver, selector) => new js.PropertyAccess(receiver, selector)); 956 (receiver, selector) => new js.PropertyAccess(receiver, selector));
936 } 957 }
937 958
938 @override 959 @override
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 /// 998 ///
978 /// See the comments of [visitFun] for an example. 999 /// See the comments of [visitFun] for an example.
979 @override 1000 @override
980 js.Expression visitAwait(js.Await node) { 1001 js.Expression visitAwait(js.Await node) {
981 assert(isAsync || isAsyncStar); 1002 assert(isAsync || isAsyncStar);
982 int afterAwait = newLabel("returning from await."); 1003 int afterAwait = newLabel("returning from await.");
983 withExpression(node.expression, (js.Expression value) { 1004 withExpression(node.expression, (js.Expression value) {
984 addStatement(setGotoVariable(afterAwait)); 1005 addStatement(setGotoVariable(afterAwait));
985 addStatement(js.js.statement(""" 1006 addStatement(js.js.statement("""
986 return #asyncHelper(#value, 1007 return #asyncHelper(#value,
987 $bodyName, 1008 #body,
988 ${isAsync ? completerName : controllerName}); 1009 #controller);
989 """, { 1010 """, {
990 "asyncHelper": isAsync ? asyncHelper : streamHelper, 1011 "asyncHelper": isAsync ? asyncHelper : streamHelper,
991 "value": value, 1012 "value": value,
1013 "body": bodyName,
1014 "controller": isAsync ? completerName : controllerName,
992 })); 1015 }));
993 }, store: false); 1016 }, store: false);
994 beginLabel(afterAwait); 1017 beginLabel(afterAwait);
995 return new js.VariableUse(resultName); 1018 return new js.VariableUse(resultName);
996 } 1019 }
997 1020
998 /// Checks if [node] is the variable named [resultName]. 1021 /// Checks if [node] is the variable named [resultName].
999 /// 1022 ///
1000 /// [resultName] is used to hold the result of a transformed computation 1023 /// [resultName] is used to hold the result of a transformed computation
1001 /// for example the result of awaiting, or the result of a conditional or 1024 /// for example the result of awaiting, or the result of a conditional or
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 // Ignore other nodes. 1181 // Ignore other nodes.
1159 } 1182 }
1160 jumpStack = jumpStack.reversed.toList(); 1183 jumpStack = jumpStack.reversed.toList();
1161 // As the program jumps directly to the top of the stack, it is taken off 1184 // As the program jumps directly to the top of the stack, it is taken off
1162 // now. 1185 // now.
1163 int firstTarget = jumpStack.removeLast(); 1186 int firstTarget = jumpStack.removeLast();
1164 if (jumpStack.isNotEmpty) { 1187 if (jumpStack.isNotEmpty) {
1165 hasJumpThroughFinally = true; 1188 hasJumpThroughFinally = true;
1166 js.Expression jsJumpStack = new js.ArrayInitializer( 1189 js.Expression jsJumpStack = new js.ArrayInitializer(
1167 jumpStack.map((int label) => js.number(label)).toList()); 1190 jumpStack.map((int label) => js.number(label)).toList());
1168 addStatement(js.js.statement("$nextName = #", [jsJumpStack])); 1191 addStatement(js.js.statement("# = #", [nextName, jsJumpStack]));
1169 } 1192 }
1170 addGoto(firstTarget); 1193 addGoto(firstTarget);
1171 } 1194 }
1172 1195
1173 @override 1196 @override
1174 void visitDefault(js.Default node) => unreachable(node); 1197 void visitDefault(js.Default node) => unreachable(node);
1175 1198
1176 @override 1199 @override
1177 void visitDo(js.Do node) { 1200 void visitDo(js.Do node) {
1178 if (!shouldTransform(node)) { 1201 if (!shouldTransform(node)) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 } 1354 }
1332 beginLabel(joinLabel); 1355 beginLabel(joinLabel);
1333 } 1356 }
1334 1357
1335 @override 1358 @override
1336 visitInterpolatedExpression(js.InterpolatedExpression node) { 1359 visitInterpolatedExpression(js.InterpolatedExpression node) {
1337 return unsupported(node); 1360 return unsupported(node);
1338 } 1361 }
1339 1362
1340 @override 1363 @override
1364 visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
1365 return unsupported(node);
1366 }
1367
1368 @override
1341 visitInterpolatedLiteral(js.InterpolatedLiteral node) => unsupported(node); 1369 visitInterpolatedLiteral(js.InterpolatedLiteral node) => unsupported(node);
1342 1370
1343 @override 1371 @override
1344 visitInterpolatedParameter(js.InterpolatedParameter node) { 1372 visitInterpolatedParameter(js.InterpolatedParameter node) {
1345 return unsupported(node); 1373 return unsupported(node);
1346 } 1374 }
1347 1375
1348 @override 1376 @override
1349 visitInterpolatedSelector(js.InterpolatedSelector node) { 1377 visitInterpolatedSelector(js.InterpolatedSelector node) {
1350 return unsupported(node); 1378 return unsupported(node);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 1506
1479 @override 1507 @override
1480 js.Expression visitRegExpLiteral(js.RegExpLiteral node) => node; 1508 js.Expression visitRegExpLiteral(js.RegExpLiteral node) => node;
1481 1509
1482 @override 1510 @override
1483 void visitReturn(js.Return node) { 1511 void visitReturn(js.Return node) {
1484 assert(node.value == null || !isSyncStar && !isAsyncStar); 1512 assert(node.value == null || !isSyncStar && !isAsyncStar);
1485 js.Node target = analysis.targets[node]; 1513 js.Node target = analysis.targets[node];
1486 if (node.value != null) { 1514 if (node.value != null) {
1487 withExpression(node.value, (js.Expression value) { 1515 withExpression(node.value, (js.Expression value) {
1488 addStatement(js.js.statement("$returnValueName = #", [value])); 1516 addStatement(js.js.statement("# = #", [returnValueName, value]));
1489 }, store: false); 1517 }, store: false);
1490 } 1518 }
1491 translateJump(target, exitLabel); 1519 translateJump(target, exitLabel);
1492 } 1520 }
1493 1521
1494 @override 1522 @override
1495 void visitSwitch(js.Switch node) { 1523 void visitSwitch(js.Switch node) {
1496 if (!node.cases.any(shouldTransform)) { 1524 if (!node.cases.any(shouldTransform)) {
1497 // If only the key has an await, translation can be simplified. 1525 // If only the key has an await, translation can be simplified.
1498 bool oldInsideUntranslated = insideUntranslatedBreakable; 1526 bool oldInsideUntranslated = insideUntranslatedBreakable;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 1687
1660 js.Node last = jumpTargets.removeLast(); 1688 js.Node last = jumpTargets.removeLast();
1661 assert(last == node); 1689 assert(last == node);
1662 1690
1663 if (node.finallyPart == null) { 1691 if (node.finallyPart == null) {
1664 setErrorHandler(); 1692 setErrorHandler();
1665 addGoto(afterFinallyLabel); 1693 addGoto(afterFinallyLabel);
1666 } else { 1694 } else {
1667 // The handler is reset as the first thing in the finally block. 1695 // The handler is reset as the first thing in the finally block.
1668 addStatement( 1696 addStatement(
1669 js.js.statement("$nextName = [#];", [js.number(afterFinallyLabel)])); 1697 js.js.statement("# = [#];",
1698 [nextName, js.number(afterFinallyLabel)]));
1670 addGoto(finallyLabel); 1699 addGoto(finallyLabel);
1671 } 1700 }
1672 1701
1673 if (node.catchPart != null) { 1702 if (node.catchPart != null) {
1674 beginLabel(handlerLabel); 1703 beginLabel(handlerLabel);
1675 // [uncaughtLabel] is the handler for the code in the catch-part. 1704 // [uncaughtLabel] is the handler for the code in the catch-part.
1676 // It ensures that [nextName] is set up to run the right finally blocks. 1705 // It ensures that [nextName] is set up to run the right finally blocks.
1677 handlerLabels[node.catchPart] = uncaughtLabel; 1706 handlerLabels[node.catchPart] = uncaughtLabel;
1678 jumpTargets.add(node.catchPart); 1707 jumpTargets.add(node.catchPart);
1679 setErrorHandler(); 1708 setErrorHandler();
1680 // The catch declaration name can shadow outer variables, so a fresh name 1709 // The catch declaration name can shadow outer variables, so a fresh name
1681 // is needed to avoid collisions. See Ecma 262, 3rd edition, 1710 // is needed to avoid collisions. See Ecma 262, 3rd edition,
1682 // section 12.14. 1711 // section 12.14.
1683 String errorRename = freshName(node.catchPart.declaration.name); 1712 String errorRename = freshName(node.catchPart.declaration.name);
1684 localVariables.add(new js.VariableDeclaration(errorRename)); 1713 localVariables.add(new js.VariableDeclaration(errorRename));
1685 variableRenamings 1714 variableRenamings
1686 .add(new Pair(node.catchPart.declaration.name, errorRename)); 1715 .add(new Pair(node.catchPart.declaration.name, errorRename));
1687 addExpressionStatement(new js.Assignment( 1716 addExpressionStatement(new js.Assignment(
1688 new js.VariableUse(errorRename), 1717 new js.VariableUse(errorRename),
1689 new js.VariableUse(currentErrorName))); 1718 new js.VariableUse(currentErrorName)));
1690 visitStatement(node.catchPart.body); 1719 visitStatement(node.catchPart.body);
1691 variableRenamings.removeLast(); 1720 variableRenamings.removeLast();
1692 if (node.finallyPart != null) { 1721 if (node.finallyPart != null) {
1693 // The error has been caught, so after the finally, continue after the 1722 // The error has been caught, so after the finally, continue after the
1694 // try. 1723 // try.
1695 addStatement(js.js.statement("$nextName = [#];", 1724 addStatement(js.js.statement("# = [#];",
1696 [js.number(afterFinallyLabel)])); 1725 [nextName, js.number(afterFinallyLabel)]));
1697 addGoto(finallyLabel); 1726 addGoto(finallyLabel);
1698 } else { 1727 } else {
1699 addGoto(afterFinallyLabel); 1728 addGoto(afterFinallyLabel);
1700 } 1729 }
1701 js.Node last = jumpTargets.removeLast(); 1730 js.Node last = jumpTargets.removeLast();
1702 assert(last == node.catchPart); 1731 assert(last == node.catchPart);
1703 } 1732 }
1704 1733
1705 // The "uncaught"-handler tells the finally-block to continue with 1734 // The "uncaught"-handler tells the finally-block to continue with
1706 // the enclosing finally-blocks until the current catch-handler. 1735 // the enclosing finally-blocks until the current catch-handler.
1707 beginLabel(uncaughtLabel); 1736 beginLabel(uncaughtLabel);
1708 1737
1709 List<int> enclosingFinallies = _finalliesUpToAndEnclosingHandler(); 1738 List<int> enclosingFinallies = _finalliesUpToAndEnclosingHandler();
1710 1739
1711 int nextLabel = enclosingFinallies.removeLast(); 1740 int nextLabel = enclosingFinallies.removeLast();
1712 if (enclosingFinallies.isNotEmpty) { 1741 if (enclosingFinallies.isNotEmpty) {
1713 // [enclosingFinallies] can be empty if there is no surrounding finally 1742 // [enclosingFinallies] can be empty if there is no surrounding finally
1714 // blocks. Then [nextLabel] will be [rethrowLabel]. 1743 // blocks. Then [nextLabel] will be [rethrowLabel].
1715 addStatement( 1744 addStatement(
1716 js.js.statement("$nextName = #;", new js.ArrayInitializer( 1745 js.js.statement("# = #;", [nextName, new js.ArrayInitializer(
1717 enclosingFinallies.map(js.number).toList()))); 1746 enclosingFinallies.map(js.number).toList())]));
1718 } 1747 }
1719 if (node.finallyPart == null) { 1748 if (node.finallyPart == null) {
1720 // The finally-block belonging to [node] will be visited because of 1749 // The finally-block belonging to [node] will be visited because of
1721 // fallthrough. If it does not exist, add an explicit goto. 1750 // fallthrough. If it does not exist, add an explicit goto.
1722 addGoto(nextLabel); 1751 addGoto(nextLabel);
1723 } 1752 }
1724 if (node.finallyPart != null) { 1753 if (node.finallyPart != null) {
1725 js.Node last = jumpTargets.removeLast(); 1754 js.Node last = jumpTargets.removeLast();
1726 assert(last == node.finallyPart); 1755 assert(last == node.finallyPart);
1727 1756
1728 beginLabel(finallyLabel); 1757 beginLabel(finallyLabel);
1729 setErrorHandler(); 1758 setErrorHandler();
1730 visitStatement(node.finallyPart); 1759 visitStatement(node.finallyPart);
1731 addStatement(new js.Comment("// goto the next finally handler")); 1760 addStatement(new js.Comment("// goto the next finally handler"));
1732 addStatement(js.js.statement("$gotoName = $nextName.pop();")); 1761 addStatement(js.js.statement("# = #.pop();", [gotoName, nextName]));
1733 addBreak(); 1762 addBreak();
1734 } 1763 }
1735 beginLabel(afterFinallyLabel); 1764 beginLabel(afterFinallyLabel);
1736 } 1765 }
1737 1766
1738 @override 1767 @override
1739 visitVariableDeclaration(js.VariableDeclaration node) { 1768 visitVariableDeclaration(js.VariableDeclaration node) {
1740 unreachable(node); 1769 unreachable(node);
1741 } 1770 }
1742 1771
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1825 /// must be run in case the stream was canceled. 1854 /// must be run in case the stream was canceled.
1826 void addAsyncYield(js.DartYield node, js.Expression expression) { 1855 void addAsyncYield(js.DartYield node, js.Expression expression) {
1827 assert(isAsyncStar); 1856 assert(isAsyncStar);
1828 // Find all the finally blocks that should be performed if the stream is 1857 // Find all the finally blocks that should be performed if the stream is
1829 // canceled during the yield. 1858 // canceled during the yield.
1830 // At the bottom of the stack is the return label. 1859 // At the bottom of the stack is the return label.
1831 List<int> enclosingFinallyLabels = <int>[exitLabel]; 1860 List<int> enclosingFinallyLabels = <int>[exitLabel];
1832 enclosingFinallyLabels.addAll(jumpTargets 1861 enclosingFinallyLabels.addAll(jumpTargets
1833 .where((js.Node node) => finallyLabels[node] != null) 1862 .where((js.Node node) => finallyLabels[node] != null)
1834 .map((js.Block node) => finallyLabels[node])); 1863 .map((js.Block node) => finallyLabels[node]));
1835 addStatement(js.js.statement("$nextWhenCanceledName = #", 1864 addStatement(js.js.statement("# = #;",
1836 [new js.ArrayInitializer(enclosingFinallyLabels.map(js.number) 1865 [nextWhenCanceledName, new js.ArrayInitializer(
1837 .toList())])); 1866 enclosingFinallyLabels.map(js.number).toList())]));
1838 addStatement(js.js.statement(""" 1867 addStatement(js.js.statement("""
1839 return #streamHelper(#yieldExpression(#expression), 1868 return #streamHelper(#yieldExpression(#expression), #body,
1840 $bodyName, $controllerName);""", { 1869 #controller);""", {
1841 "streamHelper": streamHelper, 1870 "streamHelper": streamHelper,
1842 "yieldExpression": node.hasStar ? yieldStarExpression : yieldExpression, 1871 "yieldExpression": node.hasStar ? yieldStarExpression : yieldExpression,
1843 "expression": expression, 1872 "expression": expression,
1873 "body": bodyName,
1874 "controller": controllerName,
1844 })); 1875 }));
1845 } 1876 }
1846 1877
1847 @override 1878 @override
1848 void visitDartYield(js.DartYield node) { 1879 void visitDartYield(js.DartYield node) {
1849 assert(isSyncStar || isAsyncStar); 1880 assert(isSyncStar || isAsyncStar);
1850 int label = newLabel("after yield"); 1881 int label = newLabel("after yield");
1851 // Don't do a break here for the goto, but instead a return in either 1882 // Don't do a break here for the goto, but instead a return in either
1852 // addSynYield or addAsyncYield. 1883 // addSynYield or addAsyncYield.
1853 withExpression(node.expression, (js.Expression expression) { 1884 withExpression(node.expression, (js.Expression expression) {
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
2082 bool otherwise = visit(node.otherwise); 2113 bool otherwise = visit(node.otherwise);
2083 return condition || then || otherwise; 2114 return condition || then || otherwise;
2084 } 2115 }
2085 2116
2086 @override 2117 @override
2087 bool visitInterpolatedExpression(js.InterpolatedExpression node) { 2118 bool visitInterpolatedExpression(js.InterpolatedExpression node) {
2088 return unsupported(node); 2119 return unsupported(node);
2089 } 2120 }
2090 2121
2091 @override 2122 @override
2123 bool visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
2124 return unsupported(node);
2125 }
2126
2127 @override
2092 bool visitInterpolatedLiteral(js.InterpolatedLiteral node) { 2128 bool visitInterpolatedLiteral(js.InterpolatedLiteral node) {
2093 return unsupported(node); 2129 return unsupported(node);
2094 } 2130 }
2095 2131
2096 @override 2132 @override
2097 bool visitInterpolatedParameter(js.InterpolatedParameter node) { 2133 bool visitInterpolatedParameter(js.InterpolatedParameter node) {
2098 return unsupported(node); 2134 return unsupported(node);
2099 } 2135 }
2100 2136
2101 @override 2137 @override
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
2271 return condition || body; 2307 return condition || body;
2272 } 2308 }
2273 2309
2274 @override 2310 @override
2275 bool visitDartYield(js.DartYield node) { 2311 bool visitDartYield(js.DartYield node) {
2276 hasYield = true; 2312 hasYield = true;
2277 visit(node.expression); 2313 visit(node.expression);
2278 return true; 2314 return true;
2279 } 2315 }
2280 } 2316 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js/printer.dart ('k') | pkg/compiler/lib/src/js/template.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698