| 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 5978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5989 Scanner::kNoSourcePos, | 5989 Scanner::kNoSourcePos, |
| 5990 stack_trace_param.var, | 5990 stack_trace_param.var, |
| 5991 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); | 5991 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); |
| 5992 } | 5992 } |
| 5993 | 5993 |
| 5994 SaveExceptionAndStacktrace(exception_var, stack_trace_var); | 5994 SaveExceptionAndStacktrace(exception_var, stack_trace_var); |
| 5995 | 5995 |
| 5996 ASSERT(try_blocks_list_ != NULL); | 5996 ASSERT(try_blocks_list_ != NULL); |
| 5997 ASSERT(innermost_function().IsAsyncClosure() || | 5997 ASSERT(innermost_function().IsAsyncClosure() || |
| 5998 innermost_function().IsAsyncFunction()); | 5998 innermost_function().IsAsyncFunction()); |
| 5999 if ((try_blocks_list_->outer_try_block() != NULL) && | 5999 const TryBlocks* outer_try_block = try_blocks_list_->outer_try_block(); |
| 6000 (try_blocks_list_->outer_try_block()->try_block() | 6000 if (outer_try_block != NULL) { |
| 6001 ->scope->function_level() == | 6001 LocalScope* scope = outer_try_block->try_block()->scope; |
| 6002 current_block_->scope->function_level())) { | 6002 if (scope->function_level() == current_block_->scope->function_level()) { |
| 6003 // We need to unchain three scope levels: catch clause, catch | 6003 current_block_->statements->Add( |
| 6004 // parameters, and the general try block. | 6004 AwaitTransformer::RestoreSavedTryContext( |
| 6005 current_block_->statements->Add( | 6005 Z, scope->parent(), outer_try_block->try_index())); |
| 6006 AwaitTransformer::RestoreSavedTryContext( | 6006 } |
| 6007 Z, | |
| 6008 current_block_->scope->parent()->parent()->parent(), | |
| 6009 try_blocks_list_->outer_try_block()->try_index())); | |
| 6010 } | 6007 } |
| 6011 | 6008 |
| 6012 // Complete the async future with an error. | 6009 // Complete the async future with an error. |
| 6013 // Since we control the catch block there is no need to generate a nested | 6010 // Since we control the catch block there is no need to generate a nested |
| 6014 // if/then/else. | 6011 // if/then/else. |
| 6015 LocalVariable* async_completer = current_block_->scope->LookupVariable( | 6012 LocalVariable* async_completer = current_block_->scope->LookupVariable( |
| 6016 Symbols::AsyncCompleter(), false); | 6013 Symbols::AsyncCompleter(), false); |
| 6017 ASSERT(async_completer != NULL); | 6014 ASSERT(async_completer != NULL); |
| 6018 ArgumentListNode* completer_args = | 6015 ArgumentListNode* completer_args = |
| 6019 new (Z) ArgumentListNode(Scanner::kNoSourcePos); | 6016 new (Z) ArgumentListNode(Scanner::kNoSourcePos); |
| (...skipping 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8329 ExpectToken(Token::kLBRACE); | 8326 ExpectToken(Token::kLBRACE); |
| 8330 | 8327 |
| 8331 // In case of async closures we need to restore the saved try index of an | 8328 // In case of async closures we need to restore the saved try index of an |
| 8332 // outer try block (if it exists). The current try block has already been | 8329 // outer try block (if it exists). The current try block has already been |
| 8333 // removed from the stack of try blocks. | 8330 // removed from the stack of try blocks. |
| 8334 if ((innermost_function().IsAsyncClosure() || | 8331 if ((innermost_function().IsAsyncClosure() || |
| 8335 innermost_function().IsAsyncFunction() || | 8332 innermost_function().IsAsyncFunction() || |
| 8336 innermost_function().IsSyncGenClosure() || | 8333 innermost_function().IsSyncGenClosure() || |
| 8337 innermost_function().IsSyncGenerator()) && | 8334 innermost_function().IsSyncGenerator()) && |
| 8338 (try_blocks_list_ != NULL)) { | 8335 (try_blocks_list_ != NULL)) { |
| 8339 // We need two unchain two scopes: finally clause, and the try block level. | 8336 LocalScope* scope = try_blocks_list_->try_block()->scope; |
| 8340 current_block_->statements->Add( | 8337 if (scope->function_level() == current_block_->scope->function_level()) { |
| 8341 AwaitTransformer::RestoreSavedTryContext( | 8338 current_block_->statements->Add( |
| 8342 Z, | 8339 AwaitTransformer::RestoreSavedTryContext( |
| 8343 current_block_->scope->parent()->parent(), | 8340 Z, scope->parent(), try_blocks_list_->try_index())); |
| 8344 try_blocks_list_->try_index())); | 8341 } |
| 8345 } | 8342 } |
| 8346 | 8343 |
| 8347 ParseStatementSequence(); | 8344 ParseStatementSequence(); |
| 8348 ExpectToken(Token::kRBRACE); | 8345 ExpectToken(Token::kRBRACE); |
| 8349 SequenceNode* finally_block = CloseBlock(); | 8346 SequenceNode* finally_block = CloseBlock(); |
| 8350 return finally_block; | 8347 return finally_block; |
| 8351 } | 8348 } |
| 8352 | 8349 |
| 8353 | 8350 |
| 8354 void Parser::PushTryBlock(Block* try_block) { | 8351 void Parser::PushTryBlock(Block* try_block) { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8486 // declarations in the body to shadow the catch parameters. | 8483 // declarations in the body to shadow the catch parameters. |
| 8487 CheckToken(Token::kLBRACE); | 8484 CheckToken(Token::kLBRACE); |
| 8488 | 8485 |
| 8489 // In case of async closures we need to restore the saved try index of an | 8486 // In case of async closures we need to restore the saved try index of an |
| 8490 // outer try block (if it exists). | 8487 // outer try block (if it exists). |
| 8491 ASSERT(try_blocks_list_ != NULL); | 8488 ASSERT(try_blocks_list_ != NULL); |
| 8492 if (innermost_function().IsAsyncClosure() || | 8489 if (innermost_function().IsAsyncClosure() || |
| 8493 innermost_function().IsAsyncFunction() || | 8490 innermost_function().IsAsyncFunction() || |
| 8494 innermost_function().IsSyncGenClosure() || | 8491 innermost_function().IsSyncGenClosure() || |
| 8495 innermost_function().IsSyncGenerator()) { | 8492 innermost_function().IsSyncGenerator()) { |
| 8496 if ((try_blocks_list_->outer_try_block() != NULL) && | 8493 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); |
| 8497 (try_blocks_list_->outer_try_block()->try_block() | 8494 if (try_block != NULL) { |
| 8498 ->scope->function_level() == | 8495 LocalScope* scope = try_block->try_block()->scope; |
| 8499 current_block_->scope->function_level())) { | 8496 if (scope->function_level() == |
| 8500 // We need to unchain three scope levels: catch clause, catch | 8497 current_block_->scope->function_level()) { |
| 8501 // parameters, and the general try block. | 8498 current_block_->statements->Add( |
| 8502 current_block_->statements->Add( | 8499 AwaitTransformer::RestoreSavedTryContext( |
| 8503 AwaitTransformer::RestoreSavedTryContext( | 8500 Z, scope->parent(), try_block->try_index())); |
| 8504 Z, | 8501 } |
| 8505 current_block_->scope->parent()->parent()->parent(), | |
| 8506 try_blocks_list_->outer_try_block()->try_index())); | |
| 8507 } | 8502 } |
| 8508 SaveExceptionAndStacktrace(exception_var, stack_trace_var); | 8503 SaveExceptionAndStacktrace(exception_var, stack_trace_var); |
| 8509 } | 8504 } |
| 8510 | 8505 |
| 8511 current_block_->statements->Add(ParseNestedStatement(false, NULL)); | 8506 current_block_->statements->Add(ParseNestedStatement(false, NULL)); |
| 8512 catch_blocks.Add(CloseBlock()); | 8507 catch_blocks.Add(CloseBlock()); |
| 8513 | 8508 |
| 8514 const bool is_bad_type = | 8509 const bool is_bad_type = |
| 8515 exception_param.type->IsMalformed() || | 8510 exception_param.type->IsMalformed() || |
| 8516 exception_param.type->IsMalbounded(); | 8511 exception_param.type->IsMalbounded(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8587 // The last body is entered unconditionally. Start building the | 8582 // The last body is entered unconditionally. Start building the |
| 8588 // if/then/else nest with that body as the innermost else block. | 8583 // if/then/else nest with that body as the innermost else block. |
| 8589 // Note that it is nested inside an extra block which we opened | 8584 // Note that it is nested inside an extra block which we opened |
| 8590 // before we knew the body was entered unconditionally. | 8585 // before we knew the body was entered unconditionally. |
| 8591 type_tests.RemoveLast(); | 8586 type_tests.RemoveLast(); |
| 8592 current_block_->statements->Add(catch_blocks.RemoveLast()); | 8587 current_block_->statements->Add(catch_blocks.RemoveLast()); |
| 8593 current = CloseBlock(); | 8588 current = CloseBlock(); |
| 8594 } | 8589 } |
| 8595 // If the last body was entered conditionally and there is no need to add | 8590 // If the last body was entered conditionally and there is no need to add |
| 8596 // a rethrow, use an empty else body (current = NULL above). | 8591 // a rethrow, use an empty else body (current = NULL above). |
| 8597 | |
| 8598 while (!type_tests.is_empty()) { | 8592 while (!type_tests.is_empty()) { |
| 8599 AstNode* type_test = type_tests.RemoveLast(); | 8593 AstNode* type_test = type_tests.RemoveLast(); |
| 8600 SequenceNode* catch_block = catch_blocks.RemoveLast(); | 8594 SequenceNode* catch_block = catch_blocks.RemoveLast(); |
| 8601 | 8595 current_block_->statements->Add(new(Z) IfNode( |
| 8602 // TODO(regis): Understand the purpose of the following code restoring | 8596 type_test->token_pos(), type_test, catch_block, current)); |
| 8603 // :saved_try_context_var. This code was added as part of r39926. | 8597 current = CloseBlock(); |
| 8604 // In some cases, this code even crashed the compiler (debug mode assert), | 8598 } |
| 8605 // because the scope unchaining was starting from the wrong block. | 8599 // Restore :saved_try_context_var before executing the catch clauses. |
| 8606 // The catch clause(s) emitted below contain the same restoring code. | 8600 if (current != NULL) { |
| 8607 // So why is it necessary? Could it be an attempt to handle the case where | |
| 8608 // the catch clause is replaced by a throw because of a bad type? It is not | |
| 8609 // necessary in this case either, because no await could have been executed | |
| 8610 // between the setup of :saved_try_context_var in the try clause and here | |
| 8611 // (it is the execution of an await that clears all stack-based variables). | |
| 8612 | |
| 8613 // In case of async closures we need to restore the saved try index of an | |
| 8614 // outer try block (if it exists). | |
| 8615 ASSERT(try_blocks_list_ != NULL); | 8601 ASSERT(try_blocks_list_ != NULL); |
| 8616 if (innermost_function().IsAsyncClosure() || | 8602 if (innermost_function().IsAsyncClosure() || |
| 8617 innermost_function().IsAsyncFunction() || | 8603 innermost_function().IsAsyncFunction() || |
| 8618 innermost_function().IsSyncGenClosure() || | 8604 innermost_function().IsSyncGenClosure() || |
| 8619 innermost_function().IsSyncGenerator()) { | 8605 innermost_function().IsSyncGenerator()) { |
| 8620 if ((try_blocks_list_->outer_try_block() != NULL) && | 8606 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); |
| 8621 (try_blocks_list_->outer_try_block()->try_block() | 8607 if (try_block != NULL) { |
| 8622 ->scope->function_level() == | 8608 LocalScope* scope = try_block->try_block()->scope; |
| 8623 current_block_->scope->function_level())) { | 8609 if (scope->function_level() == |
| 8624 // We need to unchain three scope levels (from the catch block and not | 8610 current_block_->scope->function_level()) { |
| 8625 // from the current block): catch clause, catch | 8611 SequenceNode* restore_code = new(Z) SequenceNode(handler_pos, NULL); |
| 8626 // parameters, and the general try block. | 8612 restore_code->Add( |
| 8627 current_block_->statements->Add( | 8613 AwaitTransformer::RestoreSavedTryContext( |
| 8628 AwaitTransformer::RestoreSavedTryContext( | 8614 Z, scope->parent(), try_block->try_index())); |
| 8629 Z, | 8615 restore_code->Add(current); |
| 8630 catch_block->scope()->parent()->parent()->parent(), | 8616 current = restore_code; |
| 8631 try_blocks_list_->outer_try_block()->try_index())); | 8617 } |
| 8632 } | 8618 } |
| 8633 } | 8619 } |
| 8634 | |
| 8635 current_block_->statements->Add(new(Z) IfNode( | |
| 8636 type_test->token_pos(), type_test, catch_block, current)); | |
| 8637 current = CloseBlock(); | |
| 8638 } | 8620 } |
| 8639 return current; | 8621 return current; |
| 8640 } | 8622 } |
| 8641 | 8623 |
| 8642 | 8624 |
| 8643 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) { | 8625 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) { |
| 8644 const String& async_saved_try_ctx_name = String::ZoneHandle(Z, | 8626 const String& async_saved_try_ctx_name = String::ZoneHandle(Z, |
| 8645 Symbols::New(String::Handle(Z, | 8627 Symbols::New(String::Handle(Z, |
| 8646 String::NewFormatted("%s%d", | 8628 String::NewFormatted("%s%d", |
| 8647 Symbols::AsyncSavedTryCtxVarPrefix().ToCString(), | 8629 Symbols::AsyncSavedTryCtxVarPrefix().ToCString(), |
| (...skipping 4058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12706 void Parser::SkipQualIdent() { | 12688 void Parser::SkipQualIdent() { |
| 12707 ASSERT(IsIdentifier()); | 12689 ASSERT(IsIdentifier()); |
| 12708 ConsumeToken(); | 12690 ConsumeToken(); |
| 12709 if (CurrentToken() == Token::kPERIOD) { | 12691 if (CurrentToken() == Token::kPERIOD) { |
| 12710 ConsumeToken(); // Consume the kPERIOD token. | 12692 ConsumeToken(); // Consume the kPERIOD token. |
| 12711 ExpectIdentifier("identifier expected after '.'"); | 12693 ExpectIdentifier("identifier expected after '.'"); |
| 12712 } | 12694 } |
| 12713 } | 12695 } |
| 12714 | 12696 |
| 12715 } // namespace dart | 12697 } // namespace dart |
| OLD | NEW |