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