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 |