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 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 await_is_keyword_(false), | 289 await_is_keyword_(false), |
| 290 current_member_(NULL), | 290 current_member_(NULL), |
| 291 allow_function_literals_(true), | 291 allow_function_literals_(true), |
| 292 parsed_function_(NULL), | 292 parsed_function_(NULL), |
| 293 innermost_function_(Function::Handle(isolate_)), | 293 innermost_function_(Function::Handle(isolate_)), |
| 294 literal_token_(LiteralToken::Handle(isolate_)), | 294 literal_token_(LiteralToken::Handle(isolate_)), |
| 295 current_class_(Class::Handle(isolate_)), | 295 current_class_(Class::Handle(isolate_)), |
| 296 library_(Library::Handle(isolate_, library.raw())), | 296 library_(Library::Handle(isolate_, library.raw())), |
| 297 try_blocks_list_(NULL), | 297 try_blocks_list_(NULL), |
| 298 last_used_try_index_(0), | 298 last_used_try_index_(0), |
| 299 unregister_pending_function_(false) { | 299 unregister_pending_function_(false), |
| 300 async_temp_scope_(NULL) { | |
| 300 ASSERT(tokens_iterator_.IsValid()); | 301 ASSERT(tokens_iterator_.IsValid()); |
| 301 ASSERT(!library.IsNull()); | 302 ASSERT(!library.IsNull()); |
| 302 } | 303 } |
| 303 | 304 |
| 304 | 305 |
| 305 // For parsing a function. | 306 // For parsing a function. |
| 306 Parser::Parser(const Script& script, | 307 Parser::Parser(const Script& script, |
| 307 ParsedFunction* parsed_function, | 308 ParsedFunction* parsed_function, |
| 308 intptr_t token_position) | 309 intptr_t token_position) |
| 309 : isolate_(Isolate::Current()), | 310 : isolate_(Isolate::Current()), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 320 innermost_function_(Function::Handle(isolate_, | 321 innermost_function_(Function::Handle(isolate_, |
| 321 parsed_function->function().raw())), | 322 parsed_function->function().raw())), |
| 322 literal_token_(LiteralToken::Handle(isolate_)), | 323 literal_token_(LiteralToken::Handle(isolate_)), |
| 323 current_class_(Class::Handle(isolate_, | 324 current_class_(Class::Handle(isolate_, |
| 324 parsed_function->function().Owner())), | 325 parsed_function->function().Owner())), |
| 325 library_(Library::Handle(isolate_, Class::Handle( | 326 library_(Library::Handle(isolate_, Class::Handle( |
| 326 isolate_, | 327 isolate_, |
| 327 parsed_function->function().origin()).library())), | 328 parsed_function->function().origin()).library())), |
| 328 try_blocks_list_(NULL), | 329 try_blocks_list_(NULL), |
| 329 last_used_try_index_(0), | 330 last_used_try_index_(0), |
| 330 unregister_pending_function_(false) { | 331 unregister_pending_function_(false), |
| 332 async_temp_scope_(NULL) { | |
| 331 ASSERT(tokens_iterator_.IsValid()); | 333 ASSERT(tokens_iterator_.IsValid()); |
| 332 ASSERT(!current_function().IsNull()); | 334 ASSERT(!current_function().IsNull()); |
| 333 if (FLAG_enable_type_checks) { | 335 if (FLAG_enable_type_checks) { |
| 334 EnsureExpressionTemp(); | 336 EnsureExpressionTemp(); |
| 335 } | 337 } |
| 336 } | 338 } |
| 337 | 339 |
| 338 | 340 |
| 339 Parser::~Parser() { | 341 Parser::~Parser() { |
| 340 if (unregister_pending_function_) { | 342 if (unregister_pending_function_) { |
| (...skipping 2594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2935 Function::Handle(I, innermost_function().raw()); | 2937 Function::Handle(I, innermost_function().raw()); |
| 2936 innermost_function_ = func.raw(); | 2938 innermost_function_ = func.raw(); |
| 2937 | 2939 |
| 2938 // Save current try index. Try index starts at zero for each function. | 2940 // Save current try index. Try index starts at zero for each function. |
| 2939 intptr_t saved_try_index = last_used_try_index_; | 2941 intptr_t saved_try_index = last_used_try_index_; |
| 2940 last_used_try_index_ = 0; | 2942 last_used_try_index_ = 0; |
| 2941 | 2943 |
| 2942 intptr_t formal_params_pos = TokenPos(); | 2944 intptr_t formal_params_pos = TokenPos(); |
| 2943 // TODO(12455) : Need better validation mechanism. | 2945 // TODO(12455) : Need better validation mechanism. |
| 2944 | 2946 |
| 2947 LocalVariable* saved_saved_try_ctx = parsed_function()->saved_try_ctx(); | |
|
hausner
2014/09/02 20:04:47
We only have to save and restore these values if a
Michael Lippautz (Google)
2014/09/02 20:25:22
Yes, I added a comment.
| |
| 2948 const String& saved_async_saved_try_ctx_name = | |
| 2949 String::Handle(I, parsed_function()->async_saved_try_ctx_name()); | |
| 2950 parsed_function()->reset_saved_try_ctx_vars(); | |
| 2951 LocalScope* saved_async_temp_scope = async_temp_scope_; | |
| 2952 | |
| 2945 if (func.IsConstructor()) { | 2953 if (func.IsConstructor()) { |
| 2946 SequenceNode* statements = ParseConstructor(func, default_parameter_values); | 2954 SequenceNode* statements = ParseConstructor(func, default_parameter_values); |
| 2947 innermost_function_ = saved_innermost_function.raw(); | 2955 innermost_function_ = saved_innermost_function.raw(); |
| 2948 last_used_try_index_ = saved_try_index; | 2956 last_used_try_index_ = saved_try_index; |
| 2949 return statements; | 2957 return statements; |
| 2950 } | 2958 } |
| 2951 | 2959 |
| 2952 ASSERT(!func.IsConstructor()); | 2960 ASSERT(!func.IsConstructor()); |
| 2953 OpenFunctionBlock(func); // Build local scope for function. | 2961 OpenFunctionBlock(func); // Build local scope for function. |
| 2954 | 2962 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3044 } | 3052 } |
| 3045 | 3053 |
| 3046 RawFunction::AsyncModifier func_modifier = ParseFunctionModifier(); | 3054 RawFunction::AsyncModifier func_modifier = ParseFunctionModifier(); |
| 3047 func.set_modifier(func_modifier); | 3055 func.set_modifier(func_modifier); |
| 3048 | 3056 |
| 3049 OpenBlock(); // Open a nested scope for the outermost function block. | 3057 OpenBlock(); // Open a nested scope for the outermost function block. |
| 3050 | 3058 |
| 3051 Function& async_closure = Function::ZoneHandle(I); | 3059 Function& async_closure = Function::ZoneHandle(I); |
| 3052 if (func.IsAsyncFunction() && !func.is_async_closure()) { | 3060 if (func.IsAsyncFunction() && !func.is_async_closure()) { |
| 3053 async_closure = OpenAsyncFunction(formal_params_pos); | 3061 async_closure = OpenAsyncFunction(formal_params_pos); |
| 3062 async_temp_scope_ = current_block_->scope; | |
| 3054 } else if (func.is_async_closure()) { | 3063 } else if (func.is_async_closure()) { |
| 3055 OpenAsyncClosure(); | 3064 OpenAsyncClosure(); |
| 3065 async_temp_scope_ = current_block_->scope; | |
| 3056 } | 3066 } |
| 3057 | 3067 |
| 3058 bool saved_await_is_keyword = await_is_keyword_; | 3068 bool saved_await_is_keyword = await_is_keyword_; |
| 3059 if (func.IsAsyncFunction() || func.is_async_closure()) { | 3069 if (func.IsAsyncFunction() || func.is_async_closure()) { |
| 3060 await_is_keyword_ = true; | 3070 await_is_keyword_ = true; |
| 3061 } | 3071 } |
| 3062 | 3072 |
| 3063 intptr_t end_token_pos = 0; | 3073 intptr_t end_token_pos = 0; |
| 3064 if (CurrentToken() == Token::kLBRACE) { | 3074 if (CurrentToken() == Token::kLBRACE) { |
| 3065 ConsumeToken(); | 3075 ConsumeToken(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3122 SequenceNode* body = CloseBlock(); | 3132 SequenceNode* body = CloseBlock(); |
| 3123 if (func.IsAsyncFunction() && !func.is_async_closure()) { | 3133 if (func.IsAsyncFunction() && !func.is_async_closure()) { |
| 3124 body = CloseAsyncFunction(async_closure, body); | 3134 body = CloseAsyncFunction(async_closure, body); |
| 3125 } else if (func.is_async_closure()) { | 3135 } else if (func.is_async_closure()) { |
| 3126 CloseAsyncClosure(body); | 3136 CloseAsyncClosure(body); |
| 3127 } | 3137 } |
| 3128 current_block_->statements->Add(body); | 3138 current_block_->statements->Add(body); |
| 3129 innermost_function_ = saved_innermost_function.raw(); | 3139 innermost_function_ = saved_innermost_function.raw(); |
| 3130 last_used_try_index_ = saved_try_index; | 3140 last_used_try_index_ = saved_try_index; |
| 3131 await_is_keyword_ = saved_await_is_keyword; | 3141 await_is_keyword_ = saved_await_is_keyword; |
| 3142 async_temp_scope_ = saved_async_temp_scope; | |
| 3143 parsed_function()->set_saved_try_ctx(saved_saved_try_ctx); | |
| 3144 parsed_function()->set_async_saved_try_ctx_name( | |
| 3145 saved_async_saved_try_ctx_name); | |
| 3132 return CloseBlock(); | 3146 return CloseBlock(); |
| 3133 } | 3147 } |
| 3134 | 3148 |
| 3135 | 3149 |
| 3136 void Parser::AddEqualityNullCheck() { | 3150 void Parser::AddEqualityNullCheck() { |
| 3137 AstNode* argument = | 3151 AstNode* argument = |
| 3138 new LoadLocalNode(Scanner::kNoSourcePos, | 3152 new LoadLocalNode(Scanner::kNoSourcePos, |
| 3139 current_block_->scope->parent()->VariableAt(1)); | 3153 current_block_->scope->parent()->VariableAt(1)); |
| 3140 LiteralNode* null_operand = | 3154 LiteralNode* null_operand = |
| 3141 new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(I)); | 3155 new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(I)); |
| (...skipping 2379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5521 new(I) LocalScope(current_block_->scope, | 5535 new(I) LocalScope(current_block_->scope, |
| 5522 current_block_->scope->function_level() + 1, | 5536 current_block_->scope->function_level() + 1, |
| 5523 0); | 5537 0); |
| 5524 } | 5538 } |
| 5525 ChainNewBlock(outer_scope); | 5539 ChainNewBlock(outer_scope); |
| 5526 } | 5540 } |
| 5527 | 5541 |
| 5528 | 5542 |
| 5529 void Parser::OpenAsyncClosure() { | 5543 void Parser::OpenAsyncClosure() { |
| 5530 TRACE_PARSER("OpenAsyncClosure"); | 5544 TRACE_PARSER("OpenAsyncClosure"); |
| 5531 parsed_function()->set_await_temps_scope(current_block_->scope); | |
| 5532 } | 5545 } |
| 5533 | 5546 |
| 5534 | 5547 |
| 5535 RawFunction* Parser::OpenAsyncFunction(intptr_t formal_param_pos) { | 5548 RawFunction* Parser::OpenAsyncFunction(intptr_t formal_param_pos) { |
| 5536 TRACE_PARSER("OpenAsyncFunction"); | 5549 TRACE_PARSER("OpenAsyncFunction"); |
| 5550 | |
| 5551 AddAsyncClosureVariables(); | |
| 5552 | |
| 5537 // Create the closure containing the old body of this function. | 5553 // Create the closure containing the old body of this function. |
| 5538 Class& sig_cls = Class::ZoneHandle(I); | 5554 Class& sig_cls = Class::ZoneHandle(I); |
| 5539 Type& sig_type = Type::ZoneHandle(I); | 5555 Type& sig_type = Type::ZoneHandle(I); |
| 5540 Function& closure = Function::ZoneHandle(I); | 5556 Function& closure = Function::ZoneHandle(I); |
| 5541 String& sig = String::ZoneHandle(I); | 5557 String& sig = String::ZoneHandle(I); |
| 5542 ParamList closure_params; | 5558 ParamList closure_params; |
| 5543 closure_params.AddFinalParameter( | 5559 closure_params.AddFinalParameter( |
| 5544 formal_param_pos, | 5560 formal_param_pos, |
| 5545 &Symbols::ClosureParameter(), | 5561 &Symbols::ClosureParameter(), |
| 5546 &Type::ZoneHandle(I, Type::DynamicType())); | 5562 &Type::ZoneHandle(I, Type::DynamicType())); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 5572 } | 5588 } |
| 5573 ASSERT(AbstractType::Handle(I, closure.result_type()).IsResolved()); | 5589 ASSERT(AbstractType::Handle(I, closure.result_type()).IsResolved()); |
| 5574 ASSERT(closure.NumParameters() == closure_params.parameters->length()); | 5590 ASSERT(closure.NumParameters() == closure_params.parameters->length()); |
| 5575 OpenFunctionBlock(closure); | 5591 OpenFunctionBlock(closure); |
| 5576 AddFormalParamsToScope(&closure_params, current_block_->scope); | 5592 AddFormalParamsToScope(&closure_params, current_block_->scope); |
| 5577 OpenBlock(); | 5593 OpenBlock(); |
| 5578 return closure.raw(); | 5594 return closure.raw(); |
| 5579 } | 5595 } |
| 5580 | 5596 |
| 5581 | 5597 |
| 5598 void Parser::AddAsyncClosureVariables() { | |
| 5599 // Add to AST: | |
| 5600 // var :await_jump_var; | |
| 5601 // var :await_ctx_var; | |
| 5602 // var :async_op; | |
| 5603 // var :async_completer; | |
| 5604 const Type& dynamic_type = Type::ZoneHandle(I, Type::DynamicType()); | |
| 5605 LocalVariable* await_jump_var = new (I) LocalVariable( | |
| 5606 Scanner::kNoSourcePos, Symbols::AwaitJumpVar(), dynamic_type); | |
| 5607 current_block_->scope->AddVariable(await_jump_var); | |
| 5608 current_block_->scope->CaptureVariable(Symbols::AwaitJumpVar()); | |
| 5609 await_jump_var->set_is_captured(); | |
| 5610 LocalVariable* await_ctx_var = new (I) LocalVariable( | |
| 5611 Scanner::kNoSourcePos, Symbols::AwaitContextVar(), dynamic_type); | |
| 5612 current_block_->scope->AddVariable(await_ctx_var); | |
| 5613 current_block_->scope->CaptureVariable(Symbols::AwaitContextVar()); | |
| 5614 await_ctx_var->set_is_captured(); | |
| 5615 LocalVariable* async_op_var = new (I) LocalVariable( | |
| 5616 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type); | |
| 5617 current_block_->scope->AddVariable(async_op_var); | |
| 5618 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); | |
| 5619 async_op_var->set_is_captured(); | |
| 5620 LocalVariable* async_completer = new (I) LocalVariable( | |
| 5621 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); | |
| 5622 current_block_->scope->AddVariable(async_completer); | |
| 5623 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); | |
| 5624 async_completer->set_is_captured(); | |
| 5625 } | |
| 5626 | |
| 5627 | |
| 5582 SequenceNode* Parser::CloseBlock() { | 5628 SequenceNode* Parser::CloseBlock() { |
| 5583 SequenceNode* statements = current_block_->statements; | 5629 SequenceNode* statements = current_block_->statements; |
| 5584 if (current_block_->scope != NULL) { | 5630 if (current_block_->scope != NULL) { |
| 5585 // Record the begin and end token index of the scope. | 5631 // Record the begin and end token index of the scope. |
| 5586 ASSERT(statements != NULL); | 5632 ASSERT(statements != NULL); |
| 5587 current_block_->scope->set_begin_token_pos(statements->token_pos()); | 5633 current_block_->scope->set_begin_token_pos(statements->token_pos()); |
| 5588 current_block_->scope->set_end_token_pos(TokenPos()); | 5634 current_block_->scope->set_end_token_pos(TokenPos()); |
| 5589 } | 5635 } |
| 5590 current_block_ = current_block_->parent; | 5636 current_block_ = current_block_->parent; |
| 5591 return statements; | 5637 return statements; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 5604 | 5650 |
| 5605 SequenceNode* Parser::CloseAsyncFunction(const Function& closure, | 5651 SequenceNode* Parser::CloseAsyncFunction(const Function& closure, |
| 5606 SequenceNode* closure_body) { | 5652 SequenceNode* closure_body) { |
| 5607 TRACE_PARSER("CloseAsyncFunction"); | 5653 TRACE_PARSER("CloseAsyncFunction"); |
| 5608 ASSERT(!closure.IsNull()); | 5654 ASSERT(!closure.IsNull()); |
| 5609 ASSERT(closure_body != NULL); | 5655 ASSERT(closure_body != NULL); |
| 5610 // The block for the async closure body has already been closed. Close the | 5656 // The block for the async closure body has already been closed. Close the |
| 5611 // corresponding function block. | 5657 // corresponding function block. |
| 5612 CloseBlock(); | 5658 CloseBlock(); |
| 5613 | 5659 |
| 5660 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | |
| 5661 closure_body->scope()->CaptureVariable(Symbols::AsyncCompleter()); | |
| 5662 | |
| 5614 // Create and return a new future that executes a closure with the current | 5663 // Create and return a new future that executes a closure with the current |
| 5615 // body. | 5664 // body. |
| 5616 | 5665 |
| 5617 // No need to capture parameters or other variables, since they have already | 5666 // No need to capture parameters or other variables, since they have already |
| 5618 // been captured in the corresponding scope as the body has been parsed within | 5667 // been captured in the corresponding scope as the body has been parsed within |
| 5619 // a nested block (contained in the async funtion's block). | 5668 // a nested block (contained in the async funtion's block). |
| 5620 const Class& future = Class::ZoneHandle(I, | 5669 const Class& future = Class::ZoneHandle(I, |
| 5621 GetClassForAsync(Symbols::Future())); | 5670 GetClassForAsync(Symbols::Future())); |
| 5622 ASSERT(!future.IsNull()); | 5671 ASSERT(!future.IsNull()); |
| 5623 const Function& constructor = Function::ZoneHandle(I, | 5672 const Function& constructor = Function::ZoneHandle(I, |
| 5624 future.LookupFunction(Symbols::FutureConstructor())); | 5673 future.LookupFunction(Symbols::FutureConstructor())); |
| 5625 ASSERT(!constructor.IsNull()); | 5674 ASSERT(!constructor.IsNull()); |
| 5626 const Class& completer = Class::ZoneHandle(I, | 5675 const Class& completer = Class::ZoneHandle(I, |
| 5627 GetClassForAsync(Symbols::Completer())); | 5676 GetClassForAsync(Symbols::Completer())); |
| 5628 ASSERT(!completer.IsNull()); | 5677 ASSERT(!completer.IsNull()); |
| 5629 const Function& completer_constructor = Function::ZoneHandle(I, | 5678 const Function& completer_constructor = Function::ZoneHandle(I, |
| 5630 completer.LookupFunction(Symbols::CompleterConstructor())); | 5679 completer.LookupFunction(Symbols::CompleterConstructor())); |
| 5631 ASSERT(!completer_constructor.IsNull()); | 5680 ASSERT(!completer_constructor.IsNull()); |
| 5632 | 5681 |
| 5633 bool found = false; | 5682 LocalVariable* async_completer = current_block_->scope->LookupVariable( |
| 5634 // Add to AST: | 5683 Symbols::AsyncCompleter(), false); |
| 5635 // var :async_op; | |
| 5636 // var :async_completer; | |
| 5637 // var :await_jump_var; | |
| 5638 // var :await_ctx_var; | |
| 5639 // Add as many variables to saved the try block ctx as there were try blocks. | |
| 5640 // var :async_saved_try_ctx_var_<x>; | |
| 5641 const Type& dynamic_type = Type::ZoneHandle(I, Type::DynamicType()); | |
| 5642 LocalVariable* async_op_var = new (I) LocalVariable( | |
| 5643 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type); | |
| 5644 current_block_->scope->AddVariable(async_op_var); | |
| 5645 found = closure_body->scope()->CaptureVariable(Symbols::AsyncOperation()); | |
| 5646 ASSERT(found); | |
| 5647 LocalVariable* async_completer = new (I) LocalVariable( | |
| 5648 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); | |
| 5649 current_block_->scope->AddVariable(async_completer); | |
| 5650 found = closure_body->scope()->CaptureVariable(Symbols::AsyncCompleter()); | |
| 5651 ASSERT(found); | |
| 5652 LocalVariable* await_jump_var = new (I) LocalVariable( | |
| 5653 Scanner::kNoSourcePos, Symbols::AwaitJumpVar(), dynamic_type); | |
| 5654 current_block_->scope->AddVariable(await_jump_var); | |
| 5655 found = closure_body->scope()->CaptureVariable(Symbols::AwaitJumpVar()); | |
| 5656 ASSERT(found); | |
| 5657 LocalVariable* await_ctx_var = new (I) LocalVariable( | |
| 5658 Scanner::kNoSourcePos, Symbols::AwaitContextVar(), dynamic_type); | |
| 5659 current_block_->scope->AddVariable(await_ctx_var); | |
| 5660 found = closure_body->scope()->CaptureVariable(Symbols::AwaitContextVar()); | |
| 5661 ASSERT(found); | |
| 5662 LocalVariable* async_saved_try_ctx_var; | |
| 5663 for (int16_t i = 0; i < last_used_try_index_; i++) { | |
| 5664 String& async_saved_try_ctx_name = BuildAsyncSavedTryContextName(I, i); | |
| 5665 async_saved_try_ctx_var = new (I) LocalVariable( | |
| 5666 Scanner::kNoSourcePos, async_saved_try_ctx_name, dynamic_type); | |
| 5667 current_block_->scope->AddVariable(async_saved_try_ctx_var); | |
| 5668 found = closure_body->scope()->CaptureVariable(async_saved_try_ctx_name); | |
| 5669 ASSERT(found); | |
| 5670 } | |
| 5671 | 5684 |
| 5672 // Add to AST: | 5685 // Add to AST: |
| 5673 // :async_completer = new Completer(); | 5686 // :async_completer = new Completer(); |
| 5674 ArgumentListNode* empty_args = | 5687 ArgumentListNode* empty_args = |
| 5675 new (I) ArgumentListNode(Scanner::kNoSourcePos); | 5688 new (I) ArgumentListNode(Scanner::kNoSourcePos); |
| 5676 ConstructorCallNode* completer_constructor_node = new (I) ConstructorCallNode( | 5689 ConstructorCallNode* completer_constructor_node = new (I) ConstructorCallNode( |
| 5677 Scanner::kNoSourcePos, | 5690 Scanner::kNoSourcePos, |
| 5678 TypeArguments::ZoneHandle(I), | 5691 TypeArguments::ZoneHandle(I), |
| 5679 completer_constructor, | 5692 completer_constructor, |
| 5680 empty_args); | 5693 empty_args); |
| 5681 StoreLocalNode* store_completer = new (I) StoreLocalNode( | 5694 StoreLocalNode* store_completer = new (I) StoreLocalNode( |
| 5682 Scanner::kNoSourcePos, | 5695 Scanner::kNoSourcePos, |
| 5683 async_completer, | 5696 async_completer, |
| 5684 completer_constructor_node); | 5697 completer_constructor_node); |
| 5685 current_block_->statements->Add(store_completer); | 5698 current_block_->statements->Add(store_completer); |
| 5686 | 5699 |
| 5687 // Add to AST: | 5700 // Add to AST: |
| 5688 // :async_op = <closure>; (containing the original body) | 5701 // :async_op = <closure>; (containing the original body) |
| 5702 LocalVariable* async_op_var = current_block_->scope->LookupVariable( | |
| 5703 Symbols::AsyncOperation(), false); | |
| 5689 ClosureNode* cn = new(I) ClosureNode( | 5704 ClosureNode* cn = new(I) ClosureNode( |
| 5690 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); | 5705 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); |
| 5691 StoreLocalNode* store_async_op = new (I) StoreLocalNode( | 5706 StoreLocalNode* store_async_op = new (I) StoreLocalNode( |
| 5692 Scanner::kNoSourcePos, | 5707 Scanner::kNoSourcePos, |
| 5693 async_op_var, | 5708 async_op_var, |
| 5694 cn); | 5709 cn); |
| 5695 current_block_->statements->Add(store_async_op); | 5710 current_block_->statements->Add(store_async_op); |
| 5696 | 5711 |
| 5697 // Add to AST: | 5712 // Add to AST: |
| 5698 // new Future(:async_op); | 5713 // new Future(:async_op); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 5719 } | 5734 } |
| 5720 | 5735 |
| 5721 | 5736 |
| 5722 void Parser::CloseAsyncClosure(SequenceNode* body) { | 5737 void Parser::CloseAsyncClosure(SequenceNode* body) { |
| 5723 TRACE_PARSER("CloseAsyncClosure"); | 5738 TRACE_PARSER("CloseAsyncClosure"); |
| 5724 // We need a temporary expression to store intermediate return values. | 5739 // We need a temporary expression to store intermediate return values. |
| 5725 parsed_function()->EnsureExpressionTemp(); | 5740 parsed_function()->EnsureExpressionTemp(); |
| 5726 // Implicitly mark those variables below as captured. We currently mark all | 5741 // Implicitly mark those variables below as captured. We currently mark all |
| 5727 // variables of all scopes as captured (below), but as soon as we do something | 5742 // variables of all scopes as captured (below), but as soon as we do something |
| 5728 // smarter we rely on these internal variables to be available. | 5743 // smarter we rely on these internal variables to be available. |
| 5729 body->scope()->LookupVariable(Symbols::Completer(), false); | |
| 5730 body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | 5744 body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 5731 body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); | 5745 body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
| 5746 body->scope()->LookupVariable(Symbols::AsyncCompleter(), false); | |
| 5732 body->scope()->RecursivelyCaptureAllVariables(); | 5747 body->scope()->RecursivelyCaptureAllVariables(); |
| 5733 } | 5748 } |
| 5734 | 5749 |
| 5735 | 5750 |
| 5736 // Set up default values for all optional parameters to the function. | 5751 // Set up default values for all optional parameters to the function. |
| 5737 void Parser::SetupDefaultsForOptionalParams(const ParamList* params, | 5752 void Parser::SetupDefaultsForOptionalParams(const ParamList* params, |
| 5738 Array* default_values) { | 5753 Array* default_values) { |
| 5739 if (params->num_optional_parameters > 0) { | 5754 if (params->num_optional_parameters > 0) { |
| 5740 // Build array of default parameter values. | 5755 // Build array of default parameter values. |
| 5741 ParamDesc* param = | 5756 ParamDesc* param = |
| (...skipping 1519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7261 | 7276 |
| 7262 | 7277 |
| 7263 SequenceNode* Parser::ParseFinallyBlock() { | 7278 SequenceNode* Parser::ParseFinallyBlock() { |
| 7264 TRACE_PARSER("ParseFinallyBlock"); | 7279 TRACE_PARSER("ParseFinallyBlock"); |
| 7265 OpenBlock(); | 7280 OpenBlock(); |
| 7266 ExpectToken(Token::kLBRACE); | 7281 ExpectToken(Token::kLBRACE); |
| 7267 | 7282 |
| 7268 // In case of async closures we need to restore the saved try index of an | 7283 // In case of async closures we need to restore the saved try index of an |
| 7269 // outer try block (if it exists). The current try block has already been | 7284 // outer try block (if it exists). The current try block has already been |
| 7270 // removed from the stack of try blocks. | 7285 // removed from the stack of try blocks. |
| 7271 if (current_function().is_async_closure() && (try_blocks_list_ != NULL)) { | 7286 if ((innermost_function().is_async_closure() || |
| 7287 innermost_function().IsAsyncFunction()) && | |
| 7288 (try_blocks_list_ != NULL)) { | |
| 7272 // We need two unchain two scopes: finally clause, and the try block level. | 7289 // We need two unchain two scopes: finally clause, and the try block level. |
| 7273 SetupSavedTryContext(current_block_->scope->parent()->parent(), | 7290 RestoreSavedTryContext(current_block_->scope->parent()->parent(), |
| 7274 try_blocks_list_->try_index(), | 7291 try_blocks_list_->try_index(), |
| 7275 current_block_->statements); | 7292 current_block_->statements); |
| 7276 } else { | 7293 } else { |
| 7277 parsed_function()->reset_saved_try_ctx_vars(); | 7294 parsed_function()->reset_saved_try_ctx_vars(); |
| 7278 } | 7295 } |
| 7279 | 7296 |
| 7280 ParseStatementSequence(); | 7297 ParseStatementSequence(); |
| 7281 ExpectToken(Token::kRBRACE); | 7298 ExpectToken(Token::kRBRACE); |
| 7282 SequenceNode* finally_block = CloseBlock(); | 7299 SequenceNode* finally_block = CloseBlock(); |
| 7283 return finally_block; | 7300 return finally_block; |
| 7284 } | 7301 } |
| 7285 | 7302 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7419 no_args)); | 7436 no_args)); |
| 7420 } | 7437 } |
| 7421 | 7438 |
| 7422 // Add nested block with user-defined code. This blocks allows | 7439 // Add nested block with user-defined code. This blocks allows |
| 7423 // declarations in the body to shadow the catch parameters. | 7440 // declarations in the body to shadow the catch parameters. |
| 7424 CheckToken(Token::kLBRACE); | 7441 CheckToken(Token::kLBRACE); |
| 7425 | 7442 |
| 7426 // In case of async closures we need to restore the saved try index of an | 7443 // In case of async closures we need to restore the saved try index of an |
| 7427 // outer try block (if it exists). | 7444 // outer try block (if it exists). |
| 7428 ASSERT(try_blocks_list_ != NULL); | 7445 ASSERT(try_blocks_list_ != NULL); |
| 7429 if (current_function().is_async_closure() && | 7446 if (innermost_function().is_async_closure() || |
| 7430 (try_blocks_list_->outer_try_block() != NULL)) { | 7447 innermost_function().IsAsyncFunction()) { |
| 7431 // We need to unchain three scope levels: catch clause, catch parameters, | 7448 if ((try_blocks_list_->outer_try_block() != NULL) && |
| 7432 // and the general try block. | 7449 (try_blocks_list_->outer_try_block()->try_block() |
| 7433 SetupSavedTryContext(current_block_->scope->parent()->parent()->parent(), | 7450 ->scope->function_level() == |
| 7434 try_blocks_list_->outer_try_block()->try_index(), | 7451 current_block_->scope->function_level())) { |
| 7435 current_block_->statements); | 7452 // We need to unchain three scope levels: catch clause, catch |
| 7436 } else { | 7453 // parameters, and the general try block. |
| 7437 parsed_function()->reset_saved_try_ctx_vars(); | 7454 RestoreSavedTryContext( |
| 7455 current_block_->scope->parent()->parent()->parent(), | |
| 7456 try_blocks_list_->outer_try_block()->try_index(), | |
| 7457 current_block_->statements); | |
| 7458 } else { | |
| 7459 parsed_function()->reset_saved_try_ctx_vars(); | |
| 7460 } | |
| 7438 } | 7461 } |
| 7439 | 7462 |
| 7440 current_block_->statements->Add(ParseNestedStatement(false, NULL)); | 7463 current_block_->statements->Add(ParseNestedStatement(false, NULL)); |
| 7441 catch_blocks.Add(CloseBlock()); | 7464 catch_blocks.Add(CloseBlock()); |
| 7442 | 7465 |
| 7443 const bool is_bad_type = | 7466 const bool is_bad_type = |
| 7444 exception_param.type->IsMalformed() || | 7467 exception_param.type->IsMalformed() || |
| 7445 exception_param.type->IsMalbounded(); | 7468 exception_param.type->IsMalbounded(); |
| 7446 if (exception_param.type->IsDynamicType() || is_bad_type) { | 7469 if (exception_param.type->IsDynamicType() || is_bad_type) { |
| 7447 // There is no exception type or else it is malformed or malbounded. | 7470 // There is no exception type or else it is malformed or malbounded. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7525 AstNode* type_test = type_tests.RemoveLast(); | 7548 AstNode* type_test = type_tests.RemoveLast(); |
| 7526 SequenceNode* catch_block = catch_blocks.RemoveLast(); | 7549 SequenceNode* catch_block = catch_blocks.RemoveLast(); |
| 7527 current_block_->statements->Add(new(I) IfNode( | 7550 current_block_->statements->Add(new(I) IfNode( |
| 7528 type_test->token_pos(), type_test, catch_block, current)); | 7551 type_test->token_pos(), type_test, catch_block, current)); |
| 7529 current = CloseBlock(); | 7552 current = CloseBlock(); |
| 7530 } | 7553 } |
| 7531 return current; | 7554 return current; |
| 7532 } | 7555 } |
| 7533 | 7556 |
| 7534 | 7557 |
| 7558 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) { | |
| 7559 const String& async_saved_try_ctx_name = | |
| 7560 BuildAsyncSavedTryContextName(I, last_used_try_index_ - 1); | |
| 7561 LocalVariable* async_saved_try_ctx = new (I) LocalVariable( | |
| 7562 Scanner::kNoSourcePos, | |
| 7563 async_saved_try_ctx_name, | |
| 7564 Type::ZoneHandle(I, Type::DynamicType())); | |
| 7565 async_temp_scope_->AddVariable(async_saved_try_ctx); | |
| 7566 async_saved_try_ctx->set_is_captured(); | |
| 7567 async_saved_try_ctx = current_block_->scope->LookupVariable( | |
| 7568 async_saved_try_ctx_name, false); | |
| 7569 ASSERT(async_saved_try_ctx != NULL); | |
| 7570 ASSERT(saved_try_context != NULL); | |
| 7571 current_block_->statements->Add(new (I) StoreLocalNode( | |
| 7572 Scanner::kNoSourcePos, async_saved_try_ctx, new (I) LoadLocalNode( | |
| 7573 Scanner::kNoSourcePos, saved_try_context))); | |
| 7574 parsed_function()->set_saved_try_ctx(saved_try_context); | |
| 7575 parsed_function()->set_async_saved_try_ctx_name(async_saved_try_ctx_name); | |
| 7576 } | |
| 7577 | |
| 7578 | |
| 7535 // Set up the currently relevant :saved_try_context_var on the stack: | 7579 // Set up the currently relevant :saved_try_context_var on the stack: |
| 7536 // * Try blocks: Set the context variable for this try block. | 7580 // * Try blocks: Set the context variable for this try block. |
| 7537 // * Catch/finally blocks: Set the context variable for any outer try block (if | 7581 // * Catch/finally blocks: Set the context variable for any outer try block (if |
| 7538 // existent). | 7582 // existent). |
| 7539 // | 7583 // |
| 7540 // Also save the captured variable and the stack variable to be able to set | 7584 // Also save the captured variable and the stack variable to be able to set |
| 7541 // it after a function continues execution (await). | 7585 // it after a function continues execution (await). |
| 7542 void Parser::SetupSavedTryContext(LocalScope* saved_try_context_scope, | 7586 void Parser::RestoreSavedTryContext(LocalScope* saved_try_context_scope, |
| 7543 int16_t try_index, | 7587 int16_t try_index, |
| 7544 SequenceNode* target) { | 7588 SequenceNode* target) { |
| 7545 LocalVariable* saved_try_ctx = saved_try_context_scope->LookupVariable( | 7589 LocalVariable* saved_try_ctx = saved_try_context_scope->LookupVariable( |
| 7546 Symbols::SavedTryContextVar(), false); | 7590 Symbols::SavedTryContextVar(), false); |
| 7547 ASSERT((saved_try_ctx != NULL) && !saved_try_ctx->is_captured()); | 7591 ASSERT((saved_try_ctx != NULL) && !saved_try_ctx->is_captured()); |
| 7548 const String& async_saved_try_ctx_name = | 7592 const String& async_saved_try_ctx_name = |
| 7549 BuildAsyncSavedTryContextName(I, try_index); | 7593 BuildAsyncSavedTryContextName(I, try_index); |
| 7550 LocalVariable* async_saved_try_ctx = | 7594 LocalVariable* async_saved_try_ctx = |
| 7551 target->scope()->LookupVariable(async_saved_try_ctx_name, false); | 7595 target->scope()->LookupVariable(async_saved_try_ctx_name, false); |
| 7552 ASSERT((async_saved_try_ctx != NULL) && async_saved_try_ctx->is_captured()); | 7596 ASSERT(async_saved_try_ctx != NULL); |
| 7597 ASSERT(async_saved_try_ctx->is_captured()); | |
| 7553 target->Add(new (I) StoreLocalNode( | 7598 target->Add(new (I) StoreLocalNode( |
| 7554 Scanner::kNoSourcePos, saved_try_ctx, new (I) LoadLocalNode( | 7599 Scanner::kNoSourcePos, |
| 7555 Scanner::kNoSourcePos, async_saved_try_ctx))); | 7600 saved_try_ctx, |
| 7601 new (I) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx))); | |
| 7556 | 7602 |
| 7557 parsed_function()->set_saved_try_ctx(saved_try_ctx); | 7603 parsed_function()->set_saved_try_ctx(saved_try_ctx); |
| 7558 parsed_function()->set_async_saved_try_ctx(async_saved_try_ctx); | 7604 parsed_function()->set_async_saved_try_ctx_name(async_saved_try_ctx_name); |
| 7559 } | 7605 } |
| 7560 | 7606 |
| 7561 | 7607 |
| 7562 AstNode* Parser::ParseTryStatement(String* label_name) { | 7608 AstNode* Parser::ParseTryStatement(String* label_name) { |
| 7563 TRACE_PARSER("ParseTryStatement"); | 7609 TRACE_PARSER("ParseTryStatement"); |
| 7564 | 7610 |
| 7565 // We create three variables for exceptions here: | 7611 // We create three variables for exceptions here: |
| 7566 // ':saved_try_context_var' - Used to save the context before the start of | 7612 // ':saved_try_context_var' - Used to save the context before the start of |
| 7567 // the try block. The context register is | 7613 // the try block. The context register is |
| 7568 // restored from this variable before | 7614 // restored from this variable before |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7611 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); | 7657 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); |
| 7612 OpenBlock(); | 7658 OpenBlock(); |
| 7613 current_block_->scope->AddLabel(try_label); | 7659 current_block_->scope->AddLabel(try_label); |
| 7614 } | 7660 } |
| 7615 | 7661 |
| 7616 // Now parse the 'try' block. | 7662 // Now parse the 'try' block. |
| 7617 OpenBlock(); | 7663 OpenBlock(); |
| 7618 PushTryBlock(current_block_); | 7664 PushTryBlock(current_block_); |
| 7619 ExpectToken(Token::kLBRACE); | 7665 ExpectToken(Token::kLBRACE); |
| 7620 | 7666 |
| 7621 if (current_function().is_async_closure()) { | 7667 if (innermost_function().is_async_closure() || |
| 7622 const String& async_saved_try_ctx_name = | 7668 innermost_function().IsAsyncFunction()) { |
| 7623 BuildAsyncSavedTryContextName(I, last_used_try_index_ - 1); | 7669 SetupSavedTryContext(context_var); |
| 7624 LocalVariable* async_saved_try_ctx = | |
| 7625 current_block_->scope->LookupVariable( | |
| 7626 async_saved_try_ctx_name, false); | |
| 7627 ASSERT(async_saved_try_ctx != NULL); | |
| 7628 ASSERT(context_var != NULL); | |
| 7629 current_block_->statements->Add(new (I) StoreLocalNode( | |
| 7630 Scanner::kNoSourcePos, async_saved_try_ctx, new (I) LoadLocalNode( | |
| 7631 Scanner::kNoSourcePos, context_var))); | |
| 7632 parsed_function()->set_saved_try_ctx(context_var); | |
| 7633 parsed_function()->set_async_saved_try_ctx(async_saved_try_ctx); | |
| 7634 } | 7670 } |
| 7635 | 7671 |
| 7636 ParseStatementSequence(); | 7672 ParseStatementSequence(); |
| 7637 ExpectToken(Token::kRBRACE); | 7673 ExpectToken(Token::kRBRACE); |
| 7638 SequenceNode* try_block = CloseBlock(); | 7674 SequenceNode* try_block = CloseBlock(); |
| 7639 | 7675 |
| 7640 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 7676 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
| 7641 (CurrentToken() != Token::kFINALLY)) { | 7677 (CurrentToken() != Token::kFINALLY)) { |
| 7642 ReportError("catch or finally clause expected"); | 7678 ReportError("catch or finally clause expected"); |
| 7643 } | 7679 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7699 AstNode* try_catch_node = new(I) TryCatchNode( | 7735 AstNode* try_catch_node = new(I) TryCatchNode( |
| 7700 try_pos, try_block, context_var, catch_clause, finally_block, try_index); | 7736 try_pos, try_block, context_var, catch_clause, finally_block, try_index); |
| 7701 | 7737 |
| 7702 if (try_label != NULL) { | 7738 if (try_label != NULL) { |
| 7703 current_block_->statements->Add(try_catch_node); | 7739 current_block_->statements->Add(try_catch_node); |
| 7704 SequenceNode* sequence = CloseBlock(); | 7740 SequenceNode* sequence = CloseBlock(); |
| 7705 sequence->set_label(try_label); | 7741 sequence->set_label(try_label); |
| 7706 try_catch_node = sequence; | 7742 try_catch_node = sequence; |
| 7707 } | 7743 } |
| 7708 | 7744 |
| 7709 // In case of async closures we need to restore the saved try index of an | |
| 7710 // outer try block (if it exists). | |
| 7711 if (current_function().is_async_closure() && | |
| 7712 (outer_try_index != CatchClauseNode::kInvalidTryIndex)) { | |
| 7713 SequenceNode* try_catch_and_restore_try_ctx = new (I) SequenceNode( | |
| 7714 Scanner::kNoSourcePos, current_block_->scope); | |
| 7715 try_catch_and_restore_try_ctx->Add(try_catch_node); | |
| 7716 SetupSavedTryContext( | |
| 7717 current_block_->scope, outer_try_index, try_catch_and_restore_try_ctx); | |
| 7718 return try_catch_and_restore_try_ctx; | |
| 7719 } else { | |
| 7720 parsed_function()->reset_saved_try_ctx_vars(); | |
| 7721 } | |
| 7722 | |
| 7723 return try_catch_node; | 7745 return try_catch_node; |
| 7724 } | 7746 } |
| 7725 | 7747 |
| 7726 | 7748 |
| 7727 AstNode* Parser::ParseJump(String* label_name) { | 7749 AstNode* Parser::ParseJump(String* label_name) { |
| 7728 TRACE_PARSER("ParseJump"); | 7750 TRACE_PARSER("ParseJump"); |
| 7729 ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE); | 7751 ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE); |
| 7730 Token::Kind jump_kind = CurrentToken(); | 7752 Token::Kind jump_kind = CurrentToken(); |
| 7731 const intptr_t jump_pos = TokenPos(); | 7753 const intptr_t jump_pos = TokenPos(); |
| 7732 SourceLabel* target = NULL; | 7754 SourceLabel* target = NULL; |
| (...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8550 return expr; | 8572 return expr; |
| 8551 } | 8573 } |
| 8552 | 8574 |
| 8553 | 8575 |
| 8554 AstNode* Parser::ParseAwaitableExpr(bool require_compiletime_const, | 8576 AstNode* Parser::ParseAwaitableExpr(bool require_compiletime_const, |
| 8555 bool consume_cascades) { | 8577 bool consume_cascades) { |
| 8556 TRACE_PARSER("ParseAwaitableExpr"); | 8578 TRACE_PARSER("ParseAwaitableExpr"); |
| 8557 parsed_function()->reset_have_seen_await(); | 8579 parsed_function()->reset_have_seen_await(); |
| 8558 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); | 8580 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); |
| 8559 if (parsed_function()->have_seen_await()) { | 8581 if (parsed_function()->have_seen_await()) { |
| 8560 if (!current_block_->scope->LookupVariable( | 8582 // Make sure we do not reuse the scope to avoid creating contexts that we |
| 8561 Symbols::AsyncOperation(), true)) { | 8583 // are unaware of, i.e, creating contexts that have already been covered. |
| 8562 // Async operations are always encapsulated into a local function. We only | 8584 // See FlowGraphBuilder::VisitSequenceNode() for details on when contexts |
| 8563 // need to transform the expression when generating code for this inner | 8585 // are created. |
| 8564 // function. | 8586 OpenBlock(); |
| 8565 return expr; | 8587 AwaitTransformer at(current_block_->statements, |
| 8566 } | 8588 library_, |
| 8567 SequenceNode* intermediates_block = new(I) SequenceNode( | 8589 parsed_function(), |
| 8568 Scanner::kNoSourcePos, current_block_->scope); | 8590 async_temp_scope_); |
| 8569 AwaitTransformer at(intermediates_block, library_, parsed_function()); | |
| 8570 AstNode* result = at.Transform(expr); | 8591 AstNode* result = at.Transform(expr); |
| 8571 current_block_->statements->Add(intermediates_block); | 8592 current_block_->statements->Add(CloseBlock()); |
| 8572 parsed_function()->reset_have_seen_await(); | 8593 parsed_function()->reset_have_seen_await(); |
| 8573 return result; | 8594 return result; |
| 8574 } | 8595 } |
| 8575 return expr; | 8596 return expr; |
| 8576 } | 8597 } |
| 8577 | 8598 |
| 8578 | 8599 |
| 8579 AstNode* Parser::ParseExpr(bool require_compiletime_const, | 8600 AstNode* Parser::ParseExpr(bool require_compiletime_const, |
| 8580 bool consume_cascades) { | 8601 bool consume_cascades) { |
| 8581 TRACE_PARSER("ParseExpr"); | 8602 TRACE_PARSER("ParseExpr"); |
| (...skipping 2913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11495 void Parser::SkipQualIdent() { | 11516 void Parser::SkipQualIdent() { |
| 11496 ASSERT(IsIdentifier()); | 11517 ASSERT(IsIdentifier()); |
| 11497 ConsumeToken(); | 11518 ConsumeToken(); |
| 11498 if (CurrentToken() == Token::kPERIOD) { | 11519 if (CurrentToken() == Token::kPERIOD) { |
| 11499 ConsumeToken(); // Consume the kPERIOD token. | 11520 ConsumeToken(); // Consume the kPERIOD token. |
| 11500 ExpectIdentifier("identifier expected after '.'"); | 11521 ExpectIdentifier("identifier expected after '.'"); |
| 11501 } | 11522 } |
| 11502 } | 11523 } |
| 11503 | 11524 |
| 11504 } // namespace dart | 11525 } // namespace dart |
| OLD | NEW |