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