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 5407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5418 current_block_->scope->function_level() + 1, | 5418 current_block_->scope->function_level() + 1, |
5419 0); | 5419 0); |
5420 } | 5420 } |
5421 ChainNewBlock(outer_scope); | 5421 ChainNewBlock(outer_scope); |
5422 } | 5422 } |
5423 | 5423 |
5424 | 5424 |
5425 void Parser::OpenAsyncClosure() { | 5425 void Parser::OpenAsyncClosure() { |
5426 TRACE_PARSER("OpenAsyncClosure"); | 5426 TRACE_PARSER("OpenAsyncClosure"); |
5427 parsed_function()->set_await_temps_scope(current_block_->scope); | 5427 parsed_function()->set_await_temps_scope(current_block_->scope); |
5428 // TODO(mlippautz): Set up explicit jump table for await continuations. | |
5429 } | 5428 } |
5430 | 5429 |
5431 | 5430 |
5432 RawFunction* Parser::OpenAsyncFunction(intptr_t formal_param_pos) { | 5431 RawFunction* Parser::OpenAsyncFunction(intptr_t formal_param_pos) { |
5433 TRACE_PARSER("OpenAsyncFunction"); | 5432 TRACE_PARSER("OpenAsyncFunction"); |
5434 // Create the closure containing the old body of this function. | 5433 // Create the closure containing the old body of this function. |
5435 Class& sig_cls = Class::ZoneHandle(I); | 5434 Class& sig_cls = Class::ZoneHandle(I); |
5436 Type& sig_type = Type::ZoneHandle(I); | 5435 Type& sig_type = Type::ZoneHandle(I); |
5437 Function& closure = Function::ZoneHandle(I); | 5436 Function& closure = Function::ZoneHandle(I); |
5438 String& sig = String::ZoneHandle(I); | 5437 String& sig = String::ZoneHandle(I); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5482 // Record the begin and end token index of the scope. | 5481 // Record the begin and end token index of the scope. |
5483 ASSERT(statements != NULL); | 5482 ASSERT(statements != NULL); |
5484 current_block_->scope->set_begin_token_pos(statements->token_pos()); | 5483 current_block_->scope->set_begin_token_pos(statements->token_pos()); |
5485 current_block_->scope->set_end_token_pos(TokenPos()); | 5484 current_block_->scope->set_end_token_pos(TokenPos()); |
5486 } | 5485 } |
5487 current_block_ = current_block_->parent; | 5486 current_block_ = current_block_->parent; |
5488 return statements; | 5487 return statements; |
5489 } | 5488 } |
5490 | 5489 |
5491 | 5490 |
| 5491 static inline String& BuildAsyncSavedTryContextName(Isolate* isolate, |
| 5492 int16_t id) { |
| 5493 const char* async_saved_prefix = ":async_saved_try_ctx_var_"; |
| 5494 // Can be a regular handle since we only use it to build an actual symbol. |
| 5495 const String& cnt_str = String::Handle( |
| 5496 String::NewFormatted("%s%d", async_saved_prefix, id)); |
| 5497 return String::ZoneHandle(isolate, Symbols::New(cnt_str)); |
| 5498 } |
| 5499 |
| 5500 |
5492 SequenceNode* Parser::CloseAsyncFunction(const Function& closure, | 5501 SequenceNode* Parser::CloseAsyncFunction(const Function& closure, |
5493 SequenceNode* closure_body) { | 5502 SequenceNode* closure_body) { |
5494 TRACE_PARSER("CloseAsyncFunction"); | 5503 TRACE_PARSER("CloseAsyncFunction"); |
5495 ASSERT(!closure.IsNull()); | 5504 ASSERT(!closure.IsNull()); |
5496 ASSERT(closure_body != NULL); | 5505 ASSERT(closure_body != NULL); |
5497 // The block for the async closure body has already been closed. Close the | 5506 // The block for the async closure body has already been closed. Close the |
5498 // corresponding function block. | 5507 // corresponding function block. |
5499 CloseBlock(); | 5508 CloseBlock(); |
5500 | 5509 |
5501 // Create and return a new future that executes a closure with the current | 5510 // Create and return a new future that executes a closure with the current |
5502 // body. | 5511 // body. |
5503 | 5512 |
5504 bool found = false; | |
5505 | |
5506 // No need to capture parameters or other variables, since they have already | 5513 // No need to capture parameters or other variables, since they have already |
5507 // been captured in the corresponding scope as the body has been parsed within | 5514 // been captured in the corresponding scope as the body has been parsed within |
5508 // a nested block (contained in the async funtion's block). | 5515 // a nested block (contained in the async funtion's block). |
5509 const Class& future = Class::ZoneHandle(I, | 5516 const Class& future = Class::ZoneHandle(I, |
5510 GetClassForAsync(Symbols::Future())); | 5517 GetClassForAsync(Symbols::Future())); |
5511 ASSERT(!future.IsNull()); | 5518 ASSERT(!future.IsNull()); |
5512 const Function& constructor = Function::ZoneHandle(I, | 5519 const Function& constructor = Function::ZoneHandle(I, |
5513 future.LookupFunction(Symbols::FutureConstructor())); | 5520 future.LookupFunction(Symbols::FutureConstructor())); |
5514 ASSERT(!constructor.IsNull()); | 5521 ASSERT(!constructor.IsNull()); |
5515 const Class& completer = Class::ZoneHandle(I, | 5522 const Class& completer = Class::ZoneHandle(I, |
5516 GetClassForAsync(Symbols::Completer())); | 5523 GetClassForAsync(Symbols::Completer())); |
5517 ASSERT(!completer.IsNull()); | 5524 ASSERT(!completer.IsNull()); |
5518 const Function& completer_constructor = Function::ZoneHandle(I, | 5525 const Function& completer_constructor = Function::ZoneHandle(I, |
5519 completer.LookupFunction(Symbols::CompleterConstructor())); | 5526 completer.LookupFunction(Symbols::CompleterConstructor())); |
5520 ASSERT(!completer_constructor.IsNull()); | 5527 ASSERT(!completer_constructor.IsNull()); |
5521 | 5528 |
| 5529 bool found = false; |
5522 // Add to AST: | 5530 // Add to AST: |
5523 // var :async_op; | 5531 // var :async_op; |
5524 // var :async_completer; | 5532 // var :async_completer; |
| 5533 // var :await_jump_var; |
| 5534 // var :await_ctx_var; |
| 5535 // Add as many variables to saved the try block ctx as there were try blocks. |
| 5536 // var :async_saved_try_ctx_var_<x>; |
| 5537 const Type& dynamic_type = Type::ZoneHandle(I, Type::DynamicType()); |
5525 LocalVariable* async_op_var = new (I) LocalVariable( | 5538 LocalVariable* async_op_var = new (I) LocalVariable( |
5526 Scanner::kNoSourcePos, | 5539 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type); |
5527 Symbols::AsyncOperation(), | |
5528 Type::ZoneHandle(I, Type::DynamicType())); | |
5529 current_block_->scope->AddVariable(async_op_var); | 5540 current_block_->scope->AddVariable(async_op_var); |
5530 found = closure_body->scope()->CaptureVariable(Symbols::AsyncOperation()); | 5541 found = closure_body->scope()->CaptureVariable(Symbols::AsyncOperation()); |
5531 ASSERT(found); | 5542 ASSERT(found); |
5532 LocalVariable* async_completer = new (I) LocalVariable( | 5543 LocalVariable* async_completer = new (I) LocalVariable( |
5533 Scanner::kNoSourcePos, | 5544 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); |
5534 Symbols::AsyncCompleter(), | |
5535 Type::ZoneHandle(I, Type::DynamicType())); | |
5536 current_block_->scope->AddVariable(async_completer); | 5545 current_block_->scope->AddVariable(async_completer); |
5537 found = closure_body->scope()->CaptureVariable(Symbols::AsyncCompleter()); | 5546 found = closure_body->scope()->CaptureVariable(Symbols::AsyncCompleter()); |
5538 ASSERT(found); | 5547 ASSERT(found); |
| 5548 LocalVariable* await_jump_var = new (I) LocalVariable( |
| 5549 Scanner::kNoSourcePos, Symbols::AwaitJumpVar(), dynamic_type); |
| 5550 current_block_->scope->AddVariable(await_jump_var); |
| 5551 found = closure_body->scope()->CaptureVariable(Symbols::AwaitJumpVar()); |
| 5552 ASSERT(found); |
| 5553 LocalVariable* await_ctx_var = new (I) LocalVariable( |
| 5554 Scanner::kNoSourcePos, Symbols::AwaitContextVar(), dynamic_type); |
| 5555 current_block_->scope->AddVariable(await_ctx_var); |
| 5556 found = closure_body->scope()->CaptureVariable(Symbols::AwaitContextVar()); |
| 5557 ASSERT(found); |
| 5558 LocalVariable* async_saved_try_ctx_var; |
| 5559 for (int16_t i = 0; i < last_used_try_index_; i++) { |
| 5560 String& async_saved_try_ctx_name = BuildAsyncSavedTryContextName(I, i); |
| 5561 async_saved_try_ctx_var = new (I) LocalVariable( |
| 5562 Scanner::kNoSourcePos, async_saved_try_ctx_name, dynamic_type); |
| 5563 current_block_->scope->AddVariable(async_saved_try_ctx_var); |
| 5564 found = closure_body->scope()->CaptureVariable(async_saved_try_ctx_name); |
| 5565 ASSERT(found); |
| 5566 } |
5539 | 5567 |
5540 // Add to AST: | 5568 // Add to AST: |
5541 // :async_completer = new Completer(); | 5569 // :async_completer = new Completer(); |
5542 ArgumentListNode* empty_args = new (I) ArgumentListNode( | 5570 ArgumentListNode* empty_args = |
5543 Scanner::kNoSourcePos); | 5571 new (I) ArgumentListNode(Scanner::kNoSourcePos); |
5544 ConstructorCallNode* completer_constructor_node = new (I) ConstructorCallNode( | 5572 ConstructorCallNode* completer_constructor_node = new (I) ConstructorCallNode( |
5545 Scanner::kNoSourcePos, | 5573 Scanner::kNoSourcePos, |
5546 TypeArguments::ZoneHandle(I), | 5574 TypeArguments::ZoneHandle(I), |
5547 completer_constructor, | 5575 completer_constructor, |
5548 empty_args); | 5576 empty_args); |
5549 StoreLocalNode* store_completer = new (I) StoreLocalNode( | 5577 StoreLocalNode* store_completer = new (I) StoreLocalNode( |
5550 Scanner::kNoSourcePos, | 5578 Scanner::kNoSourcePos, |
5551 async_completer, | 5579 async_completer, |
5552 completer_constructor_node); | 5580 completer_constructor_node); |
5553 current_block_->statements->Add(store_completer); | 5581 current_block_->statements->Add(store_completer); |
(...skipping 30 matching lines...) Expand all Loading... |
5584 Symbols::CompleterFuture())); | 5612 Symbols::CompleterFuture())); |
5585 current_block_->statements->Add(return_node); | 5613 current_block_->statements->Add(return_node); |
5586 return CloseBlock(); | 5614 return CloseBlock(); |
5587 } | 5615 } |
5588 | 5616 |
5589 | 5617 |
5590 void Parser::CloseAsyncClosure(SequenceNode* body) { | 5618 void Parser::CloseAsyncClosure(SequenceNode* body) { |
5591 TRACE_PARSER("CloseAsyncClosure"); | 5619 TRACE_PARSER("CloseAsyncClosure"); |
5592 // We need a temporary expression to store intermediate return values. | 5620 // We need a temporary expression to store intermediate return values. |
5593 parsed_function()->EnsureExpressionTemp(); | 5621 parsed_function()->EnsureExpressionTemp(); |
| 5622 // Implicitly mark those variables below as captured. We currently mark all |
| 5623 // variables of all scopes as captured (below), but as soon as we do something |
| 5624 // smarter we rely on these internal variables to be available. |
| 5625 body->scope()->LookupVariable(Symbols::Completer(), false); |
| 5626 body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 5627 body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
| 5628 body->scope()->RecursivelyCaptureAllVariables(); |
5594 } | 5629 } |
5595 | 5630 |
5596 | 5631 |
5597 // Set up default values for all optional parameters to the function. | 5632 // Set up default values for all optional parameters to the function. |
5598 void Parser::SetupDefaultsForOptionalParams(const ParamList* params, | 5633 void Parser::SetupDefaultsForOptionalParams(const ParamList* params, |
5599 Array* default_values) { | 5634 Array* default_values) { |
5600 if (params->num_optional_parameters > 0) { | 5635 if (params->num_optional_parameters > 0) { |
5601 // Build array of default parameter values. | 5636 // Build array of default parameter values. |
5602 ParamDesc* param = | 5637 ParamDesc* param = |
5603 params->parameters->data() + params->num_fixed_parameters; | 5638 params->parameters->data() + params->num_fixed_parameters; |
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7118 } | 7153 } |
7119 stack_trace_param->var = var; | 7154 stack_trace_param->var = var; |
7120 } | 7155 } |
7121 } | 7156 } |
7122 | 7157 |
7123 | 7158 |
7124 SequenceNode* Parser::ParseFinallyBlock() { | 7159 SequenceNode* Parser::ParseFinallyBlock() { |
7125 TRACE_PARSER("ParseFinallyBlock"); | 7160 TRACE_PARSER("ParseFinallyBlock"); |
7126 OpenBlock(); | 7161 OpenBlock(); |
7127 ExpectToken(Token::kLBRACE); | 7162 ExpectToken(Token::kLBRACE); |
| 7163 |
| 7164 // In case of async closures we need to restore the saved try index of an |
| 7165 // outer try block (if it exists). The current try block has already been |
| 7166 // removed from the stack of try blocks. |
| 7167 if (current_function().is_async_closure() && (try_blocks_list_ != NULL)) { |
| 7168 // We need two unchain two scopes: finally clause, and the try block level. |
| 7169 SetupSavedTryContext(current_block_->scope->parent()->parent(), |
| 7170 try_blocks_list_->try_index(), |
| 7171 current_block_->statements); |
| 7172 } else { |
| 7173 parsed_function()->reset_saved_try_ctx_vars(); |
| 7174 } |
| 7175 |
7128 ParseStatementSequence(); | 7176 ParseStatementSequence(); |
7129 ExpectToken(Token::kRBRACE); | 7177 ExpectToken(Token::kRBRACE); |
7130 SequenceNode* finally_block = CloseBlock(); | 7178 SequenceNode* finally_block = CloseBlock(); |
7131 return finally_block; | 7179 return finally_block; |
7132 } | 7180 } |
7133 | 7181 |
7134 | 7182 |
7135 void Parser::PushTryBlock(Block* try_block) { | 7183 void Parser::PushTryBlock(Block* try_block) { |
7136 intptr_t try_index = AllocateTryIndex(); | 7184 intptr_t try_index = AllocateTryIndex(); |
7137 TryBlocks* block = new(I) TryBlocks( | 7185 TryBlocks* block = new(I) TryBlocks( |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7263 current_block_->statements->Add(new(I) InstanceCallNode( | 7311 current_block_->statements->Add(new(I) InstanceCallNode( |
7264 catch_pos, | 7312 catch_pos, |
7265 new(I) LoadLocalNode(catch_pos, stack_trace_param.var), | 7313 new(I) LoadLocalNode(catch_pos, stack_trace_param.var), |
7266 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()), | 7314 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()), |
7267 no_args)); | 7315 no_args)); |
7268 } | 7316 } |
7269 | 7317 |
7270 // Add nested block with user-defined code. This blocks allows | 7318 // Add nested block with user-defined code. This blocks allows |
7271 // declarations in the body to shadow the catch parameters. | 7319 // declarations in the body to shadow the catch parameters. |
7272 CheckToken(Token::kLBRACE); | 7320 CheckToken(Token::kLBRACE); |
| 7321 |
| 7322 // In case of async closures we need to restore the saved try index of an |
| 7323 // outer try block (if it exists). |
| 7324 ASSERT(try_blocks_list_ != NULL); |
| 7325 if (current_function().is_async_closure() && |
| 7326 (try_blocks_list_->outer_try_block() != NULL)) { |
| 7327 // We need to unchain three scope levels: catch clause, catch parameters, |
| 7328 // and the general try block. |
| 7329 SetupSavedTryContext(current_block_->scope->parent()->parent()->parent(), |
| 7330 try_blocks_list_->outer_try_block()->try_index(), |
| 7331 current_block_->statements); |
| 7332 } else { |
| 7333 parsed_function()->reset_saved_try_ctx_vars(); |
| 7334 } |
| 7335 |
7273 current_block_->statements->Add(ParseNestedStatement(false, NULL)); | 7336 current_block_->statements->Add(ParseNestedStatement(false, NULL)); |
7274 catch_blocks.Add(CloseBlock()); | 7337 catch_blocks.Add(CloseBlock()); |
7275 | 7338 |
7276 const bool is_bad_type = | 7339 const bool is_bad_type = |
7277 exception_param.type->IsMalformed() || | 7340 exception_param.type->IsMalformed() || |
7278 exception_param.type->IsMalbounded(); | 7341 exception_param.type->IsMalbounded(); |
7279 if (exception_param.type->IsDynamicType() || is_bad_type) { | 7342 if (exception_param.type->IsDynamicType() || is_bad_type) { |
7280 // There is no exception type or else it is malformed or malbounded. | 7343 // There is no exception type or else it is malformed or malbounded. |
7281 // In the first case, unconditionally execute the catch body. In the | 7344 // In the first case, unconditionally execute the catch body. In the |
7282 // second case, unconditionally throw. | 7345 // second case, unconditionally throw. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7358 AstNode* type_test = type_tests.RemoveLast(); | 7421 AstNode* type_test = type_tests.RemoveLast(); |
7359 SequenceNode* catch_block = catch_blocks.RemoveLast(); | 7422 SequenceNode* catch_block = catch_blocks.RemoveLast(); |
7360 current_block_->statements->Add(new(I) IfNode( | 7423 current_block_->statements->Add(new(I) IfNode( |
7361 type_test->token_pos(), type_test, catch_block, current)); | 7424 type_test->token_pos(), type_test, catch_block, current)); |
7362 current = CloseBlock(); | 7425 current = CloseBlock(); |
7363 } | 7426 } |
7364 return current; | 7427 return current; |
7365 } | 7428 } |
7366 | 7429 |
7367 | 7430 |
| 7431 // Set up the currently relevant :saved_try_context_var on the stack: |
| 7432 // * Try blocks: Set the context variable for this try block. |
| 7433 // * Catch/finally blocks: Set the context variable for any outer try block (if |
| 7434 // existent). |
| 7435 // |
| 7436 // Also save the captured variable and the stack variable to be able to set |
| 7437 // it after a function continues execution (await). |
| 7438 void Parser::SetupSavedTryContext(LocalScope* saved_try_context_scope, |
| 7439 int16_t try_index, |
| 7440 SequenceNode* target) { |
| 7441 LocalVariable* saved_try_ctx = saved_try_context_scope->LookupVariable( |
| 7442 Symbols::SavedTryContextVar(), false); |
| 7443 ASSERT((saved_try_ctx != NULL) && !saved_try_ctx->is_captured()); |
| 7444 const String& async_saved_try_ctx_name = |
| 7445 BuildAsyncSavedTryContextName(I, try_index); |
| 7446 LocalVariable* async_saved_try_ctx = |
| 7447 target->scope()->LookupVariable(async_saved_try_ctx_name, false); |
| 7448 ASSERT((async_saved_try_ctx != NULL) && async_saved_try_ctx->is_captured()); |
| 7449 target->Add(new (I) StoreLocalNode( |
| 7450 Scanner::kNoSourcePos, saved_try_ctx, new (I) LoadLocalNode( |
| 7451 Scanner::kNoSourcePos, async_saved_try_ctx))); |
| 7452 |
| 7453 parsed_function()->set_saved_try_ctx(saved_try_ctx); |
| 7454 parsed_function()->set_async_saved_try_ctx(async_saved_try_ctx); |
| 7455 } |
| 7456 |
| 7457 |
7368 AstNode* Parser::ParseTryStatement(String* label_name) { | 7458 AstNode* Parser::ParseTryStatement(String* label_name) { |
7369 TRACE_PARSER("ParseTryStatement"); | 7459 TRACE_PARSER("ParseTryStatement"); |
7370 | 7460 |
7371 // We create three variables for exceptions here: | 7461 // We create three variables for exceptions here: |
7372 // ':saved_try_context_var' - Used to save the context before the start of | 7462 // ':saved_try_context_var' - Used to save the context before the start of |
7373 // the try block. The context register is | 7463 // the try block. The context register is |
7374 // restored from this variable before | 7464 // restored from this variable before |
7375 // processing the catch block handler. | 7465 // processing the catch block handler. |
7376 // ':exception_var' - Used to save the current exception object that was | 7466 // ':exception_var' - Used to save the current exception object that was |
7377 // thrown. | 7467 // thrown. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7416 if (label_name != NULL) { | 7506 if (label_name != NULL) { |
7417 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); | 7507 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); |
7418 OpenBlock(); | 7508 OpenBlock(); |
7419 current_block_->scope->AddLabel(try_label); | 7509 current_block_->scope->AddLabel(try_label); |
7420 } | 7510 } |
7421 | 7511 |
7422 // Now parse the 'try' block. | 7512 // Now parse the 'try' block. |
7423 OpenBlock(); | 7513 OpenBlock(); |
7424 PushTryBlock(current_block_); | 7514 PushTryBlock(current_block_); |
7425 ExpectToken(Token::kLBRACE); | 7515 ExpectToken(Token::kLBRACE); |
| 7516 |
| 7517 if (current_function().is_async_closure()) { |
| 7518 const String& async_saved_try_ctx_name = |
| 7519 BuildAsyncSavedTryContextName(I, last_used_try_index_ - 1); |
| 7520 LocalVariable* async_saved_try_ctx = |
| 7521 current_block_->scope->LookupVariable( |
| 7522 async_saved_try_ctx_name, false); |
| 7523 ASSERT(async_saved_try_ctx != NULL); |
| 7524 ASSERT(context_var != NULL); |
| 7525 current_block_->statements->Add(new (I) StoreLocalNode( |
| 7526 Scanner::kNoSourcePos, async_saved_try_ctx, new (I) LoadLocalNode( |
| 7527 Scanner::kNoSourcePos, context_var))); |
| 7528 parsed_function()->set_saved_try_ctx(context_var); |
| 7529 parsed_function()->set_async_saved_try_ctx(async_saved_try_ctx); |
| 7530 } |
| 7531 |
7426 ParseStatementSequence(); | 7532 ParseStatementSequence(); |
7427 ExpectToken(Token::kRBRACE); | 7533 ExpectToken(Token::kRBRACE); |
7428 SequenceNode* try_block = CloseBlock(); | 7534 SequenceNode* try_block = CloseBlock(); |
7429 | 7535 |
7430 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 7536 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
7431 (CurrentToken() != Token::kFINALLY)) { | 7537 (CurrentToken() != Token::kFINALLY)) { |
7432 ReportError("catch or finally clause expected"); | 7538 ReportError("catch or finally clause expected"); |
7433 } | 7539 } |
7434 | 7540 |
7435 // Now parse the 'catch' blocks if any. | 7541 // Now parse the 'catch' blocks if any. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7488 // and attach the label to it. | 7594 // and attach the label to it. |
7489 AstNode* try_catch_node = new(I) TryCatchNode( | 7595 AstNode* try_catch_node = new(I) TryCatchNode( |
7490 try_pos, try_block, context_var, catch_clause, finally_block, try_index); | 7596 try_pos, try_block, context_var, catch_clause, finally_block, try_index); |
7491 | 7597 |
7492 if (try_label != NULL) { | 7598 if (try_label != NULL) { |
7493 current_block_->statements->Add(try_catch_node); | 7599 current_block_->statements->Add(try_catch_node); |
7494 SequenceNode* sequence = CloseBlock(); | 7600 SequenceNode* sequence = CloseBlock(); |
7495 sequence->set_label(try_label); | 7601 sequence->set_label(try_label); |
7496 try_catch_node = sequence; | 7602 try_catch_node = sequence; |
7497 } | 7603 } |
| 7604 |
| 7605 // In case of async closures we need to restore the saved try index of an |
| 7606 // outer try block (if it exists). |
| 7607 if (current_function().is_async_closure() && |
| 7608 (outer_try_index != CatchClauseNode::kInvalidTryIndex)) { |
| 7609 SequenceNode* try_catch_and_restore_try_ctx = new (I) SequenceNode( |
| 7610 Scanner::kNoSourcePos, current_block_->scope); |
| 7611 try_catch_and_restore_try_ctx->Add(try_catch_node); |
| 7612 SetupSavedTryContext( |
| 7613 current_block_->scope, outer_try_index, try_catch_and_restore_try_ctx); |
| 7614 return try_catch_and_restore_try_ctx; |
| 7615 } else { |
| 7616 parsed_function()->reset_saved_try_ctx_vars(); |
| 7617 } |
| 7618 |
7498 return try_catch_node; | 7619 return try_catch_node; |
7499 } | 7620 } |
7500 | 7621 |
7501 | 7622 |
7502 AstNode* Parser::ParseJump(String* label_name) { | 7623 AstNode* Parser::ParseJump(String* label_name) { |
7503 TRACE_PARSER("ParseJump"); | 7624 TRACE_PARSER("ParseJump"); |
7504 ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE); | 7625 ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE); |
7505 Token::Kind jump_kind = CurrentToken(); | 7626 Token::Kind jump_kind = CurrentToken(); |
7506 const intptr_t jump_pos = TokenPos(); | 7627 const intptr_t jump_pos = TokenPos(); |
7507 SourceLabel* target = NULL; | 7628 SourceLabel* target = NULL; |
(...skipping 3758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11266 void Parser::SkipQualIdent() { | 11387 void Parser::SkipQualIdent() { |
11267 ASSERT(IsIdentifier()); | 11388 ASSERT(IsIdentifier()); |
11268 ConsumeToken(); | 11389 ConsumeToken(); |
11269 if (CurrentToken() == Token::kPERIOD) { | 11390 if (CurrentToken() == Token::kPERIOD) { |
11270 ConsumeToken(); // Consume the kPERIOD token. | 11391 ConsumeToken(); // Consume the kPERIOD token. |
11271 ExpectIdentifier("identifier expected after '.'"); | 11392 ExpectIdentifier("identifier expected after '.'"); |
11272 } | 11393 } |
11273 } | 11394 } |
11274 | 11395 |
11275 } // namespace dart | 11396 } // namespace dart |
OLD | NEW |