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

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

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