OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
9 #include "vm/ast_transformer.h" | 9 #include "vm/ast_transformer.h" |
10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
(...skipping 8237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8248 await_cond->AddNode(await_preamble); | 8248 await_cond->AddNode(await_preamble); |
8249 await_cond->AddNode(cond_expr); | 8249 await_cond->AddNode(cond_expr); |
8250 cond_expr = await_cond; | 8250 cond_expr = await_cond; |
8251 } | 8251 } |
8252 ExpectToken(Token::kRPAREN); | 8252 ExpectToken(Token::kRPAREN); |
8253 ExpectSemicolon(); | 8253 ExpectSemicolon(); |
8254 return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body); | 8254 return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body); |
8255 } | 8255 } |
8256 | 8256 |
8257 | 8257 |
| 8258 static LocalVariable* LookupSavedTryContextVar(LocalScope* scope) { |
| 8259 LocalVariable* var = |
| 8260 scope->LocalLookupVariable(Symbols::SavedTryContextVar()); |
| 8261 ASSERT((var != NULL) && !var->is_captured()); |
| 8262 return var; |
| 8263 } |
| 8264 |
| 8265 |
| 8266 static LocalVariable* LookupAsyncSavedTryContextVar(LocalScope* scope, |
| 8267 uint16_t try_index) { |
| 8268 const String& async_saved_try_ctx_name = |
| 8269 String::ZoneHandle(Symbols::New(String::Handle( |
| 8270 String::NewFormatted( |
| 8271 "%s%d", |
| 8272 Symbols::AsyncSavedTryCtxVarPrefix().ToCString(), |
| 8273 try_index)))); |
| 8274 LocalVariable* var = scope->LocalLookupVariable(async_saved_try_ctx_name); |
| 8275 ASSERT((var != NULL) && var->is_captured());\ |
| 8276 return var; |
| 8277 } |
| 8278 |
| 8279 |
8258 // If the await or yield being parsed is in a try block, the continuation code | 8280 // If the await or yield being parsed is in a try block, the continuation code |
8259 // needs to restore the corresponding stack-based variable :saved_try_ctx_var, | 8281 // needs to restore the corresponding stack-based variable :saved_try_ctx_var, |
8260 // and the stack-based variable :saved_try_ctx_var of the outer try block. | 8282 // and the stack-based variable :saved_try_ctx_var of the outer try block. |
8261 // The inner :saved_try_ctx_var is used by a finally clause handling an | 8283 // The inner :saved_try_ctx_var is used by a finally clause handling an |
8262 // exception thrown by the continuation code in a try block or catch block. | 8284 // exception thrown by the continuation code in a try block or catch block. |
8263 // If no finally clause exists, the catch or finally clause of the outer try | 8285 // If no finally clause exists, the catch or finally clause of the outer try |
8264 // block, if any, uses the outer :saved_try_ctx_var to handle the exception. | 8286 // block, if any, uses the outer :saved_try_ctx_var to handle the exception. |
8265 // | 8287 // |
8266 // * Try blocks and catch blocks: | 8288 // * Try blocks and catch blocks: |
8267 // Set the context variable for this try block and for the outer try block. | 8289 // Set the context variable for this try block and for the outer try block. |
8268 // * Finally blocks: | 8290 // * Finally blocks: |
8269 // Set the context variable for the outer try block. Note that the try | 8291 // Set the context variable for the outer try block. Note that the try |
8270 // declaring the finally is popped before parsing the finally clause, so the | 8292 // declaring the finally is popped before parsing the finally clause, so the |
8271 // outer try block is at the top of the try block list. | 8293 // outer try block is at the top of the try block list. |
8272 // | 8294 void Parser::CheckAsyncOpInTryBlock( |
8273 // TODO(regis): Could we return the variables instead of their containing | 8295 LocalVariable** saved_try_ctx, |
8274 // scopes? Check if they are already setup at this point. | 8296 LocalVariable** async_saved_try_ctx, |
8275 void Parser::CheckAsyncOpInTryBlock(LocalScope** try_scope, | 8297 LocalVariable** outer_saved_try_ctx, |
8276 int16_t* try_index, | 8298 LocalVariable** outer_async_saved_try_ctx) const { |
8277 LocalScope** outer_try_scope, | 8299 *saved_try_ctx = NULL; |
8278 int16_t* outer_try_index) const { | 8300 *async_saved_try_ctx = NULL; |
8279 *try_scope = NULL; | 8301 *outer_saved_try_ctx = NULL; |
8280 *try_index = CatchClauseNode::kInvalidTryIndex; | 8302 *outer_async_saved_try_ctx = NULL; |
8281 *outer_try_scope = NULL; | |
8282 *outer_try_index = CatchClauseNode::kInvalidTryIndex; | |
8283 if (try_stack_ != NULL) { | 8303 if (try_stack_ != NULL) { |
8284 LocalScope* scope = try_stack_->try_block()->scope; | 8304 LocalScope* scope = try_stack_->try_block()->scope; |
| 8305 uint16_t try_index = try_stack_->try_index(); |
8285 const int current_function_level = current_block_->scope->function_level(); | 8306 const int current_function_level = current_block_->scope->function_level(); |
8286 if (scope->function_level() == current_function_level) { | 8307 if (scope->function_level() == current_function_level) { |
8287 // The block declaring :saved_try_ctx_var variable is the parent of the | 8308 // The block declaring :saved_try_ctx_var variable is the parent of the |
8288 // pushed try block. | 8309 // pushed try block. |
8289 *try_scope = scope->parent(); | 8310 *saved_try_ctx = LookupSavedTryContextVar(scope->parent()); |
8290 *try_index = try_stack_->try_index(); | 8311 *async_saved_try_ctx = LookupAsyncSavedTryContextVar(scope, try_index); |
8291 if (try_stack_->outer_try() != NULL) { | 8312 if (try_stack_->outer_try() != NULL) { |
8292 // TODO(regis): Collecting the outer try scope is not necessary if we | 8313 // TODO(regis): Collecting the outer try scope is not necessary if we |
8293 // are in a finally block. Add support for try_stack_->inside_finally(). | 8314 // are in a finally block. Add support for try_stack_->inside_finally(). |
8294 scope = try_stack_->outer_try()->try_block()->scope; | 8315 scope = try_stack_->outer_try()->try_block()->scope; |
| 8316 try_index = try_stack_->outer_try()->try_index(); |
8295 if (scope->function_level() == current_function_level) { | 8317 if (scope->function_level() == current_function_level) { |
8296 *outer_try_scope = scope->parent(); | 8318 *outer_saved_try_ctx = LookupSavedTryContextVar(scope->parent()); |
8297 *outer_try_index = try_stack_->outer_try()->try_index(); | 8319 *outer_async_saved_try_ctx = |
| 8320 LookupAsyncSavedTryContextVar(scope, try_index); |
8298 } | 8321 } |
8299 } | 8322 } |
8300 } | 8323 } |
8301 } | 8324 } |
8302 // An async or async* has an implicitly created try-catch around the | 8325 // An async or async* has an implicitly created try-catch around the |
8303 // function body, so the await or yield inside the async closure should always | 8326 // function body, so the await or yield inside the async closure should always |
8304 // be created with a try scope. | 8327 // be created with a try scope. |
8305 ASSERT((*try_scope != NULL) || | 8328 ASSERT((*saved_try_ctx != NULL) || |
8306 innermost_function().IsAsyncFunction() || | 8329 innermost_function().IsAsyncFunction() || |
8307 innermost_function().IsAsyncGenerator() || | 8330 innermost_function().IsAsyncGenerator() || |
8308 innermost_function().IsSyncGenClosure() || | 8331 innermost_function().IsSyncGenClosure() || |
8309 innermost_function().IsSyncGenerator()); | 8332 innermost_function().IsSyncGenerator()); |
8310 } | 8333 } |
8311 | 8334 |
8312 | 8335 |
8313 // Build an AST node for static call to Dart function print(str). | 8336 // Build an AST node for static call to Dart function print(str). |
8314 // Used during debugging to insert print in generated dart code. | 8337 // Used during debugging to insert print in generated dart code. |
8315 AstNode* Parser::DartPrint(const char* str) { | 8338 AstNode* Parser::DartPrint(const char* str) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8419 &exception_var, | 8442 &exception_var, |
8420 &stack_trace_var, | 8443 &stack_trace_var, |
8421 &saved_exception_var, | 8444 &saved_exception_var, |
8422 &saved_stack_trace_var); | 8445 &saved_stack_trace_var); |
8423 OpenBlock(); // try block. | 8446 OpenBlock(); // try block. |
8424 PushTry(current_block_); | 8447 PushTry(current_block_); |
8425 SetupSavedTryContext(context_var); | 8448 SetupSavedTryContext(context_var); |
8426 | 8449 |
8427 // Build while loop condition. | 8450 // Build while loop condition. |
8428 // while (await :for-in-iter.moveNext()) | 8451 // while (await :for-in-iter.moveNext()) |
8429 LocalScope* try_scope; | 8452 LocalVariable* saved_try_ctx; |
8430 int16_t try_index; | 8453 LocalVariable* async_saved_try_ctx; |
8431 LocalScope* outer_try_scope; | 8454 LocalVariable* outer_saved_try_ctx; |
8432 int16_t outer_try_index; | 8455 LocalVariable* outer_async_saved_try_ctx; |
8433 CheckAsyncOpInTryBlock(&try_scope, &try_index, | 8456 CheckAsyncOpInTryBlock(&saved_try_ctx, |
8434 &outer_try_scope, &outer_try_index); | 8457 &async_saved_try_ctx, |
8435 | 8458 &outer_saved_try_ctx, |
| 8459 &outer_async_saved_try_ctx); |
8436 ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos); | 8460 ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos); |
8437 AstNode* iterator_moveNext = new(Z) InstanceCallNode( | 8461 AstNode* iterator_moveNext = new(Z) InstanceCallNode( |
8438 stream_pos, | 8462 stream_pos, |
8439 new(Z) LoadLocalNode(stream_pos, iterator_var), | 8463 new(Z) LoadLocalNode(stream_pos, iterator_var), |
8440 Symbols::MoveNext(), | 8464 Symbols::MoveNext(), |
8441 no_args); | 8465 no_args); |
8442 AstNode* await_moveNext = | 8466 AstNode* await_moveNext = |
8443 new(Z) AwaitNode(stream_pos, | 8467 new(Z) AwaitNode(stream_pos, |
8444 iterator_moveNext, | 8468 iterator_moveNext, |
8445 try_scope, | 8469 saved_try_ctx, |
8446 try_index, | 8470 async_saved_try_ctx, |
8447 outer_try_scope, | 8471 outer_saved_try_ctx, |
8448 outer_try_index); | 8472 outer_async_saved_try_ctx); |
8449 OpenBlock(); | 8473 OpenBlock(); |
8450 AwaitTransformer at(current_block_->statements, async_temp_scope_); | 8474 AwaitTransformer at(current_block_->statements, async_temp_scope_); |
8451 await_moveNext = at.Transform(await_moveNext); | 8475 await_moveNext = at.Transform(await_moveNext); |
8452 SequenceNode* await_preamble = CloseBlock(); | 8476 SequenceNode* await_preamble = CloseBlock(); |
8453 | 8477 |
8454 // Parse the for loop body. Ideally, we would use ParseNestedStatement() | 8478 // Parse the for loop body. Ideally, we would use ParseNestedStatement() |
8455 // here, but that does not work well because we have to insert an implicit | 8479 // here, but that does not work well because we have to insert an implicit |
8456 // variable assignment and potentially a variable declaration in the | 8480 // variable assignment and potentially a variable declaration in the |
8457 // loop body. | 8481 // loop body. |
8458 OpenLoopBlock(); | 8482 OpenLoopBlock(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8516 for_loop_block); | 8540 for_loop_block); |
8517 // Add the while loop to the try block. | 8541 // Add the while loop to the try block. |
8518 current_block_->statements->Add(while_node); | 8542 current_block_->statements->Add(while_node); |
8519 SequenceNode* try_block = CloseBlock(); | 8543 SequenceNode* try_block = CloseBlock(); |
8520 | 8544 |
8521 // Create an empty "catch all" block that rethrows the current | 8545 // Create an empty "catch all" block that rethrows the current |
8522 // exception and stacktrace. | 8546 // exception and stacktrace. |
8523 try_stack_->enter_catch(); | 8547 try_stack_->enter_catch(); |
8524 SequenceNode* catch_block = new(Z) SequenceNode(await_for_pos, NULL); | 8548 SequenceNode* catch_block = new(Z) SequenceNode(await_for_pos, NULL); |
8525 | 8549 |
8526 if (outer_try_scope != NULL) { | 8550 if (outer_saved_try_ctx != NULL) { |
8527 catch_block->Add(AwaitTransformer::RestoreSavedTryContext( | 8551 catch_block->Add(new (Z) StoreLocalNode( |
8528 Z, outer_try_scope, outer_try_index)); | 8552 Scanner::kNoSourcePos, |
| 8553 outer_saved_try_ctx, |
| 8554 new (Z) LoadLocalNode(Scanner::kNoSourcePos, |
| 8555 outer_async_saved_try_ctx))); |
8529 } | 8556 } |
8530 | 8557 |
8531 // We don't need to copy the current exception and stack trace variables | 8558 // We don't need to copy the current exception and stack trace variables |
8532 // into :saved_exception_var and :saved_stack_trace_var here because there | 8559 // into :saved_exception_var and :saved_stack_trace_var here because there |
8533 // is no code in the catch clause that could suspend the function. | 8560 // is no code in the catch clause that could suspend the function. |
8534 | 8561 |
8535 // Rethrow the exception. | 8562 // Rethrow the exception. |
8536 catch_block->Add(new(Z) ThrowNode( | 8563 catch_block->Add(new(Z) ThrowNode( |
8537 await_for_pos, | 8564 await_for_pos, |
8538 new(Z) LoadLocalNode(await_for_pos, exception_var), | 8565 new(Z) LoadLocalNode(await_for_pos, exception_var), |
8539 new(Z) LoadLocalNode(await_for_pos, stack_trace_var))); | 8566 new(Z) LoadLocalNode(await_for_pos, stack_trace_var))); |
8540 | 8567 |
8541 TryStack* try_statement = PopTry(); | 8568 TryStack* try_statement = PopTry(); |
8542 ASSERT(try_index == try_statement->try_index()); | 8569 const intptr_t try_index = try_statement->try_index(); |
| 8570 TryStack* outer_try = try_stack_; |
| 8571 const intptr_t outer_try_index = (outer_try != NULL) ? |
| 8572 outer_try->try_index() : CatchClauseNode::kInvalidTryIndex; |
8543 | 8573 |
8544 // The finally block contains a call to cancel the stream. | 8574 // The finally block contains a call to cancel the stream. |
8545 // :for-in-iter.cancel() | 8575 // :for-in-iter.cancel() |
8546 | 8576 |
8547 // Inline the finally block to the exit points in the try block. | 8577 // Inline the finally block to the exit points in the try block. |
8548 intptr_t node_index = 0; | 8578 intptr_t node_index = 0; |
8549 SequenceNode* finally_clause = NULL; | 8579 SequenceNode* finally_clause = NULL; |
8550 do { | 8580 do { |
8551 OpenBlock(); | 8581 OpenBlock(); |
8552 ArgumentListNode* no_args = | 8582 ArgumentListNode* no_args = |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8935 OpenBlock(); | 8965 OpenBlock(); |
8936 ExpectToken(Token::kLBRACE); | 8966 ExpectToken(Token::kLBRACE); |
8937 | 8967 |
8938 // In case of async closures we need to restore the saved try index of an | 8968 // In case of async closures we need to restore the saved try index of an |
8939 // outer try block (if it exists). The current try block has already been | 8969 // outer try block (if it exists). The current try block has already been |
8940 // removed from the stack of try blocks. | 8970 // removed from the stack of try blocks. |
8941 if (is_async) { | 8971 if (is_async) { |
8942 if (try_stack_ != NULL) { | 8972 if (try_stack_ != NULL) { |
8943 LocalScope* scope = try_stack_->try_block()->scope; | 8973 LocalScope* scope = try_stack_->try_block()->scope; |
8944 if (scope->function_level() == current_block_->scope->function_level()) { | 8974 if (scope->function_level() == current_block_->scope->function_level()) { |
| 8975 LocalVariable* saved_try_ctx = |
| 8976 LookupSavedTryContextVar(scope->parent()); |
| 8977 LocalVariable* async_saved_try_ctx = |
| 8978 LookupAsyncSavedTryContextVar(scope->parent(), |
| 8979 try_stack_->try_index()); |
8945 current_block_->statements->Add( | 8980 current_block_->statements->Add( |
8946 AwaitTransformer::RestoreSavedTryContext( | 8981 new (Z) StoreLocalNode( |
8947 Z, scope->parent(), try_stack_->try_index())); | 8982 Scanner::kNoSourcePos, |
| 8983 saved_try_ctx, |
| 8984 new (Z) LoadLocalNode(Scanner::kNoSourcePos, |
| 8985 async_saved_try_ctx))); |
8948 } | 8986 } |
8949 } | 8987 } |
8950 // We need to save the exception variables as in catch clauses, whether | 8988 // We need to save the exception variables as in catch clauses, whether |
8951 // there is an outer try or not. Note that this is only necessary if the | 8989 // there is an outer try or not. Note that this is only necessary if the |
8952 // finally clause contains an await or yield. | 8990 // finally clause contains an await or yield. |
8953 // TODO(hausner): Optimize. | 8991 // TODO(hausner): Optimize. |
8954 SaveExceptionAndStacktrace(current_block_->statements, | 8992 SaveExceptionAndStacktrace(current_block_->statements, |
8955 exception_var, | 8993 exception_var, |
8956 stack_trace_var, | 8994 stack_trace_var, |
8957 rethrow_exception_var, | 8995 rethrow_exception_var, |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9195 current = CloseBlock(); | 9233 current = CloseBlock(); |
9196 } | 9234 } |
9197 // In case of async closures, restore :saved_try_context_var before executing | 9235 // In case of async closures, restore :saved_try_context_var before executing |
9198 // the catch clauses. | 9236 // the catch clauses. |
9199 if (is_async && (current != NULL)) { | 9237 if (is_async && (current != NULL)) { |
9200 ASSERT(try_stack_ != NULL); | 9238 ASSERT(try_stack_ != NULL); |
9201 SequenceNode* async_code = new(Z) SequenceNode(handler_pos, NULL); | 9239 SequenceNode* async_code = new(Z) SequenceNode(handler_pos, NULL); |
9202 const TryStack* try_block = try_stack_->outer_try(); | 9240 const TryStack* try_block = try_stack_->outer_try(); |
9203 if (try_block != NULL) { | 9241 if (try_block != NULL) { |
9204 LocalScope* scope = try_block->try_block()->scope; | 9242 LocalScope* scope = try_block->try_block()->scope; |
9205 if (scope->function_level() == | 9243 if (scope->function_level() == current_block_->scope->function_level()) { |
9206 current_block_->scope->function_level()) { | 9244 LocalVariable* saved_try_ctx = |
9207 async_code->Add( | 9245 LookupSavedTryContextVar(scope->parent()); |
9208 AwaitTransformer::RestoreSavedTryContext( | 9246 LocalVariable* async_saved_try_ctx = |
9209 Z, scope->parent(), try_block->try_index())); | 9247 LookupAsyncSavedTryContextVar(scope->parent(), |
| 9248 try_block->try_index()); |
| 9249 current_block_->statements->Add( |
| 9250 new (Z) StoreLocalNode( |
| 9251 Scanner::kNoSourcePos, |
| 9252 saved_try_ctx, |
| 9253 new (Z) LoadLocalNode(Scanner::kNoSourcePos, |
| 9254 async_saved_try_ctx))); |
9210 } | 9255 } |
9211 } | 9256 } |
9212 SaveExceptionAndStacktrace(async_code, | 9257 SaveExceptionAndStacktrace(async_code, |
9213 exception_var, | 9258 exception_var, |
9214 stack_trace_var, | 9259 stack_trace_var, |
9215 rethrow_exception_var, | 9260 rethrow_exception_var, |
9216 rethrow_stack_trace_var); | 9261 rethrow_stack_trace_var); |
9217 // The async_code node sequence contains code to restore the context (if | 9262 // The async_code node sequence contains code to restore the context (if |
9218 // an outer try block is present) and code to save the exception and | 9263 // an outer try block is present) and code to save the exception and |
9219 // stack trace variables. | 9264 // stack trace variables. |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9565 yield->AddNode(await_marker); | 9610 yield->AddNode(await_marker); |
9566 // Return true to indicate that a value has been generated. | 9611 // Return true to indicate that a value has been generated. |
9567 ReturnNode* return_true = new(Z) ReturnNode(yield_pos, | 9612 ReturnNode* return_true = new(Z) ReturnNode(yield_pos, |
9568 new(Z) LiteralNode(TokenPos(), Bool::True())); | 9613 new(Z) LiteralNode(TokenPos(), Bool::True())); |
9569 return_true->set_return_type(ReturnNode::kContinuationTarget); | 9614 return_true->set_return_type(ReturnNode::kContinuationTarget); |
9570 yield->AddNode(return_true); | 9615 yield->AddNode(return_true); |
9571 | 9616 |
9572 // If this expression is part of a try block, also append the code for | 9617 // If this expression is part of a try block, also append the code for |
9573 // restoring the saved try context that lives on the stack and possibly the | 9618 // restoring the saved try context that lives on the stack and possibly the |
9574 // saved try context of the outer try block. | 9619 // saved try context of the outer try block. |
9575 LocalScope* try_scope; | 9620 LocalVariable* saved_try_ctx; |
9576 int16_t try_index; | 9621 LocalVariable* async_saved_try_ctx; |
9577 LocalScope* outer_try_scope; | 9622 LocalVariable* outer_saved_try_ctx; |
9578 int16_t outer_try_index; | 9623 LocalVariable* outer_async_saved_try_ctx; |
9579 CheckAsyncOpInTryBlock(&try_scope, &try_index, | 9624 CheckAsyncOpInTryBlock(&saved_try_ctx, |
9580 &outer_try_scope, &outer_try_index); | 9625 &async_saved_try_ctx, |
9581 if (try_scope != NULL) { | 9626 &outer_saved_try_ctx, |
9582 yield->AddNode( | 9627 &outer_async_saved_try_ctx); |
9583 AwaitTransformer::RestoreSavedTryContext(Z, | 9628 if (saved_try_ctx != NULL) { |
9584 try_scope, | 9629 yield->AddNode(new (Z) StoreLocalNode( |
9585 try_index)); | 9630 Scanner::kNoSourcePos, |
9586 if (outer_try_scope != NULL) { | 9631 saved_try_ctx, |
9587 yield->AddNode( | 9632 new (Z) LoadLocalNode(Scanner::kNoSourcePos, |
9588 AwaitTransformer::RestoreSavedTryContext(Z, | 9633 async_saved_try_ctx))); |
9589 outer_try_scope, | 9634 if (outer_saved_try_ctx != NULL) { |
9590 outer_try_index)); | 9635 yield->AddNode(new (Z) StoreLocalNode( |
| 9636 Scanner::kNoSourcePos, |
| 9637 outer_saved_try_ctx, |
| 9638 new (Z) LoadLocalNode(Scanner::kNoSourcePos, |
| 9639 outer_async_saved_try_ctx))); |
9591 } | 9640 } |
9592 } else { | 9641 } else { |
9593 ASSERT(outer_try_scope == NULL); | 9642 ASSERT(outer_saved_try_ctx == NULL); |
9594 } | 9643 } |
9595 } else { | 9644 } else { |
9596 // yield statement in async* function. | 9645 // yield statement in async* function. |
9597 ASSERT(innermost_function().IsAsyncGenerator() || | 9646 ASSERT(innermost_function().IsAsyncGenerator() || |
9598 innermost_function().IsAsyncGenClosure()); | 9647 innermost_function().IsAsyncGenClosure()); |
9599 | 9648 |
9600 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller()); | 9649 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller()); |
9601 ASSERT(controller_var != NULL); | 9650 ASSERT(controller_var != NULL); |
9602 // :controller.add[Stream](expr); | 9651 // :controller.add[Stream](expr); |
9603 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos); | 9652 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos); |
9604 add_args->Add(expr); | 9653 add_args->Add(expr); |
9605 AstNode* add_call = | 9654 AstNode* add_call = |
9606 new(Z) InstanceCallNode(yield_pos, | 9655 new(Z) InstanceCallNode(yield_pos, |
9607 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var), | 9656 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var), |
9608 is_yield_each ? Symbols::AddStream() : Symbols::add(), | 9657 is_yield_each ? Symbols::AddStream() : Symbols::add(), |
9609 add_args); | 9658 add_args); |
9610 | 9659 |
9611 | |
9612 // if (:controller.add[Stream](expr)) { | 9660 // if (:controller.add[Stream](expr)) { |
9613 // return; | 9661 // return; |
9614 // } | 9662 // } |
9615 // await_marker; | 9663 // await_marker; |
9616 // continuation_return; | 9664 // continuation_return; |
9617 // restore saved_try_context | 9665 // restore saved_try_context |
9618 | 9666 |
9619 SequenceNode* true_branch = | 9667 SequenceNode* true_branch = |
9620 new(Z) SequenceNode(Scanner::kNoSourcePos, NULL); | 9668 new(Z) SequenceNode(Scanner::kNoSourcePos, NULL); |
9621 AstNode* return_from_generator = new(Z) ReturnNode(yield_pos); | 9669 AstNode* return_from_generator = new(Z) ReturnNode(yield_pos); |
9622 true_branch->Add(return_from_generator); | 9670 true_branch->Add(return_from_generator); |
9623 AddNodeForFinallyInlining(return_from_generator); | 9671 AddNodeForFinallyInlining(return_from_generator); |
9624 AstNode* if_is_cancelled = | 9672 AstNode* if_is_cancelled = |
9625 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL); | 9673 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL); |
9626 yield->AddNode(if_is_cancelled); | 9674 yield->AddNode(if_is_cancelled); |
9627 | 9675 |
9628 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); | 9676 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); |
9629 await_marker->set_scope(current_block_->scope); | 9677 await_marker->set_scope(current_block_->scope); |
9630 yield->AddNode(await_marker); | 9678 yield->AddNode(await_marker); |
9631 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos); | 9679 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos); |
9632 continuation_return->set_return_type(ReturnNode::kContinuationTarget); | 9680 continuation_return->set_return_type(ReturnNode::kContinuationTarget); |
9633 yield->AddNode(continuation_return); | 9681 yield->AddNode(continuation_return); |
9634 | 9682 |
9635 // If this expression is part of a try block, also append the code for | 9683 // If this expression is part of a try block, also append the code for |
9636 // restoring the saved try context that lives on the stack and possibly the | 9684 // restoring the saved try context that lives on the stack and possibly the |
9637 // saved try context of the outer try block. | 9685 // saved try context of the outer try block. |
9638 LocalScope* try_scope; | 9686 LocalVariable* saved_try_ctx; |
9639 int16_t try_index; | 9687 LocalVariable* async_saved_try_ctx; |
9640 LocalScope* outer_try_scope; | 9688 LocalVariable* outer_saved_try_ctx; |
9641 int16_t outer_try_index; | 9689 LocalVariable* outer_async_saved_try_ctx; |
9642 CheckAsyncOpInTryBlock(&try_scope, &try_index, | 9690 CheckAsyncOpInTryBlock(&saved_try_ctx, |
9643 &outer_try_scope, &outer_try_index); | 9691 &async_saved_try_ctx, |
9644 if (try_scope != NULL) { | 9692 &outer_saved_try_ctx, |
9645 yield->AddNode( | 9693 &outer_async_saved_try_ctx); |
9646 AwaitTransformer::RestoreSavedTryContext(Z, | 9694 if (saved_try_ctx != NULL) { |
9647 try_scope, | 9695 yield->AddNode(new (Z) StoreLocalNode( |
9648 try_index)); | 9696 Scanner::kNoSourcePos, |
9649 if (outer_try_scope != NULL) { | 9697 saved_try_ctx, |
9650 yield->AddNode( | 9698 new (Z) LoadLocalNode(Scanner::kNoSourcePos, |
9651 AwaitTransformer::RestoreSavedTryContext(Z, | 9699 async_saved_try_ctx))); |
9652 outer_try_scope, | 9700 if (outer_saved_try_ctx != NULL) { |
9653 outer_try_index)); | 9701 yield->AddNode(new (Z) StoreLocalNode( |
| 9702 Scanner::kNoSourcePos, |
| 9703 outer_saved_try_ctx, |
| 9704 new (Z) LoadLocalNode(Scanner::kNoSourcePos, |
| 9705 outer_async_saved_try_ctx))); |
9654 } | 9706 } |
9655 } else { | 9707 } else { |
9656 ASSERT(outer_try_scope == NULL); | 9708 ASSERT(outer_saved_try_ctx == NULL); |
9657 } | 9709 } |
9658 } | 9710 } |
9659 return yield; | 9711 return yield; |
9660 } | 9712 } |
9661 | 9713 |
9662 | 9714 |
9663 AstNode* Parser::ParseStatement() { | 9715 AstNode* Parser::ParseStatement() { |
9664 TRACE_PARSER("ParseStatement"); | 9716 TRACE_PARSER("ParseStatement"); |
9665 AstNode* statement = NULL; | 9717 AstNode* statement = NULL; |
9666 intptr_t label_pos = 0; | 9718 intptr_t label_pos = 0; |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10580 TRACE_PARSER("ParseAwaitExpr"); | 10632 TRACE_PARSER("ParseAwaitExpr"); |
10581 if (!innermost_function().IsAsyncFunction() && | 10633 if (!innermost_function().IsAsyncFunction() && |
10582 !innermost_function().IsAsyncClosure() && | 10634 !innermost_function().IsAsyncClosure() && |
10583 !innermost_function().IsAsyncGenerator() && | 10635 !innermost_function().IsAsyncGenerator() && |
10584 !innermost_function().IsAsyncGenClosure()) { | 10636 !innermost_function().IsAsyncGenClosure()) { |
10585 ReportError("await operator is only allowed in an asynchronous function"); | 10637 ReportError("await operator is only allowed in an asynchronous function"); |
10586 } | 10638 } |
10587 ConsumeToken(); | 10639 ConsumeToken(); |
10588 parsed_function()->record_await(); | 10640 parsed_function()->record_await(); |
10589 | 10641 |
10590 LocalScope* try_scope; | 10642 LocalVariable* saved_try_ctx; |
10591 int16_t try_index; | 10643 LocalVariable* async_saved_try_ctx; |
10592 LocalScope* outer_try_scope; | 10644 LocalVariable* outer_saved_try_ctx; |
10593 int16_t outer_try_index; | 10645 LocalVariable* outer_async_saved_try_ctx; |
10594 CheckAsyncOpInTryBlock(&try_scope, &try_index, | 10646 CheckAsyncOpInTryBlock(&saved_try_ctx, |
10595 &outer_try_scope, &outer_try_index); | 10647 &async_saved_try_ctx, |
10596 | 10648 &outer_saved_try_ctx, |
| 10649 &outer_async_saved_try_ctx); |
10597 expr = new (Z) AwaitNode(op_pos, | 10650 expr = new (Z) AwaitNode(op_pos, |
10598 ParseUnaryExpr(), | 10651 ParseUnaryExpr(), |
10599 try_scope, | 10652 saved_try_ctx, |
10600 try_index, | 10653 async_saved_try_ctx, |
10601 outer_try_scope, | 10654 outer_saved_try_ctx, |
10602 outer_try_index); | 10655 outer_async_saved_try_ctx); |
10603 } else if (IsPrefixOperator(CurrentToken())) { | 10656 } else if (IsPrefixOperator(CurrentToken())) { |
10604 Token::Kind unary_op = CurrentToken(); | 10657 Token::Kind unary_op = CurrentToken(); |
10605 if (unary_op == Token::kSUB) { | 10658 if (unary_op == Token::kSUB) { |
10606 unary_op = Token::kNEGATE; | 10659 unary_op = Token::kNEGATE; |
10607 } | 10660 } |
10608 ConsumeToken(); | 10661 ConsumeToken(); |
10609 expr = ParseUnaryExpr(); | 10662 expr = ParseUnaryExpr(); |
10610 if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) { | 10663 if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) { |
10611 expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode()); | 10664 expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode()); |
10612 } else { | 10665 } else { |
(...skipping 2827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13440 void Parser::SkipQualIdent() { | 13493 void Parser::SkipQualIdent() { |
13441 ASSERT(IsIdentifier()); | 13494 ASSERT(IsIdentifier()); |
13442 ConsumeToken(); | 13495 ConsumeToken(); |
13443 if (CurrentToken() == Token::kPERIOD) { | 13496 if (CurrentToken() == Token::kPERIOD) { |
13444 ConsumeToken(); // Consume the kPERIOD token. | 13497 ConsumeToken(); // Consume the kPERIOD token. |
13445 ExpectIdentifier("identifier expected after '.'"); | 13498 ExpectIdentifier("identifier expected after '.'"); |
13446 } | 13499 } |
13447 } | 13500 } |
13448 | 13501 |
13449 } // namespace dart | 13502 } // namespace dart |
OLD | NEW |