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

Side by Side Diff: runtime/lib/core_patch.dart

Issue 944893005: Implement async* functions in VM (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 9 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 | « no previous file | runtime/vm/flow_graph_builder.h » ('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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 import "dart:math"; 5 import "dart:math";
6 import "dart:typed_data"; 6 import "dart:typed_data";
7 7
8 // Equivalent of calling FATAL from C++ code. 8 // Equivalent of calling FATAL from C++ code.
9 _fatal(msg) native "DartCore_fatal"; 9 _fatal(msg) native "DartCore_fatal";
10 10
11 11
12 // We need to pass the exception and stack trace objects as second and third 12 // We need to pass the exception and stack trace objects as second and third
13 // parameter to the continuation. See vm/ast_transformer.cc for usage. 13 // parameter to the continuation. See vm/ast_transformer.cc for usage.
14 void _asyncCatchHelper(catchFunction, continuation) { 14 void _asyncCatchHelper(catchFunction, continuation) {
15 catchFunction((e, s) => continuation(null, e, s)); 15 catchFunction((e, s) => continuation(null, e, s));
16 } 16 }
17 17
18 // The members of this class are cloned and added to each class that 18 // The members of this class are cloned and added to each class that
19 // represents an enum type. 19 // represents an enum type.
20 class _EnumHelper { 20 class _EnumHelper {
21 // Declare the list of enum value names private. When this field is 21 // Declare the list of enum value names private. When this field is
22 // cloned into a user-defined enum class, the field will be inaccessible 22 // cloned into a user-defined enum class, the field will be inaccessible
23 // because of the library-specific name suffix. The toString() function 23 // because of the library-specific name suffix. The toString() function
24 // below can access it because it uses the same name suffix. 24 // below can access it because it uses the same name suffix.
25 static const List<String> _enum_names = null; 25 static const List<String> _enum_names = null;
26 String toString() => _enum_names[index]; 26 String toString() => _enum_names[index];
27 } 27 }
28 28
29 typedef bool SyncGeneratorCallback(Iterator iterator); 29
30 // _AsyncStarStreamController is used by the compiler to implement
31 // async* generator functions.
32 class _AsyncStarStreamController {
33 StreamController controller;
34 Function asyncStarBody;
35 bool isAdding = false;
36 bool onListenReceived = false;
37 bool isScheduled = false;
38
39 Stream get stream => controller.stream;
40
41 void runBody() {
42 isScheduled = false;
43 asyncStarBody();
44 }
45
46 void scheduleGenerator() {
47 if (isScheduled || controller.isPaused || isAdding) {
48 return;
49 }
50 isScheduled = true;
51 scheduleMicrotask(runBody);
52 }
53
54 // Adds element to steam, returns true if the caller should terminate
55 // execution of the generator.
56 //
57 // TODO(hausner): Per spec, the generator should be suspended before
58 // exiting when the stream is closed. We could add a getter like this:
59 // get isCancelled => controller.hasListener;
60 // The generator would translate a 'yield e' statement to
61 // controller.add(e);
62 // suspend;
63 // if (controller.isCanelled) return;
64 bool add(event) {
65 if (!onListenReceived) _fatal("yield before stream is listened to!");
66 // If stream is cancelled, tell caller to exit the async generator.
67 if (!controller.hasListener) {
68 return true;
69 }
70 controller.add(event);
71 scheduleGenerator();
72 return false;
73 }
74
75 // Adds the elements of stream into this controller's stream.
76 // The generator will be scheduled again when all of the
77 // elements of the added stream have been consumed.
78 // Returns true if the caller should terminate
79 // execution of the generator.
80 bool addStream(Stream stream) {
81 if (!onListenReceived) _fatal("yield before stream is listened to!");
82 // If stream is cancelled, tell caller to exit the async generator.
83 if (!controller.hasListener) return true;
84 isAdding = true;
85 var whenDoneAdding =
86 controller.addStream(stream as Stream, cancelOnError: false);
87 whenDoneAdding.then((_) {
88 isAdding = false;
89 scheduleGenerator();
90 });
91 return false;
92 }
93
94 void addError(error, stackTrace) {
95 // If stream is cancelled, tell caller to exit the async generator.
96 if (!controller.hasListener) return;
97 controller.addError(error, stackTrace);
98 // No need to schedule the generator body here. This code is only
99 // called from the catch clause of the implicit try-catch-finally
100 // around the generator body. That is, we are on the error path out
101 // of the generator and do not need to run the generator again.
102 }
103
104 close() {
105 controller.close();
106 }
107
108 _AsyncStarStreamController(this.asyncStarBody) {
109 controller = new StreamController(onListen: this.onListen,
110 onResume: this.onResume,
111 onCancel: this.onCancel);
112 }
113
114 onListen() {
115 assert(!onListenReceived);
116 onListenReceived = true;
117 scheduleGenerator();
118 }
119
120 onResume() {
121 scheduleGenerator();
122 }
123
124 onCancel() {
125 scheduleGenerator();
126 }
127 }
128
30 129
31 // _SyncIterable and _syncIterator are used by the compiler to 130 // _SyncIterable and _syncIterator are used by the compiler to
32 // implement sync* generator functions. A sync* generator allocates 131 // implement sync* generator functions. A sync* generator allocates
33 // and returns a new _SyncIterable object. 132 // and returns a new _SyncIterable object.
133
134 typedef bool SyncGeneratorCallback(Iterator iterator);
135
34 class _SyncIterable extends IterableBase { 136 class _SyncIterable extends IterableBase {
35 // moveNextFn is the closurized body of the generator function. 137 // moveNextFn is the closurized body of the generator function.
36 final SyncGeneratorCallback moveNextFn; 138 final SyncGeneratorCallback moveNextFn;
37 139
38 const _SyncIterable(this.moveNextFn); 140 const _SyncIterable(this.moveNextFn);
39 141
40 get iterator { 142 get iterator {
41 return new _SyncIterator(moveNextFn._clone()); 143 return new _SyncIterator(moveNextFn._clone());
42 } 144 }
43 } 145 }
(...skipping 27 matching lines...) Expand all
71 if (isYieldEach) { 173 if (isYieldEach) {
72 // Spec mandates: it is a dynamic error if the class of [the object 174 // Spec mandates: it is a dynamic error if the class of [the object
73 // returned by yield*] does not implement Iterable. 175 // returned by yield*] does not implement Iterable.
74 yieldEachIterator = (current as Iterable).iterator; 176 yieldEachIterator = (current as Iterable).iterator;
75 continue; 177 continue;
76 } 178 }
77 return true; 179 return true;
78 } 180 }
79 } 181 }
80 } 182 }
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698