Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: runtime/vm/parser.cc

Issue 520223002: Fix scoping async functions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698