| 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 |