Chromium Code Reviews| 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 |