Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 void AwaitTransformer::Transform(AstNode* expr) { | |
| 45 expr->Visit(this); | |
| 46 } | |
| 47 | |
| 48 | |
| 49 LocalVariable* AwaitTransformer::EnsureCurrentTempVar() { | |
| 50 const char* await_temp_prefix = ":await_temp_var_"; | |
| 51 const String& cnt_str = String::Handle( | |
|
srdjan
2014/08/13 18:41:05
I,
Michael Lippautz (Google)
2014/08/13 20:32:23
Done.
| |
| 52 String::NewFormatted( | |
| 53 "%s%" Pd "", await_temp_prefix, temp_cnt_)); | |
| 54 const String& symbol = String::ZoneHandle(I, Symbols::New(cnt_str)); | |
| 55 ASSERT(!symbol.IsNull()); | |
| 56 LocalVariable* await_tmp = | |
| 57 parsed_function_->await_temps_scope()->LookupVariable(symbol, false); | |
| 58 if (await_tmp == NULL) { | |
| 59 await_tmp = new(I) LocalVariable( | |
| 60 Scanner::kNoSourcePos, | |
| 61 symbol, | |
| 62 Type::ZoneHandle(I, Type::DynamicType())); | |
| 63 parsed_function_->await_temps_scope()->AddVariable(await_tmp); | |
| 64 } | |
| 65 return await_tmp; | |
| 66 } | |
| 67 | |
| 68 | |
| 69 LocalVariable* AwaitTransformer::AddToPreambleNewTempVar(AstNode* node) { | |
| 70 LocalVariable* tmp_var = EnsureCurrentTempVar(); | |
| 71 preamble_->Add(new(I) StoreLocalNode(Scanner::kNoSourcePos, tmp_var, node)); | |
| 72 NextTempVar(); | |
| 73 return tmp_var; | |
| 74 } | |
| 75 | |
| 76 | |
| 77 void AwaitTransformer::VisitLiteralNode(LiteralNode* node) { | |
| 78 result_ = node; | |
| 79 } | |
| 80 | |
| 81 | |
| 82 void AwaitTransformer::VisitTypeNode(TypeNode* node) { | |
| 83 result_ = new(I) TypeNode(node->token_pos(), node->type()); | |
| 84 } | |
| 85 | |
| 86 | |
| 87 | |
| 88 void AwaitTransformer::VisitAwaitNode(AwaitNode* node) { | |
| 89 // Await transformation: | |
| 90 // | |
| 91 // :await_temp_var_X = <expr>; | |
| 92 // :result_param = :await_temp_var_X; | |
| 93 // if (:result_param is Future) { | |
| 94 // // :result_param.then(:async_op); | |
| 95 // } | |
| 96 // :await_temp_var_(X+1) = :result_param; | |
| 97 | |
| 98 LocalVariable* async_op = preamble_->scope()->LookupVariable( | |
| 99 Symbols::AsyncOperation(), false); | |
| 100 ASSERT(async_op != NULL); | |
| 101 LocalVariable* result_param = preamble_->scope()->LookupVariable( | |
| 102 Symbols::AsyncOperationParam(), false); | |
| 103 ASSERT(result_param != NULL); | |
| 104 | |
| 105 node->expr()->Visit(this); | |
| 106 preamble_->Add(new(I) StoreLocalNode(Scanner::kNoSourcePos, | |
| 107 result_param, | |
| 108 result_)); | |
| 109 LoadLocalNode* load_result_param = new(I) LoadLocalNode( | |
| 110 Scanner::kNoSourcePos, result_param); | |
| 111 SequenceNode* is_future_branch = new(I) SequenceNode( | |
| 112 Scanner::kNoSourcePos, preamble_->scope()); | |
| 113 ArgumentListNode* args = new(I) ArgumentListNode(Scanner::kNoSourcePos); | |
| 114 args->Add(new(I) LoadLocalNode(Scanner::kNoSourcePos, async_op)); | |
| 115 // TODO(mlippautz): Once continuations are supported, just call .then(). | |
| 116 // is_future_branch->Add(new(I) InstanceCallNode( | |
| 117 // Scanner::kNoSourcePos, load_result_param, Symbols::FutureThen(), args)); | |
| 118 // | |
| 119 // For now, throw an exception. | |
| 120 const String& exception = String::ZoneHandle( | |
| 121 I, String::New("awaitable futures not yet supported", Heap::kOld)); | |
| 122 is_future_branch->Add(new(I) ThrowNode( | |
| 123 Scanner::kNoSourcePos, | |
| 124 new(I) LiteralNode( | |
| 125 Scanner::kNoSourcePos, | |
| 126 String::ZoneHandle(I, Symbols::New(exception))), | |
| 127 NULL)); | |
| 128 const Class& cls = Class::Handle(library_.LookupClass(Symbols::Future())); | |
|
srdjan
2014/08/13 18:41:06
I,
Michael Lippautz (Google)
2014/08/13 20:32:23
Done.
| |
| 129 const AbstractType& future_type = AbstractType::ZoneHandle(I, | |
| 130 cls.RareType()); | |
| 131 ASSERT(!future_type.IsNull()); | |
| 132 TypeNode* future_type_node = new(I) TypeNode( | |
| 133 Scanner::kNoSourcePos, future_type); | |
| 134 IfNode* is_future_if = new(I) IfNode( | |
| 135 Scanner::kNoSourcePos, | |
| 136 new(I) ComparisonNode(Scanner::kNoSourcePos, | |
| 137 Token::kIS, | |
| 138 load_result_param, | |
| 139 future_type_node), | |
| 140 is_future_branch, | |
| 141 NULL); | |
| 142 preamble_->Add(is_future_if); | |
| 143 | |
| 144 // TODO(mlippautz): Join for await needs to happen here. | |
| 145 | |
| 146 LocalVariable* result = AddToPreambleNewTempVar(new(I) LoadLocalNode( | |
| 147 Scanner::kNoSourcePos, result_param)); | |
| 148 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 149 } | |
| 150 | |
| 151 | |
| 152 // Transforms boolean expressions into a sequence of evaluatons that only lazily | |
| 153 // evaluate subexpressions. | |
| 154 // | |
| 155 // Example: | |
| 156 // | |
| 157 // (a || b) only evaluates b if a is true | |
| 158 // | |
| 159 // Transformation (roughly): | |
| 160 // | |
| 161 // t_1 = a; | |
| 162 // if (t_1) { | |
| 163 // t_2 = b; | |
| 164 // } | |
| 165 // t_3 = t_1 || t_2; // Compiler takes care that lazy evaluation takes place | |
| 166 // on this level. | |
| 167 AstNode* AwaitTransformer::LazyTransform(const Token::Kind logical_op, | |
| 168 AstNode* new_left, | |
| 169 AstNode* right) { | |
| 170 ASSERT(logical_op == Token::kAND || logical_op == Token::kOR); | |
| 171 AstNode* result = NULL; | |
| 172 const Token::Kind compare_logical_op = (logical_op == Token::kAND) ? | |
| 173 Token::kEQ : Token::kNE; | |
| 174 SequenceNode* eval = new SequenceNode( | |
|
srdjan
2014/08/13 18:41:06
new (I)
Michael Lippautz (Google)
2014/08/13 20:32:23
Done.
| |
| 175 Scanner::kNoSourcePos, preamble_->scope()); | |
| 176 SequenceNode* saved_preamble = preamble_; | |
| 177 preamble_ = eval; | |
| 178 right->Visit(this); | |
| 179 result = result_; | |
| 180 preamble_ = saved_preamble; | |
| 181 IfNode* right_body = new(I) IfNode( | |
| 182 Scanner::kNoSourcePos, | |
| 183 new(I) ComparisonNode( | |
| 184 Scanner::kNoSourcePos, | |
| 185 compare_logical_op, | |
| 186 new_left, | |
| 187 new(I) LiteralNode(Scanner::kNoSourcePos, Bool::True())), | |
| 188 eval, | |
| 189 NULL); | |
| 190 preamble_->Add(right_body); | |
| 191 return result; | |
| 192 } | |
| 193 | |
| 194 | |
| 195 void AwaitTransformer::VisitBinaryOpNode(BinaryOpNode* node) { | |
| 196 node->left()->Visit(this); | |
| 197 AstNode* new_left = result_; | |
| 198 AstNode* new_right = NULL; | |
| 199 // Preserve lazy evaluaton. | |
| 200 if (node->kind() == Token::kAND || node->kind() == Token::kOR) { | |
|
srdjan
2014/08/13 18:41:05
Use more parentheses.
Michael Lippautz (Google)
2014/08/13 20:32:23
Done.
| |
| 201 new_right = LazyTransform(node->kind(), new_left, node->right()); | |
| 202 } else { | |
| 203 node->right()->Visit(this); | |
| 204 new_right = result_; | |
| 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) { | |
|
srdjan
2014/08/13 18:41:05
Use more parentheses
Michael Lippautz (Google)
2014/08/13 20:32:23
Done.
| |
| 222 new_right = LazyTransform(node->kind(), new_left, node->right()); | |
| 223 } else { | |
| 224 node->right()->Visit(this); | |
| 225 new_right = result_; | |
| 226 } | |
| 227 LocalVariable* result = AddToPreambleNewTempVar( | |
| 228 new(I) BinaryOpWithMask32Node(node->token_pos(), | |
| 229 node->kind(), | |
| 230 new_left, | |
| 231 new_right, | |
| 232 node->mask32())); | |
| 233 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 234 } | |
| 235 | |
| 236 | |
| 237 void AwaitTransformer::VisitComparisonNode(ComparisonNode* node) { | |
| 238 node->left()->Visit(this); | |
| 239 AstNode* new_left = result_; | |
| 240 node->right()->Visit(this); | |
| 241 AstNode* new_right = result_; | |
| 242 LocalVariable* result = AddToPreambleNewTempVar( | |
| 243 new(I) ComparisonNode(node->token_pos(), | |
| 244 node->kind(), | |
| 245 new_left, | |
| 246 new_right)); | |
| 247 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 248 } | |
| 249 | |
| 250 | |
| 251 void AwaitTransformer::VisitUnaryOpNode(UnaryOpNode* node) { | |
| 252 node->operand()->Visit(this); | |
| 253 AstNode* new_operand = result_; | |
| 254 | |
| 255 LocalVariable* result = AddToPreambleNewTempVar( | |
| 256 new(I) UnaryOpNode(node->token_pos(), | |
| 257 node->kind(), | |
| 258 new_operand)); | |
| 259 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 260 } | |
| 261 | |
|
srdjan
2014/08/13 18:41:05
two empty lines
Michael Lippautz (Google)
2014/08/13 20:32:23
Done.
| |
| 262 // ::= (<condition>) ? <true-branch> : <false-branch> | |
| 263 // | |
| 264 void AwaitTransformer::VisitConditionalExprNode(ConditionalExprNode* node) { | |
| 265 // TODO(mlippautz): Optimize variable assingments and branching. | |
|
srdjan
2014/08/13 18:41:06
s/assingments/assignments/
Michael Lippautz (Google)
2014/08/13 20:32:23
Got rid of the comment as it doesn't make too much
| |
| 266 node->condition()->Visit(this); | |
| 267 AstNode* new_condition = result_; | |
| 268 SequenceNode* new_true = new(I) SequenceNode( | |
| 269 Scanner::kNoSourcePos, preamble_->scope()); | |
| 270 SequenceNode* saved_preamble = preamble_; | |
| 271 preamble_ = new_true; | |
| 272 node->true_expr()->Visit(this); | |
| 273 AstNode* new_true_result = result_; | |
| 274 SequenceNode* new_false = new(I) SequenceNode( | |
| 275 Scanner::kNoSourcePos, preamble_->scope()); | |
| 276 preamble_ = new_false; | |
| 277 node->false_expr()->Visit(this); | |
| 278 AstNode* new_false_result = result_; | |
| 279 preamble_ = saved_preamble; | |
| 280 IfNode* new_if = new(I) IfNode(Scanner::kNoSourcePos, | |
| 281 new_condition, | |
| 282 new_true, | |
| 283 new_false); | |
| 284 preamble_->Add(new_if); | |
| 285 LocalVariable* result = AddToPreambleNewTempVar( | |
| 286 new(I) ConditionalExprNode(Scanner::kNoSourcePos, | |
| 287 new_condition, | |
| 288 new_true_result, | |
| 289 new_false_result)); | |
| 290 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 291 } | |
| 292 | |
| 293 | |
| 294 void AwaitTransformer::VisitArgumentListNode(ArgumentListNode* node) { | |
| 295 ArgumentListNode* new_args = new(I) ArgumentListNode(node->token_pos()); | |
| 296 for (intptr_t i = 0; i < node->length(); i++) { | |
| 297 node->NodeAt(i)->Visit(this); | |
| 298 new_args->Add(result_); | |
| 299 } | |
| 300 result_ = new_args; | |
| 301 } | |
| 302 | |
| 303 | |
| 304 void AwaitTransformer::VisitArrayNode(ArrayNode* node) { | |
| 305 GrowableArray<AstNode*> new_elements; | |
| 306 for (intptr_t i = 0; i < node->length(); i++) { | |
| 307 node->ElementAt(i)->Visit(this); | |
| 308 new_elements.Add(result_); | |
| 309 } | |
| 310 result_ = new(I) ArrayNode(node->token_pos(), node->type(), new_elements); | |
| 311 } | |
| 312 | |
| 313 | |
| 314 void AwaitTransformer::VisitStringInterpolateNode(StringInterpolateNode* node) { | |
| 315 node->value()->Visit(this); | |
| 316 ArrayNode* new_value = result_->AsArrayNode(); | |
| 317 LocalVariable* result = AddToPreambleNewTempVar( | |
| 318 new(I) StringInterpolateNode(node->token_pos(), | |
| 319 new_value)); | |
| 320 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 321 } | |
| 322 | |
| 323 | |
| 324 void AwaitTransformer::VisitClosureNode(ClosureNode* node) { | |
| 325 AstNode* new_receiver = node->receiver(); | |
| 326 if (new_receiver != NULL) { | |
| 327 new_receiver->Visit(this); | |
| 328 new_receiver = result_; | |
| 329 } | |
| 330 LocalVariable* result = AddToPreambleNewTempVar( | |
| 331 new(I) ClosureNode(node->token_pos(), | |
| 332 node->function(), | |
| 333 new_receiver, | |
| 334 node->scope())); | |
| 335 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 336 } | |
| 337 | |
| 338 | |
| 339 void AwaitTransformer::VisitInstanceCallNode(InstanceCallNode* node) { | |
| 340 node->receiver()->Visit(this); | |
| 341 AstNode* new_receiver = result_; | |
| 342 node->arguments()->Visit(this); | |
| 343 ArgumentListNode* new_args = result_->AsArgumentListNode(); | |
| 344 | |
| 345 LocalVariable* result = AddToPreambleNewTempVar( | |
| 346 new(I) InstanceCallNode(node->token_pos(), | |
| 347 new_receiver, | |
| 348 node->function_name(), | |
| 349 new_args)); | |
| 350 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 351 } | |
| 352 | |
| 353 | |
| 354 void AwaitTransformer::VisitStaticCallNode(StaticCallNode* node) { | |
| 355 node->arguments()->Visit(this); | |
| 356 ArgumentListNode* new_args = result_->AsArgumentListNode(); | |
| 357 | |
| 358 LocalVariable* result = AddToPreambleNewTempVar( | |
| 359 new(I) StaticCallNode(node->token_pos(), | |
| 360 node->function(), | |
| 361 new_args)); | |
| 362 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 363 } | |
| 364 | |
| 365 | |
| 366 void AwaitTransformer::VisitConstructorCallNode(ConstructorCallNode* node) { | |
| 367 node->arguments()->Visit(this); | |
| 368 ArgumentListNode* new_args = result_->AsArgumentListNode(); | |
| 369 | |
| 370 LocalVariable* result = AddToPreambleNewTempVar( | |
| 371 new(I) ConstructorCallNode(node->token_pos(), | |
| 372 node->type_arguments(), | |
| 373 node->constructor(), | |
| 374 new_args)); | |
| 375 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 376 } | |
| 377 | |
| 378 | |
| 379 void AwaitTransformer::VisitInstanceGetterNode(InstanceGetterNode* node) { | |
| 380 node->receiver()->Visit(this); | |
| 381 AstNode* new_receiver = result_; | |
| 382 | |
| 383 LocalVariable* result = AddToPreambleNewTempVar( | |
| 384 new(I) InstanceGetterNode(node->token_pos(), | |
| 385 new_receiver, | |
| 386 node->field_name())); | |
| 387 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 388 } | |
| 389 | |
| 390 | |
| 391 void AwaitTransformer::VisitInstanceSetterNode(InstanceSetterNode* node) { | |
| 392 AstNode* new_receiver = node->receiver(); | |
| 393 if (new_receiver != NULL) { | |
| 394 new_receiver->Visit(this); | |
| 395 new_receiver = result_; | |
| 396 } | |
| 397 | |
| 398 node->value()->Visit(this); | |
| 399 AstNode* new_value = result_; | |
| 400 | |
| 401 LocalVariable* result = AddToPreambleNewTempVar( | |
| 402 new(I) InstanceSetterNode(node->token_pos(), | |
| 403 new_receiver, | |
| 404 node->field_name(), | |
| 405 new_value)); | |
| 406 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 407 } | |
| 408 | |
| 409 | |
| 410 void AwaitTransformer::VisitStaticGetterNode(StaticGetterNode* node) { | |
| 411 AstNode* new_receiver = node->receiver(); | |
| 412 if (new_receiver != NULL) { | |
| 413 new_receiver->Visit(this); | |
| 414 new_receiver = result_; | |
| 415 } | |
| 416 | |
| 417 LocalVariable* result = AddToPreambleNewTempVar( | |
| 418 new(I) StaticGetterNode(node->token_pos(), | |
| 419 new_receiver, | |
| 420 node->is_super_getter(), | |
| 421 node->cls(), | |
| 422 node->field_name())); | |
| 423 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 424 } | |
| 425 | |
| 426 | |
| 427 void AwaitTransformer::VisitStaticSetterNode(StaticSetterNode* node) { | |
| 428 AstNode* new_receiver = node->receiver(); | |
| 429 if (new_receiver != NULL) { | |
| 430 new_receiver->Visit(this); | |
| 431 new_receiver = result_; | |
| 432 } | |
| 433 node->value()->Visit(this); | |
| 434 AstNode* new_value = result_; | |
| 435 | |
| 436 LocalVariable* result = AddToPreambleNewTempVar( | |
| 437 new(I) StaticSetterNode(node->token_pos(), | |
| 438 new_receiver, | |
| 439 node->cls(), | |
| 440 node->field_name(), | |
| 441 new_value)); | |
| 442 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 443 } | |
| 444 | |
| 445 | |
| 446 void AwaitTransformer::VisitLoadLocalNode(LoadLocalNode* node) { | |
| 447 LocalVariable* result = AddToPreambleNewTempVar( | |
| 448 new(I) LoadLocalNode(node->token_pos(), &node->local())); | |
| 449 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 450 } | |
| 451 | |
| 452 | |
| 453 void AwaitTransformer::VisitStoreLocalNode(StoreLocalNode* node) { | |
| 454 node->value()->Visit(this); | |
| 455 AstNode* new_value = result_; | |
| 456 LocalVariable* result = AddToPreambleNewTempVar( | |
| 457 new(I) StoreLocalNode(node->token_pos(), | |
| 458 &node->local(), | |
| 459 new_value)); | |
| 460 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 461 } | |
| 462 | |
| 463 | |
| 464 void AwaitTransformer::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) { | |
| 465 LocalVariable* result = AddToPreambleNewTempVar( | |
| 466 new(I) LoadStaticFieldNode(node->token_pos(), | |
| 467 node->field())); | |
| 468 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 469 } | |
| 470 | |
| 471 | |
| 472 void AwaitTransformer::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { | |
| 473 node->value()->Visit(this); | |
| 474 AstNode* new_value = result_; | |
| 475 LocalVariable* result = AddToPreambleNewTempVar( | |
| 476 new(I) StoreStaticFieldNode(node->token_pos(), | |
| 477 node->field(), | |
| 478 new_value)); | |
| 479 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 480 } | |
| 481 | |
| 482 | |
| 483 void AwaitTransformer::VisitLoadIndexedNode(LoadIndexedNode* node) { | |
| 484 node->array()->Visit(this); | |
| 485 AstNode* new_array = result_; | |
| 486 node->index_expr()->Visit(this); | |
| 487 AstNode* new_index = result_; | |
| 488 LocalVariable* result = AddToPreambleNewTempVar( | |
| 489 new(I) LoadIndexedNode(node->token_pos(), | |
| 490 new_array, | |
| 491 new_index, | |
| 492 node->super_class())); | |
| 493 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 494 } | |
| 495 | |
| 496 | |
| 497 void AwaitTransformer::VisitStoreIndexedNode(StoreIndexedNode* node) { | |
| 498 node->array()->Visit(this); | |
| 499 AstNode* new_array = result_; | |
| 500 node->index_expr()->Visit(this); | |
| 501 AstNode* new_index = result_; | |
| 502 node->value()->Visit(this); | |
| 503 AstNode* new_value = result_; | |
| 504 LocalVariable* result = AddToPreambleNewTempVar( | |
| 505 new(I) StoreIndexedNode(node->token_pos(), | |
| 506 new_array, | |
| 507 new_index, | |
| 508 new_value, | |
| 509 node->super_class())); | |
| 510 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 511 } | |
| 512 | |
| 513 | |
| 514 void AwaitTransformer::VisitAssignableNode(AssignableNode* node) { | |
| 515 node->expr()->Visit(this); | |
| 516 AstNode* new_expr = result_; | |
| 517 LocalVariable* result = AddToPreambleNewTempVar( | |
| 518 new(I) AssignableNode(node->token_pos(), | |
| 519 new_expr, | |
| 520 node->type(), | |
| 521 node->dst_name())); | |
| 522 result_ = new(I) LoadLocalNode(Scanner::kNoSourcePos, result); | |
| 523 } | |
| 524 | |
| 525 | |
| 526 void AwaitTransformer::VisitLetNode(LetNode* node) { | |
| 527 // TODO(mlippautz): Check initializers and their temps. | |
| 528 LetNode* result = new(I) LetNode(node->token_pos()); | |
| 529 for (intptr_t i = 0; i < node->nodes().length(); i++) { | |
| 530 node->nodes()[i]->Visit(this); | |
| 531 result->AddNode(result_); | |
| 532 } | |
| 533 result_ = result; | |
| 534 } | |
| 535 | |
| 536 | |
| 537 void AwaitTransformer::VisitThrowNode(ThrowNode* node) { | |
| 538 // TODO(mlippautz): Check if relevant. | |
| 539 node->exception()->Visit(this); | |
| 540 AstNode* new_exception = result_; | |
| 541 node->stacktrace()->Visit(this); | |
| 542 AstNode* new_stacktrace = result_; | |
| 543 result_ = new(I) ThrowNode(node->token_pos(), | |
| 544 new_exception, | |
| 545 new_stacktrace); | |
| 546 } | |
| 547 | |
| 548 } // namespace dart | |
| OLD | NEW |