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