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

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: rebase + added comment 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
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/await_future_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // 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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/await_future_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698