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

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

Powered by Google App Engine
This is Rietveld 408576698