| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 #include "vm/parser.h" | 5 #include "vm/parser.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
| 9 #include "vm/ast_transformer.h" | 9 #include "vm/ast_transformer.h" |
| 10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
| (...skipping 6837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6848 current_block_ = current_block_->parent; | 6848 current_block_ = current_block_->parent; |
| 6849 return statements; | 6849 return statements; |
| 6850 } | 6850 } |
| 6851 | 6851 |
| 6852 | 6852 |
| 6853 SequenceNode* Parser::CloseAsyncFunction(const Function& closure, | 6853 SequenceNode* Parser::CloseAsyncFunction(const Function& closure, |
| 6854 SequenceNode* closure_body) { | 6854 SequenceNode* closure_body) { |
| 6855 TRACE_PARSER("CloseAsyncFunction"); | 6855 TRACE_PARSER("CloseAsyncFunction"); |
| 6856 ASSERT(!closure.IsNull()); | 6856 ASSERT(!closure.IsNull()); |
| 6857 ASSERT(closure_body != NULL); | 6857 ASSERT(closure_body != NULL); |
| 6858 |
| 6858 // The block for the async closure body has already been closed. Close the | 6859 // The block for the async closure body has already been closed. Close the |
| 6859 // corresponding function block. | 6860 // corresponding function block. |
| 6860 CloseBlock(); | 6861 CloseBlock(); |
| 6861 | 6862 |
| 6862 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | 6863 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 6863 closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); | 6864 closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
| 6864 closure_body->scope()->CaptureVariable(Symbols::AsyncCompleter()); | 6865 closure_body->scope()->CaptureVariable(Symbols::AsyncCompleter()); |
| 6865 | 6866 |
| 6866 // Create and return a new future that executes a closure with the current | 6867 // Create and return a new future that executes a closure with the current |
| 6867 // body. | 6868 // body. |
| (...skipping 1460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8328 intptr_t loop_var_pos = TokenPos(); | 8329 intptr_t loop_var_pos = TokenPos(); |
| 8329 const String* loop_var_name = ExpectIdentifier("variable name expected"); | 8330 const String* loop_var_name = ExpectIdentifier("variable name expected"); |
| 8330 | 8331 |
| 8331 // Parse stream expression. | 8332 // Parse stream expression. |
| 8332 ExpectToken(Token::kIN); | 8333 ExpectToken(Token::kIN); |
| 8333 const intptr_t stream_pos = TokenPos(); | 8334 const intptr_t stream_pos = TokenPos(); |
| 8334 AstNode* stream_expr = | 8335 AstNode* stream_expr = |
| 8335 ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 8336 ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 8336 ExpectToken(Token::kRPAREN); | 8337 ExpectToken(Token::kRPAREN); |
| 8337 | 8338 |
| 8339 // Open a block for the iterator variable and the try-finally |
| 8340 // statement that contains the loop. |
| 8338 OpenBlock(); | 8341 OpenBlock(); |
| 8342 const Block* loop_block = current_block_; |
| 8339 | 8343 |
| 8340 // Build creation of implicit StreamIterator. | 8344 // Build creation of implicit StreamIterator. |
| 8341 // var :for-in-iter = new StreamIterator(stream_expr). | 8345 // var :for-in-iter = new StreamIterator(stream_expr). |
| 8342 const Class& stream_iterator_cls = | 8346 const Class& stream_iterator_cls = |
| 8343 Class::ZoneHandle(Z, I->object_store()->stream_iterator_class()); | 8347 Class::ZoneHandle(Z, I->object_store()->stream_iterator_class()); |
| 8344 ASSERT(!stream_iterator_cls.IsNull()); | 8348 ASSERT(!stream_iterator_cls.IsNull()); |
| 8345 const Function& iterator_ctor = | 8349 const Function& iterator_ctor = |
| 8346 Function::ZoneHandle(Z, stream_iterator_cls.LookupFunction( | 8350 Function::ZoneHandle(Z, stream_iterator_cls.LookupFunction( |
| 8347 Symbols::StreamIteratorConstructor())); | 8351 Symbols::StreamIteratorConstructor())); |
| 8348 ASSERT(!iterator_ctor.IsNull()); | 8352 ASSERT(!iterator_ctor.IsNull()); |
| 8349 ArgumentListNode* ctor_args = new (Z) ArgumentListNode(Scanner::kNoSourcePos); | 8353 ArgumentListNode* ctor_args = new (Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 8350 ctor_args->Add(stream_expr); | 8354 ctor_args->Add(stream_expr); |
| 8351 ConstructorCallNode* ctor_call = | 8355 ConstructorCallNode* ctor_call = |
| 8352 new (Z) ConstructorCallNode(Scanner::kNoSourcePos, | 8356 new (Z) ConstructorCallNode(Scanner::kNoSourcePos, |
| 8353 TypeArguments::ZoneHandle(Z), | 8357 TypeArguments::ZoneHandle(Z), |
| 8354 iterator_ctor, | 8358 iterator_ctor, |
| 8355 ctor_args); | 8359 ctor_args); |
| 8356 const AbstractType& iterator_type = Type::ZoneHandle(Z, Type::DynamicType()); | 8360 const AbstractType& iterator_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 8357 LocalVariable* iterator_var = new(Z) LocalVariable( | 8361 LocalVariable* iterator_var = new(Z) LocalVariable( |
| 8358 stream_pos, Symbols::ForInIter(), iterator_type); | 8362 stream_pos, Symbols::ForInIter(), iterator_type); |
| 8359 current_block_->scope->AddVariable(iterator_var); | 8363 current_block_->scope->AddVariable(iterator_var); |
| 8360 AstNode* iterator_init = | 8364 AstNode* iterator_init = |
| 8361 new(Z) StoreLocalNode(stream_pos, iterator_var, ctor_call); | 8365 new(Z) StoreLocalNode(stream_pos, iterator_var, ctor_call); |
| 8362 current_block_->statements->Add(iterator_init); | 8366 current_block_->statements->Add(iterator_init); |
| 8363 | 8367 |
| 8368 // We need to ensure that the stream is cancelled after the loop. |
| 8369 // Thus, wrap the loop in a try-finally that calls :for-in-iter.close() |
| 8370 // in the finally clause. It is harmless to call close() if the stream |
| 8371 // is already cancelled (when moveNext() returns false). |
| 8372 // Note: even though this is async code, we do not need to set up |
| 8373 // the closurized saved_exception_var and saved_stack_trace_var because |
| 8374 // there can not be a suspend/resume event before the exception is |
| 8375 // rethrown in the catch clause. The catch block of the implicit |
| 8376 // try-finally is empty. |
| 8377 LocalVariable* context_var = NULL; |
| 8378 LocalVariable* exception_var = NULL; |
| 8379 LocalVariable* stack_trace_var = NULL; |
| 8380 LocalVariable* saved_exception_var = NULL; |
| 8381 LocalVariable* saved_stack_trace_var = NULL; |
| 8382 SetupExceptionVariables(current_block_->scope, |
| 8383 false, // Do not create the saved_ vars. |
| 8384 &context_var, |
| 8385 &exception_var, |
| 8386 &stack_trace_var, |
| 8387 &saved_exception_var, |
| 8388 &saved_stack_trace_var); |
| 8389 OpenBlock(); // try block. |
| 8390 PushTry(current_block_); |
| 8391 SetupSavedTryContext(context_var); |
| 8392 |
| 8393 // Build while loop condition. |
| 8394 // while (await :for-in-iter.moveNext()) |
| 8364 LocalScope* try_scope; | 8395 LocalScope* try_scope; |
| 8365 int16_t try_index; | 8396 int16_t try_index; |
| 8366 LocalScope* outer_try_scope; | 8397 LocalScope* outer_try_scope; |
| 8367 int16_t outer_try_index; | 8398 int16_t outer_try_index; |
| 8368 CheckAsyncOpInTryBlock(&try_scope, &try_index, | 8399 CheckAsyncOpInTryBlock(&try_scope, &try_index, |
| 8369 &outer_try_scope, &outer_try_index); | 8400 &outer_try_scope, &outer_try_index); |
| 8370 | 8401 |
| 8371 // Build while loop condition. | |
| 8372 // while (await :for-in-iter.moveNext()) | |
| 8373 ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos); | 8402 ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos); |
| 8374 AstNode* iterator_moveNext = new(Z) InstanceCallNode( | 8403 AstNode* iterator_moveNext = new(Z) InstanceCallNode( |
| 8375 stream_pos, | 8404 stream_pos, |
| 8376 new(Z) LoadLocalNode(stream_pos, iterator_var), | 8405 new(Z) LoadLocalNode(stream_pos, iterator_var), |
| 8377 Symbols::MoveNext(), | 8406 Symbols::MoveNext(), |
| 8378 no_args); | 8407 no_args); |
| 8379 AstNode* await_moveNext = new (Z) AwaitNode(stream_pos, | 8408 AstNode* await_moveNext = |
| 8380 iterator_moveNext, | 8409 new(Z) AwaitNode(stream_pos, |
| 8381 try_scope, | 8410 iterator_moveNext, |
| 8382 try_index, | 8411 try_scope, |
| 8383 outer_try_scope, | 8412 try_index, |
| 8384 outer_try_index); | 8413 outer_try_scope, |
| 8414 outer_try_index); |
| 8385 OpenBlock(); | 8415 OpenBlock(); |
| 8386 AwaitTransformer at(current_block_->statements, async_temp_scope_); | 8416 AwaitTransformer at(current_block_->statements, async_temp_scope_); |
| 8387 AstNode* transformed_await = at.Transform(await_moveNext); | 8417 await_moveNext = at.Transform(await_moveNext); |
| 8388 SequenceNode* await_preamble = CloseBlock(); | 8418 SequenceNode* await_preamble = CloseBlock(); |
| 8389 | 8419 |
| 8390 // Parse the for loop body. Ideally, we would use ParseNestedStatement() | 8420 // Parse the for loop body. Ideally, we would use ParseNestedStatement() |
| 8391 // here, but that does not work well because we have to insert an implicit | 8421 // here, but that does not work well because we have to insert an implicit |
| 8392 // variable assignment and potentially a variable declaration in the | 8422 // variable assignment and potentially a variable declaration in the |
| 8393 // loop body. | 8423 // loop body. |
| 8394 OpenLoopBlock(); | 8424 OpenLoopBlock(); |
| 8425 |
| 8395 SourceLabel* label = | 8426 SourceLabel* label = |
| 8396 SourceLabel::New(await_for_pos, label_name, SourceLabel::kFor); | 8427 SourceLabel::New(await_for_pos, label_name, SourceLabel::kFor); |
| 8397 current_block_->scope->AddLabel(label); | 8428 current_block_->scope->AddLabel(label); |
| 8398 const intptr_t loop_var_assignment_pos = TokenPos(); | 8429 const intptr_t loop_var_assignment_pos = TokenPos(); |
| 8399 | 8430 |
| 8400 AstNode* iterator_current = new(Z) InstanceGetterNode( | 8431 AstNode* iterator_current = new(Z) InstanceGetterNode( |
| 8401 loop_var_assignment_pos, | 8432 loop_var_assignment_pos, |
| 8402 new(Z) LoadLocalNode(loop_var_assignment_pos, iterator_var), | 8433 new(Z) LoadLocalNode(loop_var_assignment_pos, iterator_var), |
| 8403 Symbols::Current()); | 8434 Symbols::Current()); |
| 8404 | 8435 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 8422 } else { | 8453 } else { |
| 8423 AstNode* loop_var_primary = | 8454 AstNode* loop_var_primary = |
| 8424 ResolveIdent(loop_var_pos, *loop_var_name, false); | 8455 ResolveIdent(loop_var_pos, *loop_var_name, false); |
| 8425 ASSERT(!loop_var_primary->IsPrimaryNode()); | 8456 ASSERT(!loop_var_primary->IsPrimaryNode()); |
| 8426 loop_var_assignment = CreateAssignmentNode(loop_var_primary, | 8457 loop_var_assignment = CreateAssignmentNode(loop_var_primary, |
| 8427 iterator_current, | 8458 iterator_current, |
| 8428 loop_var_name, | 8459 loop_var_name, |
| 8429 loop_var_assignment_pos); | 8460 loop_var_assignment_pos); |
| 8430 ASSERT(loop_var_assignment != NULL); | 8461 ASSERT(loop_var_assignment != NULL); |
| 8431 } | 8462 } |
| 8463 |
| 8432 current_block_->statements->Add(loop_var_assignment); | 8464 current_block_->statements->Add(loop_var_assignment); |
| 8433 | 8465 |
| 8434 // Now parse the for-in loop statement or block. | 8466 // Now parse the for-in loop statement or block. |
| 8435 if (CurrentToken() == Token::kLBRACE) { | 8467 if (CurrentToken() == Token::kLBRACE) { |
| 8436 ConsumeToken(); | 8468 ConsumeToken(); |
| 8437 ParseStatementSequence(); | 8469 ParseStatementSequence(); |
| 8438 ExpectToken(Token::kRBRACE); | 8470 ExpectToken(Token::kRBRACE); |
| 8439 } else { | 8471 } else { |
| 8440 AstNode* statement = ParseStatement(); | 8472 AstNode* statement = ParseStatement(); |
| 8441 if (statement != NULL) { | 8473 if (statement != NULL) { |
| 8442 current_block_->statements->Add(statement); | 8474 current_block_->statements->Add(statement); |
| 8443 } | 8475 } |
| 8444 } | 8476 } |
| 8445 SequenceNode* for_loop_statement = CloseBlock(); | 8477 SequenceNode* for_loop_block = CloseBlock(); |
| 8446 | 8478 |
| 8447 WhileNode* while_node = new (Z) WhileNode(await_for_pos, | 8479 WhileNode* while_node = new (Z) WhileNode(await_for_pos, |
| 8448 label, | 8480 label, |
| 8449 transformed_await, | 8481 await_moveNext, |
| 8450 await_preamble, | 8482 await_preamble, |
| 8451 for_loop_statement); | 8483 for_loop_block); |
| 8484 // Add the while loop to the try block. |
| 8452 current_block_->statements->Add(while_node); | 8485 current_block_->statements->Add(while_node); |
| 8486 SequenceNode* try_block = CloseBlock(); |
| 8487 |
| 8488 // Create an empty "catch all" block that rethrows the current |
| 8489 // exception and stacktrace. |
| 8490 try_stack_->enter_catch(); |
| 8491 SequenceNode* catch_block = new(Z) SequenceNode(await_for_pos, NULL); |
| 8492 |
| 8493 if (outer_try_scope != NULL) { |
| 8494 catch_block->Add(AwaitTransformer::RestoreSavedTryContext( |
| 8495 Z, outer_try_scope, outer_try_index)); |
| 8496 } |
| 8497 |
| 8498 // We don't need to copy the current exception and stack trace variables |
| 8499 // into :saved_exception_var and :saved_stack_trace_var here because there |
| 8500 // is no code in the catch clause that could suspend the function. |
| 8501 |
| 8502 // Rethrow the exception. |
| 8503 catch_block->Add(new(Z) ThrowNode( |
| 8504 await_for_pos, |
| 8505 new(Z) LoadLocalNode(await_for_pos, exception_var), |
| 8506 new(Z) LoadLocalNode(await_for_pos, stack_trace_var))); |
| 8507 |
| 8508 TryStack* try_statement = PopTry(); |
| 8509 ASSERT(try_index == try_statement->try_index()); |
| 8510 |
| 8511 // The finally block contains a call to cancel the stream. |
| 8512 // :for-in-iter.cancel() |
| 8513 |
| 8514 // Inline the finally block to the exit points in the try block. |
| 8515 intptr_t node_index = 0; |
| 8516 SequenceNode* finally_clause = NULL; |
| 8517 do { |
| 8518 OpenBlock(); |
| 8519 ArgumentListNode* no_args = |
| 8520 new(Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 8521 current_block_->statements->Add( |
| 8522 new(Z) InstanceCallNode(Scanner::kNoSourcePos, |
| 8523 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_var), |
| 8524 Symbols::Cancel(), |
| 8525 no_args)); |
| 8526 finally_clause = CloseBlock(); |
| 8527 AstNode* node_to_inline = try_statement->GetNodeToInlineFinally(node_index); |
| 8528 if (node_to_inline != NULL) { |
| 8529 InlinedFinallyNode* node = |
| 8530 new(Z) InlinedFinallyNode(Scanner::kNoSourcePos, |
| 8531 finally_clause, |
| 8532 context_var, |
| 8533 outer_try_index); |
| 8534 finally_clause = NULL; |
| 8535 AddFinallyBlockToNode(true, node_to_inline, node); |
| 8536 node_index++; |
| 8537 } |
| 8538 } while (finally_clause == NULL); |
| 8539 |
| 8540 // Create the try-statement and add to the current sequence, which is |
| 8541 // the block around the loop statement. |
| 8542 |
| 8543 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 8544 const Array& handler_types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld)); |
| 8545 handler_types.SetAt(0, dynamic_type); // Catch block handles all exceptions. |
| 8546 |
| 8547 CatchClauseNode* catch_clause = new(Z) CatchClauseNode(await_for_pos, |
| 8548 catch_block, |
| 8549 handler_types, |
| 8550 context_var, |
| 8551 exception_var, |
| 8552 stack_trace_var, |
| 8553 exception_var, |
| 8554 stack_trace_var, |
| 8555 AllocateTryIndex(), |
| 8556 true); // Needs stack trace. |
| 8557 |
| 8558 AstNode* try_catch_node = |
| 8559 new(Z) TryCatchNode(await_for_pos, |
| 8560 try_block, |
| 8561 context_var, |
| 8562 catch_clause, |
| 8563 finally_clause, |
| 8564 try_index); |
| 8565 |
| 8566 ASSERT(current_block_ == loop_block); |
| 8567 loop_block->statements->Add(try_catch_node); |
| 8453 | 8568 |
| 8454 return CloseBlock(); // Implicit block around while loop. | 8569 return CloseBlock(); // Implicit block around while loop. |
| 8455 } | 8570 } |
| 8456 | 8571 |
| 8457 | 8572 |
| 8458 AstNode* Parser::ParseForInStatement(intptr_t forin_pos, | 8573 AstNode* Parser::ParseForInStatement(intptr_t forin_pos, |
| 8459 SourceLabel* label) { | 8574 SourceLabel* label) { |
| 8460 TRACE_PARSER("ParseForInStatement"); | 8575 TRACE_PARSER("ParseForInStatement"); |
| 8461 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); | 8576 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); |
| 8462 if (CurrentToken() == Token::kCONST) { | 8577 if (CurrentToken() == Token::kCONST) { |
| (...skipping 4818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13281 void Parser::SkipQualIdent() { | 13396 void Parser::SkipQualIdent() { |
| 13282 ASSERT(IsIdentifier()); | 13397 ASSERT(IsIdentifier()); |
| 13283 ConsumeToken(); | 13398 ConsumeToken(); |
| 13284 if (CurrentToken() == Token::kPERIOD) { | 13399 if (CurrentToken() == Token::kPERIOD) { |
| 13285 ConsumeToken(); // Consume the kPERIOD token. | 13400 ConsumeToken(); // Consume the kPERIOD token. |
| 13286 ExpectIdentifier("identifier expected after '.'"); | 13401 ExpectIdentifier("identifier expected after '.'"); |
| 13287 } | 13402 } |
| 13288 } | 13403 } |
| 13289 | 13404 |
| 13290 } // namespace dart | 13405 } // namespace dart |
| OLD | NEW |