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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5494 TRACE_PARSER("CloseAsyncFunction"); | 5493 TRACE_PARSER("CloseAsyncFunction"); |
5495 ASSERT(!closure.IsNull()); | 5494 ASSERT(!closure.IsNull()); |
5496 ASSERT(closure_body != NULL); | 5495 ASSERT(closure_body != NULL); |
5497 // The block for the async closure body has already been closed. Close the | 5496 // The block for the async closure body has already been closed. Close the |
5498 // corresponding function block. | 5497 // corresponding function block. |
5499 CloseBlock(); | 5498 CloseBlock(); |
5500 | 5499 |
5501 // Create and return a new future that executes a closure with the current | 5500 // Create and return a new future that executes a closure with the current |
5502 // body. | 5501 // body. |
5503 | 5502 |
5504 bool found = false; | |
5505 | |
5506 // No need to capture parameters or other variables, since they have already | 5503 // 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 | 5504 // been captured in the corresponding scope as the body has been parsed within |
5508 // a nested block (contained in the async funtion's block). | 5505 // a nested block (contained in the async funtion's block). |
5509 const Class& future = Class::ZoneHandle(I, | 5506 const Class& future = Class::ZoneHandle(I, |
5510 GetClassForAsync(Symbols::Future())); | 5507 GetClassForAsync(Symbols::Future())); |
5511 ASSERT(!future.IsNull()); | 5508 ASSERT(!future.IsNull()); |
5512 const Function& constructor = Function::ZoneHandle(I, | 5509 const Function& constructor = Function::ZoneHandle(I, |
5513 future.LookupFunction(Symbols::FutureConstructor())); | 5510 future.LookupFunction(Symbols::FutureConstructor())); |
5514 ASSERT(!constructor.IsNull()); | 5511 ASSERT(!constructor.IsNull()); |
5515 const Class& completer = Class::ZoneHandle(I, | 5512 const Class& completer = Class::ZoneHandle(I, |
5516 GetClassForAsync(Symbols::Completer())); | 5513 GetClassForAsync(Symbols::Completer())); |
5517 ASSERT(!completer.IsNull()); | 5514 ASSERT(!completer.IsNull()); |
5518 const Function& completer_constructor = Function::ZoneHandle(I, | 5515 const Function& completer_constructor = Function::ZoneHandle(I, |
5519 completer.LookupFunction(Symbols::CompleterConstructor())); | 5516 completer.LookupFunction(Symbols::CompleterConstructor())); |
5520 ASSERT(!completer_constructor.IsNull()); | 5517 ASSERT(!completer_constructor.IsNull()); |
5521 | 5518 |
5519 bool found = false; | |
5522 // Add to AST: | 5520 // Add to AST: |
5523 // var :async_op; | 5521 // var :async_op; |
5524 // var :async_completer; | 5522 // var :async_completer; |
5523 // var :await_jump_var; | |
5524 // var :await_ctx_var; | |
5525 // Add as many variables to saved the try block ctx as there were try blocks. | |
5526 // var :await_saved_try_ctx_var_<x>; | |
hausner
2014/08/25 20:26:14
is the name :await_saved_try_ctx_var_ or :async_sa
Michael Lippautz (Google)
2014/08/26 16:45:48
Done. Using :async_...
| |
5527 Type& dynamic_type = Type::ZoneHandle(I, Type::DynamicType()); | |
hausner
2014/08/25 20:26:14
const
Michael Lippautz (Google)
2014/08/26 16:45:48
Done.
| |
5525 LocalVariable* async_op_var = new (I) LocalVariable( | 5528 LocalVariable* async_op_var = new (I) LocalVariable( |
5526 Scanner::kNoSourcePos, | 5529 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type); |
5527 Symbols::AsyncOperation(), | |
5528 Type::ZoneHandle(I, Type::DynamicType())); | |
5529 current_block_->scope->AddVariable(async_op_var); | 5530 current_block_->scope->AddVariable(async_op_var); |
5530 found = closure_body->scope()->CaptureVariable(Symbols::AsyncOperation()); | 5531 found = closure_body->scope()->CaptureVariable(Symbols::AsyncOperation()); |
5531 ASSERT(found); | 5532 ASSERT(found); |
5532 LocalVariable* async_completer = new (I) LocalVariable( | 5533 LocalVariable* async_completer = new (I) LocalVariable( |
5533 Scanner::kNoSourcePos, | 5534 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); |
5534 Symbols::AsyncCompleter(), | |
5535 Type::ZoneHandle(I, Type::DynamicType())); | |
5536 current_block_->scope->AddVariable(async_completer); | 5535 current_block_->scope->AddVariable(async_completer); |
5537 found = closure_body->scope()->CaptureVariable(Symbols::AsyncCompleter()); | 5536 found = closure_body->scope()->CaptureVariable(Symbols::AsyncCompleter()); |
5538 ASSERT(found); | 5537 ASSERT(found); |
5538 LocalVariable* await_jump_var = new (I) LocalVariable( | |
5539 Scanner::kNoSourcePos, Symbols::AwaitJumpVar(), dynamic_type); | |
5540 current_block_->scope->AddVariable(await_jump_var); | |
5541 found = closure_body->scope()->CaptureVariable(Symbols::AwaitJumpVar()); | |
5542 ASSERT(found); | |
5543 LocalVariable* await_ctx_var = new (I) LocalVariable( | |
5544 Scanner::kNoSourcePos, Symbols::AwaitContextVar(), dynamic_type); | |
5545 current_block_->scope->AddVariable(await_ctx_var); | |
5546 found = closure_body->scope()->CaptureVariable(Symbols::AwaitContextVar()); | |
5547 ASSERT(found); | |
5548 LocalVariable* async_saved_try_ctx_var; | |
5549 const char* async_saved_prefix = ":async_saved_try_ctx_var_"; | |
5550 for (int16_t i = 0; i < last_used_try_index_; i++) { | |
5551 const String& cnt_str = String::ZoneHandle( | |
hausner
2014/08/25 20:26:14
cnt_str can be a regular handle, need not be a zon
Michael Lippautz (Google)
2014/08/26 16:45:48
Done: BuildAsyncSavedTryContextName()
| |
5552 I, String::NewFormatted("%s%d", async_saved_prefix, i)); | |
5553 const String& symbol = String::ZoneHandle(I, Symbols::New(cnt_str)); | |
5554 async_saved_try_ctx_var = new (I) LocalVariable( | |
5555 Scanner::kNoSourcePos, symbol, dynamic_type); | |
5556 current_block_->scope->AddVariable(async_saved_try_ctx_var); | |
5557 found = closure_body->scope()->CaptureVariable(symbol); | |
5558 ASSERT(found); | |
5559 } | |
5539 | 5560 |
5540 // Add to AST: | 5561 // Add to AST: |
5541 // :async_completer = new Completer(); | 5562 // :async_completer = new Completer(); |
5542 ArgumentListNode* empty_args = new (I) ArgumentListNode( | 5563 ArgumentListNode* empty_args = |
5543 Scanner::kNoSourcePos); | 5564 new (I) ArgumentListNode(Scanner::kNoSourcePos); |
5544 ConstructorCallNode* completer_constructor_node = new (I) ConstructorCallNode( | 5565 ConstructorCallNode* completer_constructor_node = new (I) ConstructorCallNode( |
5545 Scanner::kNoSourcePos, | 5566 Scanner::kNoSourcePos, |
5546 TypeArguments::ZoneHandle(I), | 5567 TypeArguments::ZoneHandle(I), |
5547 completer_constructor, | 5568 completer_constructor, |
5548 empty_args); | 5569 empty_args); |
5549 StoreLocalNode* store_completer = new (I) StoreLocalNode( | 5570 StoreLocalNode* store_completer = new (I) StoreLocalNode( |
5550 Scanner::kNoSourcePos, | 5571 Scanner::kNoSourcePos, |
5551 async_completer, | 5572 async_completer, |
5552 completer_constructor_node); | 5573 completer_constructor_node); |
5553 current_block_->statements->Add(store_completer); | 5574 current_block_->statements->Add(store_completer); |
(...skipping 30 matching lines...) Expand all Loading... | |
5584 Symbols::CompleterFuture())); | 5605 Symbols::CompleterFuture())); |
5585 current_block_->statements->Add(return_node); | 5606 current_block_->statements->Add(return_node); |
5586 return CloseBlock(); | 5607 return CloseBlock(); |
5587 } | 5608 } |
5588 | 5609 |
5589 | 5610 |
5590 void Parser::CloseAsyncClosure(SequenceNode* body) { | 5611 void Parser::CloseAsyncClosure(SequenceNode* body) { |
5591 TRACE_PARSER("CloseAsyncClosure"); | 5612 TRACE_PARSER("CloseAsyncClosure"); |
5592 // We need a temporary expression to store intermediate return values. | 5613 // We need a temporary expression to store intermediate return values. |
5593 parsed_function()->EnsureExpressionTemp(); | 5614 parsed_function()->EnsureExpressionTemp(); |
5615 // Implicitly mark those variables below as captured. We currently mark all | |
5616 // variables of all scopes as captured (below), but as soon as we do something | |
5617 // smarter we rely on these internal variables to be available. | |
5618 body->scope()->LookupVariable(Symbols::Completer(), false); | |
5619 body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | |
5620 body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); | |
5621 body->scope()->RecursivelyCaptureAllVariables(); | |
5594 } | 5622 } |
5595 | 5623 |
5596 | 5624 |
5597 // Set up default values for all optional parameters to the function. | 5625 // Set up default values for all optional parameters to the function. |
5598 void Parser::SetupDefaultsForOptionalParams(const ParamList* params, | 5626 void Parser::SetupDefaultsForOptionalParams(const ParamList* params, |
5599 Array* default_values) { | 5627 Array* default_values) { |
5600 if (params->num_optional_parameters > 0) { | 5628 if (params->num_optional_parameters > 0) { |
5601 // Build array of default parameter values. | 5629 // Build array of default parameter values. |
5602 ParamDesc* param = | 5630 ParamDesc* param = |
5603 params->parameters->data() + params->num_fixed_parameters; | 5631 params->parameters->data() + params->num_fixed_parameters; |
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7118 } | 7146 } |
7119 stack_trace_param->var = var; | 7147 stack_trace_param->var = var; |
7120 } | 7148 } |
7121 } | 7149 } |
7122 | 7150 |
7123 | 7151 |
7124 SequenceNode* Parser::ParseFinallyBlock() { | 7152 SequenceNode* Parser::ParseFinallyBlock() { |
7125 TRACE_PARSER("ParseFinallyBlock"); | 7153 TRACE_PARSER("ParseFinallyBlock"); |
7126 OpenBlock(); | 7154 OpenBlock(); |
7127 ExpectToken(Token::kLBRACE); | 7155 ExpectToken(Token::kLBRACE); |
7156 | |
7157 // In case of async closures we need to restore the saved try index of an | |
7158 // outer try block (if it exists). The current try block has already been | |
7159 // removed from the stack of try blocks. | |
7160 if (current_function().is_async_closure() && (try_blocks_list_ != NULL)) { | |
7161 // We need two unchain two scopes: finally clause, and the try block level. | |
7162 SetupSavedTryContext(current_block_->scope->parent()->parent(), | |
7163 try_blocks_list_->try_index(), | |
7164 current_block_->statements); | |
7165 } else { | |
7166 parsed_function()->reset_saved_try_ctx_vars(); | |
7167 } | |
7168 | |
7128 ParseStatementSequence(); | 7169 ParseStatementSequence(); |
7129 ExpectToken(Token::kRBRACE); | 7170 ExpectToken(Token::kRBRACE); |
7130 SequenceNode* finally_block = CloseBlock(); | 7171 SequenceNode* finally_block = CloseBlock(); |
7131 return finally_block; | 7172 return finally_block; |
7132 } | 7173 } |
7133 | 7174 |
7134 | 7175 |
7135 void Parser::PushTryBlock(Block* try_block) { | 7176 void Parser::PushTryBlock(Block* try_block) { |
7136 intptr_t try_index = AllocateTryIndex(); | 7177 intptr_t try_index = AllocateTryIndex(); |
7137 TryBlocks* block = new(I) TryBlocks( | 7178 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( | 7304 current_block_->statements->Add(new(I) InstanceCallNode( |
7264 catch_pos, | 7305 catch_pos, |
7265 new(I) LoadLocalNode(catch_pos, stack_trace_param.var), | 7306 new(I) LoadLocalNode(catch_pos, stack_trace_param.var), |
7266 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()), | 7307 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()), |
7267 no_args)); | 7308 no_args)); |
7268 } | 7309 } |
7269 | 7310 |
7270 // Add nested block with user-defined code. This blocks allows | 7311 // Add nested block with user-defined code. This blocks allows |
7271 // declarations in the body to shadow the catch parameters. | 7312 // declarations in the body to shadow the catch parameters. |
7272 CheckToken(Token::kLBRACE); | 7313 CheckToken(Token::kLBRACE); |
7314 | |
7315 // In case of async closures we need to restore the saved try index of an | |
7316 // outer try block (if it exists). | |
7317 ASSERT(try_blocks_list_ != NULL); | |
7318 if (current_function().is_async_closure() && | |
7319 (try_blocks_list_->outer_try_block() != NULL)) { | |
7320 // We need to unchain three scope levels: catch clause, catch parameters, | |
7321 // and the general try block. | |
7322 SetupSavedTryContext(current_block_->scope->parent()->parent()->parent(), | |
7323 try_blocks_list_->outer_try_block()->try_index(), | |
7324 current_block_->statements); | |
7325 } else { | |
7326 parsed_function()->reset_saved_try_ctx_vars(); | |
7327 } | |
7328 | |
7273 current_block_->statements->Add(ParseNestedStatement(false, NULL)); | 7329 current_block_->statements->Add(ParseNestedStatement(false, NULL)); |
7274 catch_blocks.Add(CloseBlock()); | 7330 catch_blocks.Add(CloseBlock()); |
7275 | 7331 |
7276 const bool is_bad_type = | 7332 const bool is_bad_type = |
7277 exception_param.type->IsMalformed() || | 7333 exception_param.type->IsMalformed() || |
7278 exception_param.type->IsMalbounded(); | 7334 exception_param.type->IsMalbounded(); |
7279 if (exception_param.type->IsDynamicType() || is_bad_type) { | 7335 if (exception_param.type->IsDynamicType() || is_bad_type) { |
7280 // There is no exception type or else it is malformed or malbounded. | 7336 // There is no exception type or else it is malformed or malbounded. |
7281 // In the first case, unconditionally execute the catch body. In the | 7337 // In the first case, unconditionally execute the catch body. In the |
7282 // second case, unconditionally throw. | 7338 // second case, unconditionally throw. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7357 while (!type_tests.is_empty()) { | 7413 while (!type_tests.is_empty()) { |
7358 AstNode* type_test = type_tests.RemoveLast(); | 7414 AstNode* type_test = type_tests.RemoveLast(); |
7359 SequenceNode* catch_block = catch_blocks.RemoveLast(); | 7415 SequenceNode* catch_block = catch_blocks.RemoveLast(); |
7360 current_block_->statements->Add(new(I) IfNode( | 7416 current_block_->statements->Add(new(I) IfNode( |
7361 type_test->token_pos(), type_test, catch_block, current)); | 7417 type_test->token_pos(), type_test, catch_block, current)); |
7362 current = CloseBlock(); | 7418 current = CloseBlock(); |
7363 } | 7419 } |
7364 return current; | 7420 return current; |
7365 } | 7421 } |
7366 | 7422 |
7367 | 7423 |
hausner
2014/08/25 20:26:14
Could you add a short comment describing what this
Michael Lippautz (Google)
2014/08/26 16:45:48
Done.
| |
7424 void Parser::SetupSavedTryContext(LocalScope* saved_try_context_scope, | |
7425 int16_t try_index, | |
7426 SequenceNode* target) { | |
7427 LocalVariable* saved_try_ctx = saved_try_context_scope->LookupVariable( | |
7428 Symbols::SavedTryContextVar(), false); | |
7429 ASSERT((saved_try_ctx != NULL) && !saved_try_ctx->is_captured()); | |
7430 const char* async_saved_prefix = ":async_saved_try_ctx_var_"; | |
7431 const String& cnt_str = String::ZoneHandle( | |
hausner
2014/08/25 20:26:14
cnt_str probably doesn't need to be a ZoneHandle;
Michael Lippautz (Google)
2014/08/26 16:45:48
Done.
| |
7432 I, String::NewFormatted("%s%d", async_saved_prefix, try_index)); | |
7433 const String& current_await_saved_try_ctx_symbol = String::ZoneHandle( | |
7434 I, Symbols::New(cnt_str)); | |
7435 LocalVariable* async_saved_try_ctx = | |
7436 target->scope()->LookupVariable( | |
7437 current_await_saved_try_ctx_symbol, false); | |
7438 ASSERT((async_saved_try_ctx != NULL) && async_saved_try_ctx->is_captured()); | |
7439 target->Add(new (I) StoreLocalNode( | |
7440 Scanner::kNoSourcePos, saved_try_ctx, new (I) LoadLocalNode( | |
7441 Scanner::kNoSourcePos, async_saved_try_ctx))); | |
7442 | |
7443 parsed_function()->set_saved_try_ctx(saved_try_ctx); | |
7444 parsed_function()->set_async_saved_try_ctx(async_saved_try_ctx); | |
7445 } | |
7446 | |
7447 | |
7368 AstNode* Parser::ParseTryStatement(String* label_name) { | 7448 AstNode* Parser::ParseTryStatement(String* label_name) { |
7369 TRACE_PARSER("ParseTryStatement"); | 7449 TRACE_PARSER("ParseTryStatement"); |
7370 | 7450 |
7371 // We create three variables for exceptions here: | 7451 // We create three variables for exceptions here: |
7372 // ':saved_try_context_var' - Used to save the context before the start of | 7452 // ':saved_try_context_var' - Used to save the context before the start of |
7373 // the try block. The context register is | 7453 // the try block. The context register is |
7374 // restored from this variable before | 7454 // restored from this variable before |
7375 // processing the catch block handler. | 7455 // processing the catch block handler. |
7376 // ':exception_var' - Used to save the current exception object that was | 7456 // ':exception_var' - Used to save the current exception object that was |
7377 // thrown. | 7457 // thrown. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7416 if (label_name != NULL) { | 7496 if (label_name != NULL) { |
7417 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); | 7497 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); |
7418 OpenBlock(); | 7498 OpenBlock(); |
7419 current_block_->scope->AddLabel(try_label); | 7499 current_block_->scope->AddLabel(try_label); |
7420 } | 7500 } |
7421 | 7501 |
7422 // Now parse the 'try' block. | 7502 // Now parse the 'try' block. |
7423 OpenBlock(); | 7503 OpenBlock(); |
7424 PushTryBlock(current_block_); | 7504 PushTryBlock(current_block_); |
7425 ExpectToken(Token::kLBRACE); | 7505 ExpectToken(Token::kLBRACE); |
7506 | |
7507 const char* async_saved_prefix = ":async_saved_try_ctx_var_"; | |
7508 if (current_function().is_async_closure()) { | |
7509 const String& cnt_str = String::ZoneHandle( | |
srdjan
2014/08/26 15:54:33
Regular handle: use ZoneHandle-s only if the varia
Michael Lippautz (Google)
2014/08/26 16:45:48
Done. Code is now refactored but uses a regular ha
| |
7510 I, String::NewFormatted("%s%d", | |
7511 async_saved_prefix, last_used_try_index_-1)); | |
7512 const String& current_await_saved_try_ctx_symbol = | |
7513 String::ZoneHandle(I, Symbols::New(cnt_str)); | |
7514 LocalVariable* async_saved_try_ctx = | |
7515 current_block_->scope->LookupVariable( | |
7516 current_await_saved_try_ctx_symbol, false); | |
7517 ASSERT(async_saved_try_ctx != NULL); | |
7518 ASSERT(context_var); | |
7519 current_block_->statements->Add(new (I) StoreLocalNode( | |
7520 Scanner::kNoSourcePos, async_saved_try_ctx, new (I) LoadLocalNode( | |
7521 Scanner::kNoSourcePos, context_var))); | |
7522 parsed_function()->set_saved_try_ctx(context_var); | |
7523 parsed_function()->set_async_saved_try_ctx(async_saved_try_ctx); | |
7524 } | |
7525 | |
7426 ParseStatementSequence(); | 7526 ParseStatementSequence(); |
7427 ExpectToken(Token::kRBRACE); | 7527 ExpectToken(Token::kRBRACE); |
7428 SequenceNode* try_block = CloseBlock(); | 7528 SequenceNode* try_block = CloseBlock(); |
7429 | 7529 |
7430 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 7530 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
7431 (CurrentToken() != Token::kFINALLY)) { | 7531 (CurrentToken() != Token::kFINALLY)) { |
7432 ReportError("catch or finally clause expected"); | 7532 ReportError("catch or finally clause expected"); |
7433 } | 7533 } |
7434 | 7534 |
7435 // Now parse the 'catch' blocks if any. | 7535 // 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. | 7588 // and attach the label to it. |
7489 AstNode* try_catch_node = new(I) TryCatchNode( | 7589 AstNode* try_catch_node = new(I) TryCatchNode( |
7490 try_pos, try_block, context_var, catch_clause, finally_block, try_index); | 7590 try_pos, try_block, context_var, catch_clause, finally_block, try_index); |
7491 | 7591 |
7492 if (try_label != NULL) { | 7592 if (try_label != NULL) { |
7493 current_block_->statements->Add(try_catch_node); | 7593 current_block_->statements->Add(try_catch_node); |
7494 SequenceNode* sequence = CloseBlock(); | 7594 SequenceNode* sequence = CloseBlock(); |
7495 sequence->set_label(try_label); | 7595 sequence->set_label(try_label); |
7496 try_catch_node = sequence; | 7596 try_catch_node = sequence; |
7497 } | 7597 } |
7598 | |
7599 // In case of async closures we need to restore the saved try index of an | |
7600 // outer try block (if it exists). | |
7601 if (current_function().is_async_closure() && | |
7602 (outer_try_index != CatchClauseNode::kInvalidTryIndex)) { | |
7603 SequenceNode* try_catch_and_restore_try_ctx = new (I) SequenceNode( | |
7604 Scanner::kNoSourcePos, current_block_->scope); | |
7605 try_catch_and_restore_try_ctx->Add(try_catch_node); | |
7606 SetupSavedTryContext( | |
7607 current_block_->scope, outer_try_index, try_catch_and_restore_try_ctx); | |
7608 return try_catch_and_restore_try_ctx; | |
7609 } else { | |
7610 parsed_function()->reset_saved_try_ctx_vars(); | |
7611 } | |
7612 | |
7498 return try_catch_node; | 7613 return try_catch_node; |
7499 } | 7614 } |
7500 | 7615 |
7501 | 7616 |
7502 AstNode* Parser::ParseJump(String* label_name) { | 7617 AstNode* Parser::ParseJump(String* label_name) { |
7503 TRACE_PARSER("ParseJump"); | 7618 TRACE_PARSER("ParseJump"); |
7504 ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE); | 7619 ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE); |
7505 Token::Kind jump_kind = CurrentToken(); | 7620 Token::Kind jump_kind = CurrentToken(); |
7506 const intptr_t jump_pos = TokenPos(); | 7621 const intptr_t jump_pos = TokenPos(); |
7507 SourceLabel* target = NULL; | 7622 SourceLabel* target = NULL; |
(...skipping 3758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11266 void Parser::SkipQualIdent() { | 11381 void Parser::SkipQualIdent() { |
11267 ASSERT(IsIdentifier()); | 11382 ASSERT(IsIdentifier()); |
11268 ConsumeToken(); | 11383 ConsumeToken(); |
11269 if (CurrentToken() == Token::kPERIOD) { | 11384 if (CurrentToken() == Token::kPERIOD) { |
11270 ConsumeToken(); // Consume the kPERIOD token. | 11385 ConsumeToken(); // Consume the kPERIOD token. |
11271 ExpectIdentifier("identifier expected after '.'"); | 11386 ExpectIdentifier("identifier expected after '.'"); |
11272 } | 11387 } |
11273 } | 11388 } |
11274 | 11389 |
11275 } // namespace dart | 11390 } // namespace dart |
OLD | NEW |