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 |