OLD | NEW |
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 import "dart:math" show max; | 7 import "dart:math" show max; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 | 9 |
10 import 'package:js_runtime/shared/async_await_error_codes.dart' | 10 import 'package:js_runtime/shared/async_await_error_codes.dart' |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 /// | 151 /// |
152 /// Used if there are untransformed loops containing break or continues to | 152 /// Used if there are untransformed loops containing break or continues to |
153 /// targets outside the loop. | 153 /// targets outside the loop. |
154 String outerLabelName; | 154 String outerLabelName; |
155 | 155 |
156 /// If javascript `this` is used, it is accessed via this variable, in the | 156 /// If javascript `this` is used, it is accessed via this variable, in the |
157 /// [bodyName] function. | 157 /// [bodyName] function. |
158 js.VariableUse get self => new js.VariableUse(selfName); | 158 js.VariableUse get self => new js.VariableUse(selfName); |
159 String selfName; | 159 String selfName; |
160 | 160 |
161 final DiagnosticListener diagnosticListener; | 161 final DiagnosticReporter reporter; |
162 // For error reporting only. | 162 // For error reporting only. |
163 Spannable get spannable { | 163 Spannable get spannable { |
164 return (_spannable == null) ? NO_LOCATION_SPANNABLE : _spannable; | 164 return (_spannable == null) ? NO_LOCATION_SPANNABLE : _spannable; |
165 } | 165 } |
166 | 166 |
167 Spannable _spannable; | 167 Spannable _spannable; |
168 | 168 |
169 int _currentLabel = 0; | 169 int _currentLabel = 0; |
170 | 170 |
171 // The highest temporary variable index currently in use. | 171 // The highest temporary variable index currently in use. |
172 int currentTempVarIndex = 0; | 172 int currentTempVarIndex = 0; |
173 // The highest temporary variable index ever in use in this function. | 173 // The highest temporary variable index ever in use in this function. |
174 int tempVarHighWaterMark = 0; | 174 int tempVarHighWaterMark = 0; |
175 Map<int, js.Expression> tempVarNames = new Map<int, js.Expression>(); | 175 Map<int, js.Expression> tempVarNames = new Map<int, js.Expression>(); |
176 | 176 |
177 bool get isAsync => false; | 177 bool get isAsync => false; |
178 bool get isSyncStar => false; | 178 bool get isSyncStar => false; |
179 bool get isAsyncStar => false; | 179 bool get isAsyncStar => false; |
180 | 180 |
181 AsyncRewriterBase(this.diagnosticListener, | 181 AsyncRewriterBase(this.reporter, |
182 spannable, | 182 this._spannable, |
183 this.safeVariableName, | 183 this.safeVariableName, |
184 this.bodyName) | 184 this.bodyName); |
185 : _spannable = spannable; | |
186 | 185 |
187 /// Initialize names used by the subClass. | 186 /// Initialize names used by the subClass. |
188 void initializeNames(); | 187 void initializeNames(); |
189 | 188 |
190 /// Main entry point. | 189 /// Main entry point. |
191 /// Rewrites a sync*/async/async* function to an equivalent normal function. | 190 /// Rewrites a sync*/async/async* function to an equivalent normal function. |
192 /// | 191 /// |
193 /// [spannable] can be passed to have a location for error messages. | 192 /// [spannable] can be passed to have a location for error messages. |
194 js.Fun rewrite(js.Fun node, [Spannable spannable]) { | 193 js.Fun rewrite(js.Fun node, [Spannable spannable]) { |
195 _spannable = spannable; | 194 _spannable = spannable; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 bool shouldTransform(js.Node node) { | 344 bool shouldTransform(js.Node node) { |
346 return analysis.hasAwaitOrYield.contains(node); | 345 return analysis.hasAwaitOrYield.contains(node); |
347 } | 346 } |
348 | 347 |
349 void unsupported(js.Node node) { | 348 void unsupported(js.Node node) { |
350 throw new UnsupportedError( | 349 throw new UnsupportedError( |
351 "Node $node cannot be transformed by the await-sync transformer"); | 350 "Node $node cannot be transformed by the await-sync transformer"); |
352 } | 351 } |
353 | 352 |
354 void unreachable(js.Node node) { | 353 void unreachable(js.Node node) { |
355 diagnosticListener.internalError( | 354 reporter.internalError( |
356 spannable, "Internal error, trying to visit $node"); | 355 spannable, "Internal error, trying to visit $node"); |
357 } | 356 } |
358 | 357 |
359 visitStatement(js.Statement node) { | 358 visitStatement(js.Statement node) { |
360 node.accept(this); | 359 node.accept(this); |
361 } | 360 } |
362 | 361 |
363 /// Visits [node] to ensure its sideeffects are performed, but throwing away | 362 /// Visits [node] to ensure its sideeffects are performed, but throwing away |
364 /// the result. | 363 /// the result. |
365 /// | 364 /// |
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1369 for (js.SwitchClause clause in node.cases) { | 1368 for (js.SwitchClause clause in node.cases) { |
1370 if (clause is js.Case) { | 1369 if (clause is js.Case) { |
1371 labels[i] = newLabel("case"); | 1370 labels[i] = newLabel("case"); |
1372 clauses.add(new js.Case(visitExpression(clause.expression), | 1371 clauses.add(new js.Case(visitExpression(clause.expression), |
1373 gotoAndBreak(labels[i]))); | 1372 gotoAndBreak(labels[i]))); |
1374 } else if (clause is js.Default) { | 1373 } else if (clause is js.Default) { |
1375 labels[i] = newLabel("default"); | 1374 labels[i] = newLabel("default"); |
1376 clauses.add(new js.Default(gotoAndBreak(labels[i]))); | 1375 clauses.add(new js.Default(gotoAndBreak(labels[i]))); |
1377 hasDefault = true; | 1376 hasDefault = true; |
1378 } else { | 1377 } else { |
1379 diagnosticListener.internalError( | 1378 reporter.internalError( |
1380 spannable, "Unknown clause type $clause"); | 1379 spannable, "Unknown clause type $clause"); |
1381 } | 1380 } |
1382 i++; | 1381 i++; |
1383 } | 1382 } |
1384 if (!hasDefault) { | 1383 if (!hasDefault) { |
1385 clauses.add(new js.Default(gotoAndBreak(after))); | 1384 clauses.add(new js.Default(gotoAndBreak(after))); |
1386 } | 1385 } |
1387 withExpression(node.key, (js.Expression key) { | 1386 withExpression(node.key, (js.Expression key) { |
1388 addStatement(new js.Switch(key, clauses)); | 1387 addStatement(new js.Switch(key, clauses)); |
1389 }, store: false); | 1388 }, store: false); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1688 /// - The completer object [completer] | 1687 /// - The completer object [completer] |
1689 final js.Expression asyncHelper; | 1688 final js.Expression asyncHelper; |
1690 | 1689 |
1691 /// Contructor used to initialize the [completer] variable. | 1690 /// Contructor used to initialize the [completer] variable. |
1692 /// | 1691 /// |
1693 /// Specific to async methods. | 1692 /// Specific to async methods. |
1694 final js.Expression newCompleter; | 1693 final js.Expression newCompleter; |
1695 | 1694 |
1696 final js.Expression wrapBody; | 1695 final js.Expression wrapBody; |
1697 | 1696 |
1698 AsyncRewriter(DiagnosticListener diagnosticListener, | 1697 AsyncRewriter(DiagnosticReporter reporter, |
1699 spannable, | 1698 Spannable spannable, |
1700 {this.asyncHelper, | 1699 {this.asyncHelper, |
1701 this.newCompleter, | 1700 this.newCompleter, |
1702 this.wrapBody, | 1701 this.wrapBody, |
1703 String safeVariableName(String proposedName), | 1702 String safeVariableName(String proposedName), |
1704 js.Name bodyName}) | 1703 js.Name bodyName}) |
1705 : super(diagnosticListener, | 1704 : super(reporter, |
1706 spannable, | 1705 spannable, |
1707 safeVariableName, | 1706 safeVariableName, |
1708 bodyName); | 1707 bodyName); |
1709 | 1708 |
1710 @override | 1709 @override |
1711 void addYield(js.DartYield node, js.Expression expression) { | 1710 void addYield(js.DartYield node, js.Expression expression) { |
1712 diagnosticListener.internalError(spannable, | 1711 reporter.internalError(spannable, |
1713 "Yield in non-generating async function"); | 1712 "Yield in non-generating async function"); |
1714 } | 1713 } |
1715 | 1714 |
1716 void addErrorExit() { | 1715 void addErrorExit() { |
1717 beginLabel(rethrowLabel); | 1716 beginLabel(rethrowLabel); |
1718 addStatement(js.js.statement( | 1717 addStatement(js.js.statement( |
1719 "return #thenHelper(#currentError, #errorCode, #completer);", { | 1718 "return #thenHelper(#currentError, #errorCode, #completer);", { |
1720 "thenHelper": asyncHelper, | 1719 "thenHelper": asyncHelper, |
1721 "errorCode": js.number(error_codes.ERROR), | 1720 "errorCode": js.number(error_codes.ERROR), |
1722 "currentError": currentError, | 1721 "currentError": currentError, |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1820 final js.Expression endOfIteration; | 1819 final js.Expression endOfIteration; |
1821 | 1820 |
1822 /// A JS Expression that creates a marker indication a 'yield*' statement. | 1821 /// A JS Expression that creates a marker indication a 'yield*' statement. |
1823 /// | 1822 /// |
1824 /// Called with the stream to yield from. | 1823 /// Called with the stream to yield from. |
1825 final js.Expression yieldStarExpression; | 1824 final js.Expression yieldStarExpression; |
1826 | 1825 |
1827 /// Used by sync* functions to throw exeptions. | 1826 /// Used by sync* functions to throw exeptions. |
1828 final js.Expression uncaughtErrorExpression; | 1827 final js.Expression uncaughtErrorExpression; |
1829 | 1828 |
1830 SyncStarRewriter(DiagnosticListener diagnosticListener, | 1829 SyncStarRewriter(DiagnosticReporter diagnosticListener, |
1831 spannable, | 1830 spannable, |
1832 {this.endOfIteration, | 1831 {this.endOfIteration, |
1833 this.newIterable, | 1832 this.newIterable, |
1834 this.yieldStarExpression, | 1833 this.yieldStarExpression, |
1835 this.uncaughtErrorExpression, | 1834 this.uncaughtErrorExpression, |
1836 String safeVariableName(String proposedName), | 1835 String safeVariableName(String proposedName), |
1837 js.Name bodyName}) | 1836 js.Name bodyName}) |
1838 : super(diagnosticListener, | 1837 : super(diagnosticListener, |
1839 spannable, | 1838 spannable, |
1840 safeVariableName, | 1839 safeVariableName, |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1930 | 1929 |
1931 @override | 1930 @override |
1932 Iterable<js.VariableInitialization> variableInitializations() { | 1931 Iterable<js.VariableInitialization> variableInitializations() { |
1933 List<js.VariableInitialization> variables = | 1932 List<js.VariableInitialization> variables = |
1934 new List<js.VariableInitialization>(); | 1933 new List<js.VariableInitialization>(); |
1935 return variables; | 1934 return variables; |
1936 } | 1935 } |
1937 | 1936 |
1938 @override | 1937 @override |
1939 js.Statement awaitStatement(js.Expression value) { | 1938 js.Statement awaitStatement(js.Expression value) { |
1940 throw diagnosticListener.internalError(spannable, | 1939 throw reporter.internalError(spannable, |
1941 "Sync* functions cannot contain await statements."); | 1940 "Sync* functions cannot contain await statements."); |
1942 } | 1941 } |
1943 | 1942 |
1944 @override | 1943 @override |
1945 void initializeNames() {} | 1944 void initializeNames() {} |
1946 } | 1945 } |
1947 | 1946 |
1948 class AsyncStarRewriter extends AsyncRewriterBase { | 1947 class AsyncStarRewriter extends AsyncRewriterBase { |
1949 | 1948 |
1950 bool get isAsyncStar => true; | 1949 bool get isAsyncStar => true; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1991 /// Called with the value to yield. | 1990 /// Called with the value to yield. |
1992 final js.Expression yieldExpression; | 1991 final js.Expression yieldExpression; |
1993 | 1992 |
1994 /// A JS Expression that creates a marker indication a 'yield*' statement. | 1993 /// A JS Expression that creates a marker indication a 'yield*' statement. |
1995 /// | 1994 /// |
1996 /// Called with the stream to yield from. | 1995 /// Called with the stream to yield from. |
1997 final js.Expression yieldStarExpression; | 1996 final js.Expression yieldStarExpression; |
1998 | 1997 |
1999 final js.Expression wrapBody; | 1998 final js.Expression wrapBody; |
2000 | 1999 |
2001 AsyncStarRewriter(DiagnosticListener diagnosticListener, | 2000 AsyncStarRewriter(DiagnosticReporter reporter, |
2002 spannable, | 2001 Spannable spannable, |
2003 {this.asyncStarHelper, | 2002 {this.asyncStarHelper, |
2004 this.streamOfController, | 2003 this.streamOfController, |
2005 this.newController, | 2004 this.newController, |
2006 this.yieldExpression, | 2005 this.yieldExpression, |
2007 this.yieldStarExpression, | 2006 this.yieldStarExpression, |
2008 this.wrapBody, | 2007 this.wrapBody, |
2009 String safeVariableName(String proposedName), | 2008 String safeVariableName(String proposedName), |
2010 js.Name bodyName}) | 2009 js.Name bodyName}) |
2011 : super(diagnosticListener, | 2010 : super(reporter, |
2012 spannable, | 2011 spannable, |
2013 safeVariableName, | 2012 safeVariableName, |
2014 bodyName); | 2013 bodyName); |
2015 | 2014 |
2016 | 2015 |
2017 /// Translates a yield/yield* in an async* function. | 2016 /// Translates a yield/yield* in an async* function. |
2018 /// | 2017 /// |
2019 /// yield/yield* in an async* function is translated much like the `await` is | 2018 /// yield/yield* in an async* function is translated much like the `await` is |
2020 /// translated in [visitAwait], only the object is wrapped in a | 2019 /// translated in [visitAwait], only the object is wrapped in a |
2021 /// [yieldExpression]/[yieldStarExpression] to let [asyncStarHelper] | 2020 /// [yieldExpression]/[yieldStarExpression] to let [asyncStarHelper] |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2597 return condition || body; | 2596 return condition || body; |
2598 } | 2597 } |
2599 | 2598 |
2600 @override | 2599 @override |
2601 bool visitDartYield(js.DartYield node) { | 2600 bool visitDartYield(js.DartYield node) { |
2602 hasYield = true; | 2601 hasYield = true; |
2603 visit(node.expression); | 2602 visit(node.expression); |
2604 return true; | 2603 return true; |
2605 } | 2604 } |
2606 } | 2605 } |
OLD | NEW |