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

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

Issue 914303006: Fix yield statements in catch blocks (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 10 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 | « no previous file | tests/language/language.status » ('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 3153 matching lines...) Expand 10 before | Expand all | Expand 10 after
3164 // The closure containing the body of an async function is debuggable. 3164 // The closure containing the body of an async function is debuggable.
3165 ASSERT(func.is_debuggable()); 3165 ASSERT(func.is_debuggable());
3166 OpenAsyncClosure(); 3166 OpenAsyncClosure();
3167 } else if (func.IsSyncGenerator()) { 3167 } else if (func.IsSyncGenerator()) {
3168 // The code of a sync generator is synthesized. Disable debugging. 3168 // The code of a sync generator is synthesized. Disable debugging.
3169 func.set_is_debuggable(false); 3169 func.set_is_debuggable(false);
3170 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos()); 3170 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos());
3171 } else if (func.IsSyncGenClosure()) { 3171 } else if (func.IsSyncGenClosure()) {
3172 // The closure containing the body of a sync generator is debuggable. 3172 // The closure containing the body of a sync generator is debuggable.
3173 ASSERT(func.is_debuggable()); 3173 ASSERT(func.is_debuggable());
3174 // Nothing special to do. 3174 async_temp_scope_ = current_block_->scope;
3175 } 3175 }
3176 3176
3177 BoolScope allow_await(&this->await_is_keyword_, 3177 BoolScope allow_await(&this->await_is_keyword_,
3178 func.IsAsyncOrGenerator() || func.is_generated_body()); 3178 func.IsAsyncOrGenerator() || func.is_generated_body());
3179 intptr_t end_token_pos = 0; 3179 intptr_t end_token_pos = 0;
3180 if (CurrentToken() == Token::kLBRACE) { 3180 if (CurrentToken() == Token::kLBRACE) {
3181 ConsumeToken(); 3181 ConsumeToken();
3182 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { 3182 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) {
3183 const Class& owner = Class::Handle(Z, func.Owner()); 3183 const Class& owner = Class::Handle(Z, func.Owner());
3184 if (!owner.IsObjectClass()) { 3184 if (!owner.IsObjectClass()) {
(...skipping 2783 matching lines...) Expand 10 before | Expand all | Expand 10 after
5968 stack_trace_param.var, 5968 stack_trace_param.var,
5969 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); 5969 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
5970 current_block_->statements->Add(new(Z) InstanceCallNode( 5970 current_block_->statements->Add(new(Z) InstanceCallNode(
5971 Scanner::kNoSourcePos, 5971 Scanner::kNoSourcePos,
5972 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var), 5972 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var),
5973 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()), 5973 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()),
5974 no_args)); 5974 no_args));
5975 } 5975 }
5976 5976
5977 ASSERT(try_blocks_list_ != NULL); 5977 ASSERT(try_blocks_list_ != NULL);
5978 ASSERT(innermost_function().IsAsyncClosure() ||
5979 innermost_function().IsAsyncFunction());
5978 if (innermost_function().IsAsyncClosure() || 5980 if (innermost_function().IsAsyncClosure() ||
5979 innermost_function().IsAsyncFunction()) { 5981 innermost_function().IsAsyncFunction()) {
5982 // This should always be true here.
regis 2015/02/11 23:53:44 Add a TODO if you want to revisit this code. Other
hausner 2015/02/12 00:18:50 Removed the if. The assertion never fired in our t
5980 if ((try_blocks_list_->outer_try_block() != NULL) && 5983 if ((try_blocks_list_->outer_try_block() != NULL) &&
5981 (try_blocks_list_->outer_try_block()->try_block() 5984 (try_blocks_list_->outer_try_block()->try_block()
5982 ->scope->function_level() == 5985 ->scope->function_level() ==
5983 current_block_->scope->function_level())) { 5986 current_block_->scope->function_level())) {
5984 // We need to unchain three scope levels: catch clause, catch 5987 // We need to unchain three scope levels: catch clause, catch
5985 // parameters, and the general try block. 5988 // parameters, and the general try block.
5986 RestoreSavedTryContext( 5989 RestoreSavedTryContext(
5987 current_block_->scope->parent()->parent()->parent(), 5990 current_block_->scope->parent()->parent()->parent(),
5988 try_blocks_list_->outer_try_block()->try_index(), 5991 try_blocks_list_->outer_try_block()->try_index(),
5989 current_block_->statements); 5992 current_block_->statements);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
6074 Symbols::StackTraceVar(), 6077 Symbols::StackTraceVar(),
6075 Type::ZoneHandle(Z, Type::DynamicType())); 6078 Type::ZoneHandle(Z, Type::DynamicType()));
6076 current_block_->scope->AddVariable(stack_trace_var); 6079 current_block_->scope->AddVariable(stack_trace_var);
6077 } 6080 }
6078 6081
6079 // Open the try block. 6082 // Open the try block.
6080 OpenBlock(); 6083 OpenBlock();
6081 PushTryBlock(current_block_); 6084 PushTryBlock(current_block_);
6082 6085
6083 if (innermost_function().IsAsyncClosure() || 6086 if (innermost_function().IsAsyncClosure() ||
6084 innermost_function().IsAsyncFunction()) { 6087 innermost_function().IsAsyncFunction() ||
6088 innermost_function().IsSyncGenClosure() ||
6089 innermost_function().IsSyncGenerator()) {
6085 SetupSavedTryContext(context_var); 6090 SetupSavedTryContext(context_var);
6086 } 6091 }
6087 } 6092 }
6088 6093
6089 6094
6090 void Parser::AddSyncGenClosureParameters(ParamList* params) { 6095 void Parser::AddSyncGenClosureParameters(ParamList* params) {
6091 // Create the parameter list for the body closure of a sync generator: 6096 // Create the parameter list for the body closure of a sync generator:
6092 // 1) Implicit closure parameter; 6097 // 1) Implicit closure parameter;
6093 // 2) Iterator 6098 // 2) Iterator
6094 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); 6099 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
6157 ClassFinalizer::FinalizeType( 6162 ClassFinalizer::FinalizeType(
6158 sig_cls, sig_type, ClassFinalizer::kCanonicalize); 6163 sig_cls, sig_type, ClassFinalizer::kCanonicalize);
6159 } 6164 }
6160 ASSERT(AbstractType::Handle(Z, body.result_type()).IsResolved()); 6165 ASSERT(AbstractType::Handle(Z, body.result_type()).IsResolved());
6161 ASSERT(body.NumParameters() == closure_params.parameters->length()); 6166 ASSERT(body.NumParameters() == closure_params.parameters->length());
6162 } 6167 }
6163 6168
6164 OpenFunctionBlock(body); 6169 OpenFunctionBlock(body);
6165 AddFormalParamsToScope(&closure_params, current_block_->scope); 6170 AddFormalParamsToScope(&closure_params, current_block_->scope);
6166 OpenBlock(); 6171 OpenBlock();
6167 6172 async_temp_scope_ = current_block_->scope;
6168 /*
6169 async_temp_scope_ = current_block_->scope; // Is this needed?
6170 */
6171 return body.raw(); 6173 return body.raw();
6172 } 6174 }
6173 6175
6174 SequenceNode* Parser::CloseSyncGenFunction(const Function& closure, 6176 SequenceNode* Parser::CloseSyncGenFunction(const Function& closure,
6175 SequenceNode* closure_body) { 6177 SequenceNode* closure_body) {
6176 // The block for the closure body has already been closed. Close the 6178 // The block for the closure body has already been closed. Close the
6177 // corresponding function block. 6179 // corresponding function block.
6178 CloseBlock(); 6180 CloseBlock();
6179 6181
6180 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); 6182 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
(...skipping 2008 matching lines...) Expand 10 before | Expand all | Expand 10 after
8189 8191
8190 SequenceNode* Parser::ParseFinallyBlock() { 8192 SequenceNode* Parser::ParseFinallyBlock() {
8191 TRACE_PARSER("ParseFinallyBlock"); 8193 TRACE_PARSER("ParseFinallyBlock");
8192 OpenBlock(); 8194 OpenBlock();
8193 ExpectToken(Token::kLBRACE); 8195 ExpectToken(Token::kLBRACE);
8194 8196
8195 // In case of async closures we need to restore the saved try index of an 8197 // In case of async closures we need to restore the saved try index of an
8196 // outer try block (if it exists). The current try block has already been 8198 // outer try block (if it exists). The current try block has already been
8197 // removed from the stack of try blocks. 8199 // removed from the stack of try blocks.
8198 if ((innermost_function().IsAsyncClosure() || 8200 if ((innermost_function().IsAsyncClosure() ||
8199 innermost_function().IsAsyncFunction()) && 8201 innermost_function().IsAsyncFunction() ||
8202 innermost_function().IsSyncGenClosure() ||
8203 innermost_function().IsSyncGenerator()) &&
8200 (try_blocks_list_ != NULL)) { 8204 (try_blocks_list_ != NULL)) {
8201 // We need two unchain two scopes: finally clause, and the try block level. 8205 // We need two unchain two scopes: finally clause, and the try block level.
8202 RestoreSavedTryContext(current_block_->scope->parent()->parent(), 8206 RestoreSavedTryContext(current_block_->scope->parent()->parent(),
8203 try_blocks_list_->try_index(), 8207 try_blocks_list_->try_index(),
8204 current_block_->statements); 8208 current_block_->statements);
8205 } else { 8209 } else {
8206 parsed_function()->reset_saved_try_ctx_vars(); 8210 parsed_function()->reset_saved_try_ctx_vars();
8207 } 8211 }
8208 8212
8209 ParseStatementSequence(); 8213 ParseStatementSequence();
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
8349 } 8353 }
8350 8354
8351 // Add nested block with user-defined code. This blocks allows 8355 // Add nested block with user-defined code. This blocks allows
8352 // declarations in the body to shadow the catch parameters. 8356 // declarations in the body to shadow the catch parameters.
8353 CheckToken(Token::kLBRACE); 8357 CheckToken(Token::kLBRACE);
8354 8358
8355 // In case of async closures we need to restore the saved try index of an 8359 // In case of async closures we need to restore the saved try index of an
8356 // outer try block (if it exists). 8360 // outer try block (if it exists).
8357 ASSERT(try_blocks_list_ != NULL); 8361 ASSERT(try_blocks_list_ != NULL);
8358 if (innermost_function().IsAsyncClosure() || 8362 if (innermost_function().IsAsyncClosure() ||
8359 innermost_function().IsAsyncFunction()) { 8363 innermost_function().IsAsyncFunction() ||
8364 innermost_function().IsSyncGenClosure() ||
8365 innermost_function().IsSyncGenerator()) {
8360 if ((try_blocks_list_->outer_try_block() != NULL) && 8366 if ((try_blocks_list_->outer_try_block() != NULL) &&
8361 (try_blocks_list_->outer_try_block()->try_block() 8367 (try_blocks_list_->outer_try_block()->try_block()
8362 ->scope->function_level() == 8368 ->scope->function_level() ==
8363 current_block_->scope->function_level())) { 8369 current_block_->scope->function_level())) {
8364 // We need to unchain three scope levels: catch clause, catch 8370 // We need to unchain three scope levels: catch clause, catch
8365 // parameters, and the general try block. 8371 // parameters, and the general try block.
8366 RestoreSavedTryContext( 8372 RestoreSavedTryContext(
8367 current_block_->scope->parent()->parent()->parent(), 8373 current_block_->scope->parent()->parent()->parent(),
8368 try_blocks_list_->outer_try_block()->try_index(), 8374 try_blocks_list_->outer_try_block()->try_index(),
8369 current_block_->statements); 8375 current_block_->statements);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
8457 // a rethrow, use an empty else body (current = NULL above). 8463 // a rethrow, use an empty else body (current = NULL above).
8458 8464
8459 while (!type_tests.is_empty()) { 8465 while (!type_tests.is_empty()) {
8460 AstNode* type_test = type_tests.RemoveLast(); 8466 AstNode* type_test = type_tests.RemoveLast();
8461 SequenceNode* catch_block = catch_blocks.RemoveLast(); 8467 SequenceNode* catch_block = catch_blocks.RemoveLast();
8462 8468
8463 // In case of async closures we need to restore the saved try index of an 8469 // In case of async closures we need to restore the saved try index of an
8464 // outer try block (if it exists). 8470 // outer try block (if it exists).
8465 ASSERT(try_blocks_list_ != NULL); 8471 ASSERT(try_blocks_list_ != NULL);
8466 if (innermost_function().IsAsyncClosure() || 8472 if (innermost_function().IsAsyncClosure() ||
8467 innermost_function().IsAsyncFunction()) { 8473 innermost_function().IsAsyncFunction() ||
8474 innermost_function().IsSyncGenClosure() ||
8475 innermost_function().IsSyncGenerator()) {
8468 if ((try_blocks_list_->outer_try_block() != NULL) && 8476 if ((try_blocks_list_->outer_try_block() != NULL) &&
8469 (try_blocks_list_->outer_try_block()->try_block() 8477 (try_blocks_list_->outer_try_block()->try_block()
8470 ->scope->function_level() == 8478 ->scope->function_level() ==
8471 current_block_->scope->function_level())) { 8479 current_block_->scope->function_level())) {
8472 // We need to unchain three scope levels: catch clause, catch 8480 // We need to unchain three scope levels: catch clause, catch
8473 // parameters, and the general try block. 8481 // parameters, and the general try block.
8474 RestoreSavedTryContext( 8482 RestoreSavedTryContext(
8475 current_block_->scope->parent()->parent(), 8483 current_block_->scope->parent()->parent(),
8476 try_blocks_list_->outer_try_block()->try_index(), 8484 try_blocks_list_->outer_try_block()->try_index(),
8477 current_block_->statements); 8485 current_block_->statements);
(...skipping 10 matching lines...) Expand all
8488 } 8496 }
8489 8497
8490 8498
8491 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) { 8499 void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) {
8492 const String& async_saved_try_ctx_name = 8500 const String& async_saved_try_ctx_name =
8493 BuildAsyncSavedTryContextName(Z, last_used_try_index_ - 1); 8501 BuildAsyncSavedTryContextName(Z, last_used_try_index_ - 1);
8494 LocalVariable* async_saved_try_ctx = new (Z) LocalVariable( 8502 LocalVariable* async_saved_try_ctx = new (Z) LocalVariable(
8495 Scanner::kNoSourcePos, 8503 Scanner::kNoSourcePos,
8496 async_saved_try_ctx_name, 8504 async_saved_try_ctx_name,
8497 Type::ZoneHandle(Z, Type::DynamicType())); 8505 Type::ZoneHandle(Z, Type::DynamicType()));
8506 ASSERT(async_temp_scope_ != NULL);
8498 async_temp_scope_->AddVariable(async_saved_try_ctx); 8507 async_temp_scope_->AddVariable(async_saved_try_ctx);
8499 async_saved_try_ctx->set_is_captured(); 8508 async_saved_try_ctx->set_is_captured();
8500 async_saved_try_ctx = current_block_->scope->LookupVariable( 8509 async_saved_try_ctx = current_block_->scope->LookupVariable(
8501 async_saved_try_ctx_name, false); 8510 async_saved_try_ctx_name, false);
8502 ASSERT(async_saved_try_ctx != NULL); 8511 ASSERT(async_saved_try_ctx != NULL);
8503 ASSERT(saved_try_context != NULL); 8512 ASSERT(saved_try_context != NULL);
8504 current_block_->statements->Add(new(Z) StoreLocalNode( 8513 current_block_->statements->Add(new(Z) StoreLocalNode(
8505 Scanner::kNoSourcePos, 8514 Scanner::kNoSourcePos,
8506 async_saved_try_ctx, 8515 async_saved_try_ctx,
8507 new(Z) LoadLocalNode(Scanner::kNoSourcePos, saved_try_context))); 8516 new(Z) LoadLocalNode(Scanner::kNoSourcePos, saved_try_context)));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
8593 OpenBlock(); 8602 OpenBlock();
8594 current_block_->scope->AddLabel(try_label); 8603 current_block_->scope->AddLabel(try_label);
8595 } 8604 }
8596 8605
8597 // Now parse the 'try' block. 8606 // Now parse the 'try' block.
8598 OpenBlock(); 8607 OpenBlock();
8599 PushTryBlock(current_block_); 8608 PushTryBlock(current_block_);
8600 ExpectToken(Token::kLBRACE); 8609 ExpectToken(Token::kLBRACE);
8601 8610
8602 if (innermost_function().IsAsyncClosure() || 8611 if (innermost_function().IsAsyncClosure() ||
8603 innermost_function().IsAsyncFunction()) { 8612 innermost_function().IsAsyncFunction() ||
8613 innermost_function().IsSyncGenClosure() ||
8614 innermost_function().IsSyncGenerator()) {
8604 SetupSavedTryContext(context_var); 8615 SetupSavedTryContext(context_var);
8605 } 8616 }
8606 8617
8607 ParseStatementSequence(); 8618 ParseStatementSequence();
8608 ExpectToken(Token::kRBRACE); 8619 ExpectToken(Token::kRBRACE);
8609 SequenceNode* try_block = CloseBlock(); 8620 SequenceNode* try_block = CloseBlock();
8610 8621
8611 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && 8622 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") &&
8612 (CurrentToken() != Token::kFINALLY)) { 8623 (CurrentToken() != Token::kFINALLY)) {
8613 ReportError("catch or finally clause expected"); 8624 ReportError("catch or finally clause expected");
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
8835 yield->AddNode(set_is_yield_each); 8846 yield->AddNode(set_is_yield_each);
8836 } 8847 }
8837 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); 8848 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
8838 await_marker->set_scope(current_block_->scope); 8849 await_marker->set_scope(current_block_->scope);
8839 yield->AddNode(await_marker); 8850 yield->AddNode(await_marker);
8840 // Return true to indicate that a value has been generated. 8851 // Return true to indicate that a value has been generated.
8841 ReturnNode* return_true = new(Z) ReturnNode(statement_pos, 8852 ReturnNode* return_true = new(Z) ReturnNode(statement_pos,
8842 new(Z) LiteralNode(TokenPos(), Bool::True())); 8853 new(Z) LiteralNode(TokenPos(), Bool::True()));
8843 return_true->set_return_type(ReturnNode::kContinuationTarget); 8854 return_true->set_return_type(ReturnNode::kContinuationTarget);
8844 yield->AddNode(return_true); 8855 yield->AddNode(return_true);
8856
8857 // If this expression is part of a try block, also append the code for
8858 // restoring the saved try context that lives on the stack.
8859 const String& async_saved_try_ctx_name =
8860 String::Handle(Z, parsed_function()->async_saved_try_ctx_name());
8861 if (!async_saved_try_ctx_name.IsNull()) {
8862 LocalVariable* async_saved_try_ctx =
8863 current_block_->scope->LookupVariable(async_saved_try_ctx_name,
8864 false);
8865 ASSERT(async_saved_try_ctx != NULL);
8866 yield->AddNode(new (Z) StoreLocalNode(
8867 Scanner::kNoSourcePos,
8868 parsed_function()->saved_try_ctx(),
8869 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx)));
8870 }
8871
8845 statement = yield; 8872 statement = yield;
8846 ExpectSemicolon(); 8873 ExpectSemicolon();
8847 } else if (token == Token::kIF) { 8874 } else if (token == Token::kIF) {
8848 statement = ParseIfStatement(label_name); 8875 statement = ParseIfStatement(label_name);
8849 } else if (token == Token::kASSERT) { 8876 } else if (token == Token::kASSERT) {
8850 statement = ParseAssertStatement(); 8877 statement = ParseAssertStatement();
8851 ExpectSemicolon(); 8878 ExpectSemicolon();
8852 } else if (IsVariableDeclaration()) { 8879 } else if (IsVariableDeclaration()) {
8853 statement = ParseVariableDeclarationList(); 8880 statement = ParseVariableDeclarationList();
8854 ExpectSemicolon(); 8881 ExpectSemicolon();
(...skipping 3669 matching lines...) Expand 10 before | Expand all | Expand 10 after
12524 void Parser::SkipQualIdent() { 12551 void Parser::SkipQualIdent() {
12525 ASSERT(IsIdentifier()); 12552 ASSERT(IsIdentifier());
12526 ConsumeToken(); 12553 ConsumeToken();
12527 if (CurrentToken() == Token::kPERIOD) { 12554 if (CurrentToken() == Token::kPERIOD) {
12528 ConsumeToken(); // Consume the kPERIOD token. 12555 ConsumeToken(); // Consume the kPERIOD token.
12529 ExpectIdentifier("identifier expected after '.'"); 12556 ExpectIdentifier("identifier expected after '.'");
12530 } 12557 }
12531 } 12558 }
12532 12559
12533 } // namespace dart 12560 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698