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