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

Side by Side Diff: runtime/vm/ast_transformer.cc

Issue 447003003: Introduce await (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed comments Created 6 years, 4 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 | « runtime/vm/ast_transformer.h ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
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.
4
5 #include "vm/ast_transformer.h"
6
7 #include "vm/parser.h"
8
9 namespace dart {
10
11 // Quick access to the locally defined isolate() method.
12 #define I (isolate())
13
14 // Nodes that are unreachable from already parsed expressions.
15 #define FOR_EACH_UNREACHABLE_NODE(V) \
16 V(Case) \
17 V(CatchClause) \
18 V(CloneContext) \
19 V(ClosureCall) \
20 V(DoWhile) \
21 V(If) \
22 V(InlinedFinally) \
23 V(For) \
24 V(Jump) \
25 V(LoadInstanceField) \
26 V(NativeBody) \
27 V(Primary) \
28 V(Return) \
29 V(Sequence) \
30 V(StoreInstanceField) \
31 V(Switch) \
32 V(TryCatch) \
33 V(While)
34
35 #define DEFINE_UNREACHABLE(BaseName) \
36 void AwaitTransformer::Visit##BaseName##Node(BaseName##Node* node) { \
37 UNREACHABLE(); \
38 }
39
40 FOR_EACH_UNREACHABLE_NODE(DEFINE_UNREACHABLE)
41 #undef DEFINE_UNREACHABLE
42
43
44 AstNode* AwaitTransformer::Transform(AstNode* expr) {
45 expr->Visit(this);
46 return result_;
47 }
48
49
50 LocalVariable* AwaitTransformer::EnsureCurrentTempVar() {
51 const char* await_temp_prefix = ":await_temp_var_";
52 const String& cnt_str = String::ZoneHandle(I,
53 String::NewFormatted(
54 "%s%" Pd "", await_temp_prefix, temp_cnt_));
55 const String& symbol = String::ZoneHandle(I, Symbols::New(cnt_str));
56 ASSERT(!symbol.IsNull());
57 LocalVariable* await_tmp =
58 parsed_function_->await_temps_scope()->LookupVariable(symbol, false);
59 if (await_tmp == NULL) {
60 await_tmp = new(I) LocalVariable(
61 Scanner::kNoSourcePos,
62 symbol,
63 Type::ZoneHandle(I, Type::DynamicType()));
64 parsed_function_->await_temps_scope()->AddVariable(await_tmp);
65 }
66 return await_tmp;
67 }
68
69
70 LocalVariable* AwaitTransformer::AddToPreambleNewTempVar(AstNode* node) {
71 LocalVariable* tmp_var = EnsureCurrentTempVar();
72 preamble_->Add(new(I) StoreLocalNode(Scanner::kNoSourcePos, tmp_var, node));
73 NextTempVar();
74 return tmp_var;
75 }
76
77
78 void AwaitTransformer::VisitLiteralNode(LiteralNode* node) {
79 result_ = node;
80 }
81
82
83 void AwaitTransformer::VisitTypeNode(TypeNode* node) {
84 result_ = new(I) TypeNode(node->token_pos(), node->type());
85 }
86
87
88
89 void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
90 // Await transformation:
91 //
92 // :await_temp_var_X = <expr>;
93 // :result_param = :await_temp_var_X;
94 // if (:result_param is Future) {
95 // // :result_param.then(:async_op);
96 // }
97 // :await_temp_var_(X+1) = :result_param;
98
99 LocalVariable* async_op = preamble_->scope()->LookupVariable(
100 Symbols::AsyncOperation(), false);
101 ASSERT(async_op != NULL);
102 LocalVariable* result_param = preamble_->scope()->LookupVariable(
103 Symbols::AsyncOperationParam(), false);
104 ASSERT(result_param != NULL);
105
106 node->expr()->Visit(this);
107 preamble_->Add(new(I) StoreLocalNode(Scanner::kNoSourcePos,
108 result_param,
109 result_));
110 LoadLocalNode* load_result_param = new(I) LoadLocalNode(
111 Scanner::kNoSourcePos, result_param);
112 SequenceNode* is_future_branch = new(I) SequenceNode(
113 Scanner::kNoSourcePos, preamble_->scope());
114 ArgumentListNode* args = new(I) ArgumentListNode(Scanner::kNoSourcePos);
115 args->Add(new(I) LoadLocalNode(Scanner::kNoSourcePos, async_op));
116 // TODO(mlippautz): Once continuations are supported, just call .then().
117 // is_future_branch->Add(new(I) InstanceCallNode(
118 // Scanner::kNoSourcePos, load_result_param, Symbols::FutureThen(), args));
119 //
120 // For now, throw an exception.
121 const String& exception = String::ZoneHandle(
122 I, String::New("awaitable futures not yet supported", Heap::kOld));
123 is_future_branch->Add(new(I) ThrowNode(
124 Scanner::kNoSourcePos,
125 new(I) LiteralNode(
126 Scanner::kNoSourcePos,
127 String::ZoneHandle(I, Symbols::New(exception))),
128 NULL));
129 const Class& cls = Class::ZoneHandle(
130 I, library_.LookupClass(Symbols::Future()));
131 const AbstractType& future_type = AbstractType::ZoneHandle(I,
132 cls.RareType());
133 ASSERT(!future_type.IsNull());
134 TypeNode* future_type_node = new(I) TypeNode(
135 Scanner::kNoSourcePos, future_type);
136 IfNode* is_future_if = new(I) IfNode(
137 Scanner::kNoSourcePos,
138 new(I) ComparisonNode(Scanner::kNoSourcePos,
139 Token::kIS,
140 load_result_param,
141 future_type_node),
142 is_future_branch,
143 NULL);
144 preamble_->Add(is_future_if);
145
146 // TODO(mlippautz): Join for await needs to happen here.
147
148 LocalVariable* result = AddToPreambleNewTempVar(new(I) LoadLocalNode(
149 Scanner::kNoSourcePos, result_param));
150 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
151 }
152
153
154 // Transforms boolean expressions into a sequence of evaluatons that only lazily
155 // evaluate subexpressions.
156 //
157 // Example:
158 //
159 // (a || b) only evaluates b if a is false
160 //
161 // Transformation (roughly):
162 //
163 // t_1 = a;
164 // if (!t_1) {
165 // t_2 = b;
166 // }
167 // t_3 = t_1 || t_2; // Compiler takes care that lazy evaluation takes place
168 // on this level.
169 AstNode* AwaitTransformer::LazyTransform(const Token::Kind logical_op,
170 AstNode* new_left,
171 AstNode* right) {
172 ASSERT(logical_op == Token::kAND || logical_op == Token::kOR);
173 AstNode* result = NULL;
174 const Token::Kind compare_logical_op = (logical_op == Token::kAND) ?
175 Token::kEQ : Token::kNE;
176 SequenceNode* eval = new(I) SequenceNode(
177 Scanner::kNoSourcePos, preamble_->scope());
178 SequenceNode* saved_preamble = preamble_;
179 preamble_ = eval;
180 result = Transform(right);
181 preamble_ = saved_preamble;
182 IfNode* right_body = new(I) IfNode(
183 Scanner::kNoSourcePos,
184 new(I) ComparisonNode(
185 Scanner::kNoSourcePos,
186 compare_logical_op,
187 new_left,
188 new(I) LiteralNode(Scanner::kNoSourcePos, Bool::True())),
189 eval,
190 NULL);
191 preamble_->Add(right_body);
192 return result;
193 }
194
195
196 void AwaitTransformer::VisitBinaryOpNode(BinaryOpNode* node) {
197 node->left()->Visit(this);
198 AstNode* new_left = result_;
199 AstNode* new_right = NULL;
200 // Preserve lazy evaluaton.
201 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
202 new_right = LazyTransform(node->kind(), new_left, node->right());
203 } else {
204 new_right = Transform(node->right());
205 }
206 LocalVariable* result = AddToPreambleNewTempVar(
207 new(I) BinaryOpNode(node->token_pos(),
208 node->kind(),
209 new_left,
210 new_right));
211 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
212 }
213
214
215 void AwaitTransformer::VisitBinaryOpWithMask32Node(
216 BinaryOpWithMask32Node* node) {
217 node->left()->Visit(this);
218 AstNode* new_left = result_;
219 AstNode* new_right = NULL;
220 // Preserve lazy evaluaton.
221 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
222 new_right = LazyTransform(node->kind(), new_left, node->right());
223 } else {
224 new_right = Transform(node->right());
225 }
226 LocalVariable* result = AddToPreambleNewTempVar(
227 new(I) BinaryOpWithMask32Node(node->token_pos(),
228 node->kind(),
229 new_left,
230 new_right,
231 node->mask32()));
232 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
233 }
234
235
236 void AwaitTransformer::VisitComparisonNode(ComparisonNode* node) {
237 AstNode* new_left = Transform(node->left());
238 AstNode* new_right = Transform(node->right());
239 LocalVariable* result = AddToPreambleNewTempVar(
240 new(I) ComparisonNode(node->token_pos(),
241 node->kind(),
242 new_left,
243 new_right));
244 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
245 }
246
247
248 void AwaitTransformer::VisitUnaryOpNode(UnaryOpNode* node) {
249 AstNode* new_operand = Transform(node->operand());
250 LocalVariable* result = AddToPreambleNewTempVar(
251 new(I) UnaryOpNode(node->token_pos(), node->kind(), new_operand));
252 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
253 }
254
255
256 // ::= (<condition>) ? <true-branch> : <false-branch>
257 //
258 void AwaitTransformer::VisitConditionalExprNode(ConditionalExprNode* node) {
259 AstNode* new_condition = Transform(node->condition());
260 SequenceNode* new_true = new(I) SequenceNode(
261 Scanner::kNoSourcePos, preamble_->scope());
262 SequenceNode* saved_preamble = preamble_;
263 preamble_ = new_true;
264 AstNode* new_true_result = Transform(node->true_expr());
265 SequenceNode* new_false = new(I) SequenceNode(
266 Scanner::kNoSourcePos, preamble_->scope());
267 preamble_ = new_false;
268 AstNode* new_false_result = Transform(node->false_expr());
269 preamble_ = saved_preamble;
270 IfNode* new_if = new(I) IfNode(Scanner::kNoSourcePos,
271 new_condition,
272 new_true,
273 new_false);
274 preamble_->Add(new_if);
275 LocalVariable* result = AddToPreambleNewTempVar(
276 new(I) ConditionalExprNode(Scanner::kNoSourcePos,
277 new_condition,
278 new_true_result,
279 new_false_result));
280 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
281 }
282
283
284 void AwaitTransformer::VisitArgumentListNode(ArgumentListNode* node) {
285 ArgumentListNode* new_args = new(I) ArgumentListNode(node->token_pos());
286 for (intptr_t i = 0; i < node->length(); i++) {
287 new_args->Add(Transform(node->NodeAt(i)));
288 }
289 result_ = new_args;
290 }
291
292
293 void AwaitTransformer::VisitArrayNode(ArrayNode* node) {
294 GrowableArray<AstNode*> new_elements;
295 for (intptr_t i = 0; i < node->length(); i++) {
296 new_elements.Add(Transform(node->ElementAt(i)));
297 }
298 result_ = new(I) ArrayNode(node->token_pos(), node->type(), new_elements);
299 }
300
301
302 void AwaitTransformer::VisitStringInterpolateNode(StringInterpolateNode* node) {
303 ArrayNode* new_value = Transform(node->value())->AsArrayNode();
304 LocalVariable* result = AddToPreambleNewTempVar(
305 new(I) StringInterpolateNode(node->token_pos(),
306 new_value));
307 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
308 }
309
310
311 void AwaitTransformer::VisitClosureNode(ClosureNode* node) {
312 AstNode* new_receiver = node->receiver();
313 if (new_receiver != NULL) {
314 new_receiver = Transform(new_receiver);
315 }
316 LocalVariable* result = AddToPreambleNewTempVar(
317 new(I) ClosureNode(node->token_pos(),
318 node->function(),
319 new_receiver,
320 node->scope()));
321 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
322 }
323
324
325 void AwaitTransformer::VisitInstanceCallNode(InstanceCallNode* node) {
326 AstNode* new_receiver = Transform(node->receiver());
327 ArgumentListNode* new_args =
328 Transform(node->arguments())->AsArgumentListNode();
329 LocalVariable* result = AddToPreambleNewTempVar(
330 new(I) InstanceCallNode(node->token_pos(),
331 new_receiver,
332 node->function_name(),
333 new_args));
334 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
335 }
336
337
338 void AwaitTransformer::VisitStaticCallNode(StaticCallNode* node) {
339 ArgumentListNode* new_args =
340 Transform(node->arguments())->AsArgumentListNode();
341 LocalVariable* result = AddToPreambleNewTempVar(
342 new(I) StaticCallNode(node->token_pos(),
343 node->function(),
344 new_args));
345 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
346 }
347
348
349 void AwaitTransformer::VisitConstructorCallNode(ConstructorCallNode* node) {
350 ArgumentListNode* new_args =
351 Transform(node->arguments())->AsArgumentListNode();
352 LocalVariable* result = AddToPreambleNewTempVar(
353 new(I) ConstructorCallNode(node->token_pos(),
354 node->type_arguments(),
355 node->constructor(),
356 new_args));
357 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
358 }
359
360
361 void AwaitTransformer::VisitInstanceGetterNode(InstanceGetterNode* node) {
362 AstNode* new_receiver = Transform(node->receiver());
363 LocalVariable* result = AddToPreambleNewTempVar(
364 new(I) InstanceGetterNode(node->token_pos(),
365 new_receiver,
366 node->field_name()));
367 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
368 }
369
370
371 void AwaitTransformer::VisitInstanceSetterNode(InstanceSetterNode* node) {
372 AstNode* new_receiver = node->receiver();
373 if (new_receiver != NULL) {
374 new_receiver = Transform(new_receiver);
375 }
376 AstNode* new_value = Transform(node->value());
377 LocalVariable* result = AddToPreambleNewTempVar(
378 new(I) InstanceSetterNode(node->token_pos(),
379 new_receiver,
380 node->field_name(),
381 new_value));
382 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
383 }
384
385
386 void AwaitTransformer::VisitStaticGetterNode(StaticGetterNode* node) {
387 AstNode* new_receiver = node->receiver();
388 if (new_receiver != NULL) {
389 new_receiver = Transform(new_receiver);
390 }
391 LocalVariable* result = AddToPreambleNewTempVar(
392 new(I) StaticGetterNode(node->token_pos(),
393 new_receiver,
394 node->is_super_getter(),
395 node->cls(),
396 node->field_name()));
397 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
398 }
399
400
401 void AwaitTransformer::VisitStaticSetterNode(StaticSetterNode* node) {
402 AstNode* new_receiver = node->receiver();
403 if (new_receiver != NULL) {
404 new_receiver = Transform(new_receiver);
405 }
406 AstNode* new_value = Transform(node->value());
407 LocalVariable* result = AddToPreambleNewTempVar(
408 new(I) StaticSetterNode(node->token_pos(),
409 new_receiver,
410 node->cls(),
411 node->field_name(),
412 new_value));
413 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
414 }
415
416
417 void AwaitTransformer::VisitLoadLocalNode(LoadLocalNode* node) {
418 LocalVariable* result = AddToPreambleNewTempVar(
419 new(I) LoadLocalNode(node->token_pos(), &node->local()));
420 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
421 }
422
423
424 void AwaitTransformer::VisitStoreLocalNode(StoreLocalNode* node) {
425 AstNode* new_value = Transform(node->value());
426 LocalVariable* result = AddToPreambleNewTempVar(
427 new(I) StoreLocalNode(node->token_pos(),
428 &node->local(),
429 new_value));
430 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
431 }
432
433
434 void AwaitTransformer::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) {
435 LocalVariable* result = AddToPreambleNewTempVar(
436 new(I) LoadStaticFieldNode(node->token_pos(),
437 node->field()));
438 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
439 }
440
441
442 void AwaitTransformer::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
443 AstNode* new_value = Transform(node->value());
444 LocalVariable* result = AddToPreambleNewTempVar(
445 new(I) StoreStaticFieldNode(node->token_pos(),
446 node->field(),
447 new_value));
448 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
449 }
450
451
452 void AwaitTransformer::VisitLoadIndexedNode(LoadIndexedNode* node) {
453 AstNode* new_array = Transform(node->array());
454 AstNode* new_index = Transform(node->index_expr());
455 LocalVariable* result = AddToPreambleNewTempVar(
456 new(I) LoadIndexedNode(node->token_pos(),
457 new_array,
458 new_index,
459 node->super_class()));
460 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
461 }
462
463
464 void AwaitTransformer::VisitStoreIndexedNode(StoreIndexedNode* node) {
465 AstNode* new_array = Transform(node->array());
466 AstNode* new_index = Transform(node->index_expr());
467 AstNode* new_value = Transform(node->value());
468 LocalVariable* result = AddToPreambleNewTempVar(
469 new(I) StoreIndexedNode(node->token_pos(),
470 new_array,
471 new_index,
472 new_value,
473 node->super_class()));
474 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
475 }
476
477
478 void AwaitTransformer::VisitAssignableNode(AssignableNode* node) {
479 AstNode* new_expr = Transform(node->expr());
480 LocalVariable* result = AddToPreambleNewTempVar(
481 new(I) AssignableNode(node->token_pos(),
482 new_expr,
483 node->type(),
484 node->dst_name()));
485 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result);
486 }
487
488
489 void AwaitTransformer::VisitLetNode(LetNode* node) {
490 // TODO(mlippautz): Check initializers and their temps.
491 LetNode* result = new(I) LetNode(node->token_pos());
492 for (intptr_t i = 0; i < node->nodes().length(); i++) {
493 result->AddNode(Transform(node->nodes()[i]));
494 }
495 result_ = result;
496 }
497
498
499 void AwaitTransformer::VisitThrowNode(ThrowNode* node) {
500 // TODO(mlippautz): Check if relevant.
501 AstNode* new_exception = Transform(node->exception());
502 AstNode* new_stacktrace = Transform(node->stacktrace());
503 result_ = new(I) ThrowNode(node->token_pos(),
504 new_exception,
505 new_stacktrace);
506 }
507
508 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/ast_transformer.h ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698