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

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

Issue 944893005: Implement async* functions in VM (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "platform/utils.h" 8 #include "platform/utils.h"
9 #include "vm/ast_transformer.h" 9 #include "vm/ast_transformer.h"
10 #include "vm/bootstrap.h" 10 #include "vm/bootstrap.h"
(...skipping 3092 matching lines...) Expand 10 before | Expand all | Expand 10 after
3103 AddFormalParamsToScope(&params, current_block_->scope); 3103 AddFormalParamsToScope(&params, current_block_->scope);
3104 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); 3104 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
3105 if (!Function::Handle(func.parent_function()).IsGetterFunction()) { 3105 if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
3106 // Parse and discard any formal parameters. They are accessed as 3106 // Parse and discard any formal parameters. They are accessed as
3107 // context variables. 3107 // context variables.
3108 ParamList discarded_params; 3108 ParamList discarded_params;
3109 ParseFormalParameterList(allow_explicit_default_values, 3109 ParseFormalParameterList(allow_explicit_default_values,
3110 false, 3110 false,
3111 &discarded_params); 3111 &discarded_params);
3112 } 3112 }
3113 } else if (func.IsAsyncGenClosure()) {
3114 AddAsyncGenClosureParameters(&params);
3115 SetupDefaultsForOptionalParams(&params, default_parameter_values);
3116 AddFormalParamsToScope(&params, current_block_->scope);
3117 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
3118 ASSERT(func.NumParameters() == params.parameters->length());
3119 if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
3120 // Parse and discard any formal parameters. They are accessed as
3121 // context variables.
3122 ParamList discarded_params;
3123 ParseFormalParameterList(allow_explicit_default_values,
3124 false,
3125 &discarded_params);
3126 }
3113 } else { 3127 } else {
3114 ParseFormalParameterList(allow_explicit_default_values, false, &params); 3128 ParseFormalParameterList(allow_explicit_default_values, false, &params);
3115 3129
3116 // The number of parameters and their type are not yet set in local 3130 // The number of parameters and their type are not yet set in local
3117 // functions, since they are not 'top-level' parsed. 3131 // functions, since they are not 'top-level' parsed.
3118 if (func.IsLocalFunction()) { 3132 if (func.IsLocalFunction()) {
3119 AddFormalParamsToFunction(&params, func); 3133 AddFormalParamsToFunction(&params, func);
3120 } 3134 }
3121 SetupDefaultsForOptionalParams(&params, default_parameter_values); 3135 SetupDefaultsForOptionalParams(&params, default_parameter_values);
3122 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); 3136 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
3171 ASSERT(func.is_debuggable()); 3185 ASSERT(func.is_debuggable());
3172 OpenAsyncClosure(); 3186 OpenAsyncClosure();
3173 } else if (func.IsSyncGenerator()) { 3187 } else if (func.IsSyncGenerator()) {
3174 // The code of a sync generator is synthesized. Disable debugging. 3188 // The code of a sync generator is synthesized. Disable debugging.
3175 func.set_is_debuggable(false); 3189 func.set_is_debuggable(false);
3176 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos()); 3190 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos());
3177 } else if (func.IsSyncGenClosure()) { 3191 } else if (func.IsSyncGenClosure()) {
3178 // The closure containing the body of a sync generator is debuggable. 3192 // The closure containing the body of a sync generator is debuggable.
3179 ASSERT(func.is_debuggable()); 3193 ASSERT(func.is_debuggable());
3180 async_temp_scope_ = current_block_->scope; 3194 async_temp_scope_ = current_block_->scope;
3195 } else if (func.IsAsyncGenerator()) {
3196 func.set_is_debuggable(false);
3197 generated_body_closure = OpenAsyncGeneratorFunction(func.token_pos());
3198 } else if (func.IsAsyncGenClosure()) {
3199 // The closure containing the body of an async* function is debuggable.
3200 ASSERT(func.is_debuggable());
3201 OpenAsyncGeneratorClosure();
3181 } 3202 }
3182 3203
3183 BoolScope allow_await(&this->await_is_keyword_, 3204 BoolScope allow_await(&this->await_is_keyword_,
3184 func.IsAsyncOrGenerator() || func.is_generated_body()); 3205 func.IsAsyncOrGenerator() || func.is_generated_body());
3185 intptr_t end_token_pos = 0; 3206 intptr_t end_token_pos = 0;
3186 if (CurrentToken() == Token::kLBRACE) { 3207 if (CurrentToken() == Token::kLBRACE) {
3187 ConsumeToken(); 3208 ConsumeToken();
3188 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { 3209 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) {
3189 const Class& owner = Class::Handle(Z, func.Owner()); 3210 const Class& owner = Class::Handle(Z, func.Owner());
3190 if (!owner.IsObjectClass()) { 3211 if (!owner.IsObjectClass()) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3248 if (func.IsAsyncFunction()) { 3269 if (func.IsAsyncFunction()) {
3249 body = CloseAsyncFunction(generated_body_closure, body); 3270 body = CloseAsyncFunction(generated_body_closure, body);
3250 generated_body_closure.set_end_token_pos(end_token_pos); 3271 generated_body_closure.set_end_token_pos(end_token_pos);
3251 } else if (func.IsAsyncClosure()) { 3272 } else if (func.IsAsyncClosure()) {
3252 body = CloseAsyncClosure(body); 3273 body = CloseAsyncClosure(body);
3253 } else if (func.IsSyncGenerator()) { 3274 } else if (func.IsSyncGenerator()) {
3254 body = CloseSyncGenFunction(generated_body_closure, body); 3275 body = CloseSyncGenFunction(generated_body_closure, body);
3255 generated_body_closure.set_end_token_pos(end_token_pos); 3276 generated_body_closure.set_end_token_pos(end_token_pos);
3256 } else if (func.IsSyncGenClosure()) { 3277 } else if (func.IsSyncGenClosure()) {
3257 body->scope()->RecursivelyCaptureAllVariables(); 3278 body->scope()->RecursivelyCaptureAllVariables();
3279 } else if (func.IsAsyncGenerator()) {
3280 body = CloseAsyncGeneratorFunction(generated_body_closure, body);
3281 generated_body_closure.set_end_token_pos(end_token_pos);
3282 } else if (func.IsAsyncGenClosure()) {
3283 body = CloseAsyncGeneratorClosure(body);
3258 } 3284 }
3259 current_block_->statements->Add(body); 3285 current_block_->statements->Add(body);
3260 innermost_function_ = saved_innermost_function.raw(); 3286 innermost_function_ = saved_innermost_function.raw();
3261 last_used_try_index_ = saved_try_index; 3287 last_used_try_index_ = saved_try_index;
3262 async_temp_scope_ = saved_async_temp_scope; 3288 async_temp_scope_ = saved_async_temp_scope;
3263 return CloseBlock(); 3289 return CloseBlock();
3264 } 3290 }
3265 3291
3266 3292
3267 void Parser::AddEqualityNullCheck() { 3293 void Parser::AddEqualityNullCheck() {
(...skipping 1977 matching lines...) Expand 10 before | Expand all | Expand 10 after
5245 ExpectSemicolon(); // Reports error. 5271 ExpectSemicolon(); // Reports error.
5246 } 5272 }
5247 } 5273 }
5248 } 5274 }
5249 5275
5250 5276
5251 RawFunction::AsyncModifier Parser::ParseFunctionModifier() { 5277 RawFunction::AsyncModifier Parser::ParseFunctionModifier() {
5252 if (CurrentLiteral()->raw() == Symbols::Async().raw()) { 5278 if (CurrentLiteral()->raw() == Symbols::Async().raw()) {
5253 ConsumeToken(); 5279 ConsumeToken();
5254 if (CurrentToken() == Token::kMUL) { 5280 if (CurrentToken() == Token::kMUL) {
5255 ReportError("async* generator functions are not yet supported"); 5281 const bool enableAsyncStar = true;
5282 if (!enableAsyncStar) {
5283 ReportError("async* generator functions are not yet supported");
5284 }
5256 ConsumeToken(); 5285 ConsumeToken();
5257 return RawFunction::kAsyncGen; 5286 return RawFunction::kAsyncGen;
5258 } else { 5287 } else {
5259 return RawFunction::kAsync; 5288 return RawFunction::kAsync;
5260 } 5289 }
5261 } else if ((CurrentLiteral()->raw() == Symbols::Sync().raw()) && 5290 } else if ((CurrentLiteral()->raw() == Symbols::Sync().raw()) &&
5262 (LookaheadToken(1) == Token::kMUL)) { 5291 (LookaheadToken(1) == Token::kMUL)) {
5263 const bool enableSyncStar = true; 5292 const bool enableSyncStar = true;
5264 if (!enableSyncStar) { 5293 if (!enableSyncStar) {
5265 ReportError("sync* generator functions are not yet supported"); 5294 ReportError("sync* generator functions are not yet supported");
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after
5936 5965
5937 void Parser::OpenAsyncClosure() { 5966 void Parser::OpenAsyncClosure() {
5938 TRACE_PARSER("OpenAsyncClosure"); 5967 TRACE_PARSER("OpenAsyncClosure");
5939 5968
5940 async_temp_scope_ = current_block_->scope; 5969 async_temp_scope_ = current_block_->scope;
5941 5970
5942 OpenAsyncTryBlock(); 5971 OpenAsyncTryBlock();
5943 } 5972 }
5944 5973
5945 5974
5946 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { 5975 SequenceNode* Parser::CloseAsyncGeneratorTryBlock(SequenceNode *body) {
5976 TRACE_PARSER("CloseAsyncGeneratorTryBlock");
5977 // The generated try-catch-finally that wraps the async generator function
5978 // body is the outermost try statement.
5979 ASSERT(try_blocks_list_ != NULL);
5980 ASSERT(try_blocks_list_->outer_try_block() == NULL);
5981 // We only get here when parsing an async generator body.
5982 ASSERT(innermost_function().IsAsyncGenClosure());
5983
5984 const intptr_t try_end_pos = innermost_function().end_token_pos();
5985
5986 // The try-block (closure body code) has been parsed. We are now
5987 // generating the code for the catch block.
5947 try_blocks_list_->enter_catch(); 5988 try_blocks_list_->enter_catch();
5989 OpenBlock(); // Catch handler list.
5990 OpenBlock(); // Catch block.
5948 5991
5949 OpenBlock(); 5992 // Add the exception and stack trace parameters to the scope.
5950 OpenBlock();
5951 const AbstractType& dynamic_type = 5993 const AbstractType& dynamic_type =
5952 AbstractType::ZoneHandle(Z, Type::DynamicType()); 5994 AbstractType::ZoneHandle(Z, Type::DynamicType());
5953 CatchParamDesc exception_param; 5995 CatchParamDesc exception_param;
5954 CatchParamDesc stack_trace_param; 5996 CatchParamDesc stack_trace_param;
5955 exception_param.token_pos = Scanner::kNoSourcePos; 5997 exception_param.token_pos = Scanner::kNoSourcePos;
5956 exception_param.type = &dynamic_type; 5998 exception_param.type = &dynamic_type;
5957 exception_param.name = &Symbols::ExceptionParameter(); 5999 exception_param.name = &Symbols::ExceptionParameter();
5958 stack_trace_param.token_pos = Scanner::kNoSourcePos; 6000 stack_trace_param.token_pos = Scanner::kNoSourcePos;
5959 stack_trace_param.type = &dynamic_type; 6001 stack_trace_param.type = &dynamic_type;
5960 stack_trace_param.name = &Symbols::StackTraceParameter(); 6002 stack_trace_param.name = &Symbols::StackTraceParameter();
5961
5962 AddCatchParamsToScope( 6003 AddCatchParamsToScope(
5963 &exception_param, &stack_trace_param, current_block_->scope); 6004 &exception_param, &stack_trace_param, current_block_->scope);
5964 6005
6006 // Generate code to save the exception object and stack trace
6007 // in local variables.
5965 LocalVariable* context_var = current_block_->scope->LookupVariable( 6008 LocalVariable* context_var = current_block_->scope->LookupVariable(
5966 Symbols::SavedTryContextVar(), false); 6009 Symbols::SavedTryContextVar(), false);
5967 ASSERT(context_var != NULL); 6010 ASSERT(context_var != NULL);
5968 6011
5969 LocalVariable* exception_var = current_block_->scope->LookupVariable( 6012 LocalVariable* exception_var = current_block_->scope->LookupVariable(
5970 Symbols::ExceptionVar(), false); 6013 Symbols::ExceptionVar(), false);
5971 ASSERT(exception_var != NULL); 6014 ASSERT(exception_var != NULL);
5972 if (exception_param.var != NULL) { 6015 if (exception_param.var != NULL) {
5973 // Generate code to load the exception object (:exception_var) into 6016 // Generate code to load the exception object (:exception_var) into
5974 // the exception variable specified in this block. 6017 // the exception variable specified in this block.
(...skipping 11 matching lines...) Expand all
5986 // to load the stack trace object (:stack_trace_var) into the stack 6029 // to load the stack trace object (:stack_trace_var) into the stack
5987 // trace variable specified in this block. 6030 // trace variable specified in this block.
5988 current_block_->statements->Add(new(Z) StoreLocalNode( 6031 current_block_->statements->Add(new(Z) StoreLocalNode(
5989 Scanner::kNoSourcePos, 6032 Scanner::kNoSourcePos,
5990 stack_trace_param.var, 6033 stack_trace_param.var,
5991 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); 6034 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
5992 } 6035 }
5993 6036
5994 SaveExceptionAndStacktrace(exception_var, stack_trace_var); 6037 SaveExceptionAndStacktrace(exception_var, stack_trace_var);
5995 6038
6039 // Catch block: add the error to the stream.
6040 // :controller.AddError(:exception, :stack_trace);
6041 // return; // The finally block will close the stream.
6042 LocalVariable* controller =
6043 current_block_->scope->LookupVariable(Symbols::Controller(), false);
6044 ASSERT(controller != NULL);
6045 ArgumentListNode* args =
6046 new(Z) ArgumentListNode(Scanner::kNoSourcePos);
6047 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var));
6048 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var));
6049 current_block_->statements->Add(
6050 new(Z) InstanceCallNode(try_end_pos,
6051 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller),
6052 Symbols::AddError(),
6053 args));
6054 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos);
6055 current_block_->statements->Add(return_node);
6056 AstNode* catch_block = CloseBlock();
6057 current_block_->statements->Add(catch_block);
6058 SequenceNode* catch_handler_list = CloseBlock();
6059
6060 TryBlocks* try_block = PopTryBlock();
6061 ASSERT(try_blocks_list_ == NULL); // We popped the outermost try block.
6062
6063 // Finally block: closing the stream and returning. (Note: the return
6064 // is necessary otherwise the back-end will append a rethrow of the
6065 // current exception.)
6066 // :controller.close();
6067 // return;
6068 // We need to inline this code in all recorded exit points.
6069 intptr_t node_index = 0;
6070 SequenceNode* finally_clause = NULL;
6071 do {
6072 OpenBlock();
6073 ArgumentListNode* no_args =
6074 new(Z) ArgumentListNode(Scanner::kNoSourcePos);
6075 current_block_->statements->Add(
6076 new(Z) InstanceCallNode(try_end_pos,
6077 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller),
6078 Symbols::Close(),
6079 no_args));
6080
6081 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos);
6082 current_block_->statements->Add(return_node);
6083
6084 finally_clause = CloseBlock();
6085 AstNode* node_to_inline = try_block->GetNodeToInlineFinally(node_index);
6086 if (node_to_inline != NULL) {
6087 InlinedFinallyNode* node =
6088 new(Z) InlinedFinallyNode(try_end_pos,
6089 finally_clause,
6090 context_var,
6091 // No outer try statement
6092 CatchClauseNode::kInvalidTryIndex);
6093 finally_clause = NULL;
6094 AddFinallyBlockToNode(node_to_inline, node);
6095 node_index++;
6096 }
6097 } while (finally_clause == NULL);
6098
6099 const GrowableObjectArray& handler_types =
6100 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
6101 handler_types.Add(dynamic_type); // Catch block handles all exceptions.
6102
6103 CatchClauseNode* catch_clause = new(Z) CatchClauseNode(
6104 Scanner::kNoSourcePos,
6105 catch_handler_list,
6106 Array::ZoneHandle(Z, Array::MakeArray(handler_types)),
6107 context_var,
6108 exception_var,
6109 stack_trace_var,
6110 AllocateTryIndex(),
6111 true);
6112
6113 const intptr_t try_index = try_block->try_index();
6114
6115 AstNode* try_catch_node =
6116 new(Z) TryCatchNode(Scanner::kNoSourcePos,
6117 body,
6118 context_var,
6119 catch_clause,
6120 finally_clause,
6121 try_index);
6122 current_block_->statements->Add(try_catch_node);
6123 return CloseBlock();
6124 }
6125
6126
6127 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) {
6128 // This is the outermost try-catch of the function.
5996 ASSERT(try_blocks_list_ != NULL); 6129 ASSERT(try_blocks_list_ != NULL);
5997 ASSERT(innermost_function().IsAsyncClosure() || 6130 ASSERT(try_blocks_list_->outer_try_block() == NULL);
5998 innermost_function().IsAsyncFunction()); 6131 ASSERT(innermost_function().IsAsyncClosure());
5999 if ((try_blocks_list_->outer_try_block() != NULL) && 6132
6000 (try_blocks_list_->outer_try_block()->try_block() 6133 try_blocks_list_->enter_catch();
6001 ->scope->function_level() == 6134
6002 current_block_->scope->function_level())) { 6135 OpenBlock(); // Catch handler list.
6003 // We need to unchain three scope levels: catch clause, catch 6136 OpenBlock(); // Catch block.
6004 // parameters, and the general try block. 6137 const AbstractType& dynamic_type =
6005 current_block_->statements->Add( 6138 AbstractType::ZoneHandle(Z, Type::DynamicType());
6006 AwaitTransformer::RestoreSavedTryContext( 6139 CatchParamDesc exception_param;
6007 Z, 6140 CatchParamDesc stack_trace_param;
6008 current_block_->scope->parent()->parent()->parent(), 6141 exception_param.token_pos = Scanner::kNoSourcePos;
6009 try_blocks_list_->outer_try_block()->try_index())); 6142 exception_param.type = &dynamic_type;
6143 exception_param.name = &Symbols::ExceptionParameter();
6144 stack_trace_param.token_pos = Scanner::kNoSourcePos;
6145 stack_trace_param.type = &dynamic_type;
6146 stack_trace_param.name = &Symbols::StackTraceParameter();
6147
6148 AddCatchParamsToScope(
6149 &exception_param, &stack_trace_param, current_block_->scope);
6150
6151 LocalVariable* context_var = current_block_->scope->LookupVariable(
6152 Symbols::SavedTryContextVar(), false);
6153 ASSERT(context_var != NULL);
6154 LocalVariable* exception_var = current_block_->scope->LookupVariable(
6155 Symbols::ExceptionVar(), false);
6156 if (exception_param.var != NULL) {
6157 // Generate code to load the exception object (:exception_var) into
6158 // the exception variable specified in this block.
6159 ASSERT(exception_var != NULL);
6160 current_block_->statements->Add(new(Z) StoreLocalNode(
6161 Scanner::kNoSourcePos,
6162 exception_param.var,
6163 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
6010 } 6164 }
6011 6165
6012 // Complete the async future with an error. 6166 LocalVariable* stack_trace_var =
6013 // Since we control the catch block there is no need to generate a nested 6167 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false);
6014 // if/then/else. 6168 if (stack_trace_param.var != NULL) {
6169 // A stack trace variable is specified in this block, so generate code
6170 // to load the stack trace object (:stack_trace_var) into the stack
6171 // trace variable specified in this block.
6172 ASSERT(stack_trace_var != NULL);
6173 current_block_->statements->Add(new(Z) StoreLocalNode(
6174 Scanner::kNoSourcePos,
6175 stack_trace_param.var,
6176 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
6177 }
6178
6179 SaveExceptionAndStacktrace(exception_var, stack_trace_var);
6180
6181 // Complete the async future with an error. This catch block executes
6182 // unconditionally, there is no need to generate a type check for.
6015 LocalVariable* async_completer = current_block_->scope->LookupVariable( 6183 LocalVariable* async_completer = current_block_->scope->LookupVariable(
6016 Symbols::AsyncCompleter(), false); 6184 Symbols::AsyncCompleter(), false);
6017 ASSERT(async_completer != NULL); 6185 ASSERT(async_completer != NULL);
6018 ArgumentListNode* completer_args = 6186 ArgumentListNode* completer_args =
6019 new (Z) ArgumentListNode(Scanner::kNoSourcePos); 6187 new (Z) ArgumentListNode(Scanner::kNoSourcePos);
6020 completer_args->Add( 6188 completer_args->Add(
6021 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); 6189 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var));
6022 completer_args->Add( 6190 completer_args->Add(
6023 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); 6191 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var));
6024 current_block_->statements->Add(new (Z) InstanceCallNode( 6192 current_block_->statements->Add(new (Z) InstanceCallNode(
(...skipping 24 matching lines...) Expand all
6049 context_var, 6217 context_var,
6050 exception_var, 6218 exception_var,
6051 stack_trace_var, 6219 stack_trace_var,
6052 CatchClauseNode::kInvalidTryIndex, 6220 CatchClauseNode::kInvalidTryIndex,
6053 true); 6221 true);
6054 AstNode* try_catch_node = new (Z) TryCatchNode( 6222 AstNode* try_catch_node = new (Z) TryCatchNode(
6055 Scanner::kNoSourcePos, 6223 Scanner::kNoSourcePos,
6056 try_block, 6224 try_block,
6057 context_var, 6225 context_var,
6058 catch_clause, 6226 catch_clause,
6059 NULL, 6227 NULL, // No finally clause.
6060 try_index); 6228 try_index);
6061 current_block_->statements->Add(try_catch_node); 6229 current_block_->statements->Add(try_catch_node);
6062 return CloseBlock(); 6230 return CloseBlock();
6063 } 6231 }
6064 6232
6065 6233
6234 // Wrap the body of the async or arync* closure in a try/catch block.
6066 void Parser::OpenAsyncTryBlock() { 6235 void Parser::OpenAsyncTryBlock() {
6067 // Manually wrapping the actual body into a try/catch block. 6236 ASSERT(innermost_function().IsAsyncClosure() ||
6237 innermost_function().IsAsyncGenClosure());
6238
6068 LocalVariable* context_var = 6239 LocalVariable* context_var =
6069 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); 6240 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar());
6070 if (context_var == NULL) { 6241 if (context_var == NULL) {
6071 context_var = new(Z) LocalVariable( 6242 context_var = new(Z) LocalVariable(
6072 TokenPos(), 6243 TokenPos(),
6073 Symbols::SavedTryContextVar(), 6244 Symbols::SavedTryContextVar(),
6074 Type::ZoneHandle(Z, Type::DynamicType())); 6245 Type::ZoneHandle(Z, Type::DynamicType()));
6075 current_block_->scope->AddVariable(context_var); 6246 current_block_->scope->AddVariable(context_var);
6076 } 6247 }
6077 LocalVariable* exception_var = 6248 LocalVariable* exception_var =
(...skipping 12 matching lines...) Expand all
6090 TokenPos(), 6261 TokenPos(),
6091 Symbols::StackTraceVar(), 6262 Symbols::StackTraceVar(),
6092 Type::ZoneHandle(Z, Type::DynamicType())); 6263 Type::ZoneHandle(Z, Type::DynamicType()));
6093 current_block_->scope->AddVariable(stack_trace_var); 6264 current_block_->scope->AddVariable(stack_trace_var);
6094 } 6265 }
6095 6266
6096 SetupSavedExceptionAndStacktrace(); 6267 SetupSavedExceptionAndStacktrace();
6097 6268
6098 // Open the try block. 6269 // Open the try block.
6099 OpenBlock(); 6270 OpenBlock();
6271 // This is the outermost try-catch in the function.
6272 ASSERT(try_blocks_list_ == NULL);
6100 PushTryBlock(current_block_); 6273 PushTryBlock(current_block_);
6101 6274
6102 SetupSavedTryContext(context_var); 6275 SetupSavedTryContext(context_var);
6103 } 6276 }
6104 6277
6105 6278
6106 void Parser::AddSyncGenClosureParameters(ParamList* params) { 6279 void Parser::AddSyncGenClosureParameters(ParamList* params) {
6107 // Create the parameter list for the body closure of a sync generator: 6280 // Create the parameter list for the body closure of a sync generator:
6108 // 1) Implicit closure parameter; 6281 // 1) Implicit closure parameter;
6109 // 2) Iterator 6282 // 2) Iterator
6110 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); 6283 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
6111 // Add implicit closure parameter if not already present. 6284 // Add implicit closure parameter if not already present.
6112 if (params->parameters->length() == 0) { 6285 if (params->parameters->length() == 0) {
6113 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); 6286 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type);
6114 } 6287 }
6115 ParamDesc iterator_param; 6288 ParamDesc iterator_param;
6116 iterator_param.name = &Symbols::IteratorParameter(); 6289 iterator_param.name = &Symbols::IteratorParameter();
6117 iterator_param.type = &dynamic_type; 6290 iterator_param.type = &dynamic_type;
6118 params->parameters->Add(iterator_param); 6291 params->parameters->Add(iterator_param);
6119 params->num_fixed_parameters++; 6292 params->num_fixed_parameters++;
6120 } 6293 }
6121 6294
6122 6295
6296 void Parser::AddAsyncGenClosureParameters(ParamList* params) {
6297 // Create the parameter list for the body closure of an async generator.
6298 // The closure has the same parameters as an asynchronous non-generator.
6299 AddAsyncClosureParameters(params);
6300 }
6301
6302
6123 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) { 6303 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) {
6124 Function& body = Function::Handle(Z); 6304 Function& body = Function::Handle(Z);
6125 String& body_closure_name = String::Handle(Z); 6305 String& body_closure_name = String::Handle(Z);
6126 bool is_new_closure = false; 6306 bool is_new_closure = false;
6127 6307
6128 AddContinuationVariables(); 6308 AddContinuationVariables();
6129 6309
6130 // Check whether a function for the body of this generator 6310 // Check whether a function for the body of this generator
6131 // function has already been created by a previous 6311 // function has already been created by a previous
6132 // compilation. 6312 // compilation.
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
6223 iterable_constructor, 6403 iterable_constructor,
6224 arguments); 6404 arguments);
6225 ReturnNode* return_node = 6405 ReturnNode* return_node =
6226 new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable); 6406 new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable);
6227 current_block_->statements->Add(return_node); 6407 current_block_->statements->Add(return_node);
6228 return CloseBlock(); 6408 return CloseBlock();
6229 } 6409 }
6230 6410
6231 6411
6232 void Parser::AddAsyncClosureParameters(ParamList* params) { 6412 void Parser::AddAsyncClosureParameters(ParamList* params) {
6233 // Async closures have two optional parameters: 6413 // Async closures have three optional parameters:
6234 // * A continuation result. 6414 // * A continuation result.
6235 // * A continuation error. 6415 // * A continuation error.
6236 // * A continuation stack trace. 6416 // * A continuation stack trace.
6237 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); 6417 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
6238 // Add implicit closure parameter if not yet present. 6418 // Add implicit closure parameter if not yet present.
6239 if (params->parameters->length() == 0) { 6419 if (params->parameters->length() == 0) {
6240 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); 6420 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type);
6241 } 6421 }
6242 ParamDesc result_param; 6422 ParamDesc result_param;
6243 result_param.name = &Symbols::AsyncOperationParam(); 6423 result_param.name = &Symbols::AsyncOperationParam();
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
6352 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); 6532 current_block_->scope->CaptureVariable(Symbols::AsyncOperation());
6353 async_op_var->set_is_captured(); 6533 async_op_var->set_is_captured();
6354 LocalVariable* async_completer = new(Z) LocalVariable( 6534 LocalVariable* async_completer = new(Z) LocalVariable(
6355 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); 6535 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type);
6356 current_block_->scope->AddVariable(async_completer); 6536 current_block_->scope->AddVariable(async_completer);
6357 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); 6537 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter());
6358 async_completer->set_is_captured(); 6538 async_completer->set_is_captured();
6359 } 6539 }
6360 6540
6361 6541
6542 void Parser::AddAsyncGeneratorVariables() {
6543 // Add to current block's scope:
6544 // var :controller;
6545 // This variable is used by the nested async generator closure to
6546 // store the StreamController object to which the yielded expressions
6547 // are added.
6548 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
6549 LocalVariable* controller_var = new(Z) LocalVariable(
6550 Scanner::kNoSourcePos, Symbols::Controller(), dynamic_type);
6551 current_block_->scope->AddVariable(controller_var);
6552 current_block_->scope->CaptureVariable(Symbols::Controller());
6553 controller_var->set_is_captured();
6554
6555 LocalVariable* async_op_var = new(Z) LocalVariable(
6556 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type);
6557 current_block_->scope->AddVariable(async_op_var);
6558 current_block_->scope->CaptureVariable(Symbols::AsyncOperation());
6559 async_op_var->set_is_captured();
6560 }
6561
6562
6563 RawFunction* Parser::OpenAsyncGeneratorFunction(intptr_t async_func_pos) {
6564 TRACE_PARSER("OpenAsyncGeneratorFunction");
6565 AddContinuationVariables();
6566 AddAsyncGeneratorVariables();
6567
6568 Function& closure = Function::Handle(Z);
6569 bool is_new_closure = false;
6570
6571 // Check whether a function for the asynchronous function body of
6572 // this async generator has already been created by a previous
6573 // compilation of this function.
6574 const Function& found_func = Function::Handle(
6575 Z, current_class().LookupClosureFunction(async_func_pos));
6576 if (!found_func.IsNull() &&
6577 (found_func.token_pos() == async_func_pos) &&
6578 (found_func.script() == innermost_function().script()) &&
6579 (found_func.parent_function() == innermost_function().raw())) {
6580 ASSERT(found_func.IsAsyncGenClosure());
6581 closure = found_func.raw();
6582 } else {
6583 // Create the closure containing the body of this async generator function.
6584 const String& async_generator_name =
6585 String::Handle(Z, innermost_function().name());
6586 String& closure_name = String::Handle(Z,
6587 String::NewFormatted("<%s_async_gen_body>",
6588 async_generator_name.ToCString()));
6589 closure = Function::NewClosureFunction(
6590 String::Handle(Z, Symbols::New(closure_name)),
6591 innermost_function(),
6592 async_func_pos);
6593 closure.set_is_generated_body(true);
6594 closure.set_result_type(AbstractType::Handle(Type::DynamicType()));
6595 is_new_closure = true;
6596 }
6597
6598 ParamList closure_params;
6599 AddAsyncGenClosureParameters(&closure_params);
6600
6601 if (is_new_closure) {
6602 // Add the parameters to the newly created closure.
6603 AddFormalParamsToFunction(&closure_params, closure);
6604
6605 // Create and set the signature class of the closure.
6606 const String& sig = String::Handle(Z, closure.Signature());
6607 Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
6608 if (sig_cls.IsNull()) {
6609 sig_cls =
6610 Class::NewSignatureClass(sig, closure, script_, closure.token_pos());
6611 library_.AddClass(sig_cls);
6612 }
6613 closure.set_signature_class(sig_cls);
6614 const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
6615 if (!sig_type.IsFinalized()) {
6616 ClassFinalizer::FinalizeType(
6617 sig_cls, sig_type, ClassFinalizer::kCanonicalize);
6618 }
6619 ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved());
6620 ASSERT(closure.NumParameters() == closure_params.parameters->length());
6621 }
6622
6623 OpenFunctionBlock(closure);
6624 AddFormalParamsToScope(&closure_params, current_block_->scope);
6625 OpenBlock();
6626 async_temp_scope_ = current_block_->scope;
6627 return closure.raw();
6628 }
6629
6630
6631 // Generate the Ast nodes for the implicit code of the async* function.
6632 //
6633 // f(...) async* {
6634 // var :controller;
6635 // var :await_jump_var = -1;
6636 // var :await_context_var;
6637 // f_async_body() {
6638 // ... source code of f ...
6639 // }
6640 // :controller = new _AsyncStarStreamController(f_async_body);
6641 // return :controller.stream;
6642 // }
6643 SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure,
6644 SequenceNode* closure_body) {
6645 TRACE_PARSER("CloseAsyncGeneratorFunction");
6646 ASSERT(!closure.IsNull());
6647 ASSERT(closure_body != NULL);
6648
6649 // The block for the async closure body has already been closed. Close the
6650 // corresponding function block.
6651 CloseBlock();
6652
6653 // Make sure the implicit variables of the async generator function
6654 // are captured.
6655 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
6656 closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false);
6657 closure_body->scope()->LookupVariable(Symbols::Controller(), false);
6658
6659 const Class& controller_class = Class::Handle(Z,
6660 Library::LookupCoreClass(Symbols::_AsyncStarStreamController()));
6661 ASSERT(!controller_class.IsNull());
6662 const Function& controller_constructor = Function::ZoneHandle(Z,
6663 controller_class.LookupConstructorAllowPrivate(
6664 Symbols::_AsyncStarStreamControllerConstructor()));
6665
6666 // :await_jump_var = -1;
6667 LocalVariable* jump_var =
6668 current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false);
6669 LiteralNode* init_value =
6670 new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
6671 current_block_->statements->Add(
6672 new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value));
6673
6674 // Add to AST:
6675 // :async_op = <closure>; (containing the original body)
6676 LocalVariable* async_op_var =
6677 current_block_->scope->LookupVariable(Symbols::AsyncOperation(), false);
6678 ClosureNode* cn = new(Z) ClosureNode(
6679 Scanner::kNoSourcePos, closure, NULL, closure_body->scope());
6680 StoreLocalNode* store_async_op = new (Z) StoreLocalNode(
6681 Scanner::kNoSourcePos,
6682 async_op_var,
6683 cn);
6684 current_block_->statements->Add(store_async_op);
6685
6686 // :controller = new _AsyncStarStreamController(body_closure);
6687 ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
6688 ClosureNode* closure_obj = new(Z) ClosureNode(
6689 Scanner::kNoSourcePos, closure, NULL, closure_body->scope());
6690 arguments->Add(closure_obj);
6691 ConstructorCallNode* controller_constructor_call =
6692 new(Z) ConstructorCallNode(Scanner::kNoSourcePos,
6693 TypeArguments::ZoneHandle(Z),
6694 controller_constructor,
6695 arguments);
6696 LocalVariable* controller_var =
6697 current_block_->scope->LookupVariable(Symbols::Controller(), false);
6698 StoreLocalNode* store_controller =
6699 new(Z) StoreLocalNode(Scanner::kNoSourcePos,
6700 controller_var,
6701 controller_constructor_call);
6702 current_block_->statements->Add(store_controller);
6703
6704 // return :controller.stream;
6705 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos,
6706 new(Z) InstanceGetterNode(Scanner::kNoSourcePos,
6707 new(Z) LoadLocalNode(Scanner::kNoSourcePos,
6708 controller_var),
6709 Symbols::Stream()));
6710 current_block_->statements->Add(return_node);
6711 return CloseBlock();
6712 }
6713
6714
6715 void Parser::OpenAsyncGeneratorClosure() {
6716 async_temp_scope_ = current_block_->scope;
6717 OpenAsyncTryBlock();
6718 }
6719
6720
6721 SequenceNode* Parser::CloseAsyncGeneratorClosure(SequenceNode* body) {
6722 // TODO(hausner): Is the temporary expression necessary?
6723 // We need a temporary expression to store intermediate return values.
6724 parsed_function()->EnsureExpressionTemp();
6725
6726 SequenceNode* new_body = CloseAsyncGeneratorTryBlock(body);
6727 ASSERT(new_body != NULL);
6728 ASSERT(new_body->scope() != NULL);
6729
6730 // Implicitly mark those variables below as captured. We currently mark all
6731 // variables of all scopes as captured, but as soon as we do something
6732 // smarter we rely on these internal variables to be available.
6733 new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
6734 new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false);
6735 new_body->scope()->LookupVariable(Symbols::Controller(), false);
6736 new_body->scope()->LookupVariable(Symbols::AsyncOperationParam(), false);
6737 new_body->scope()->LookupVariable(Symbols::AsyncOperationErrorParam(), false);
6738 new_body->scope()->LookupVariable(
6739 Symbols::AsyncOperationStackTraceParam(), false);
6740 new_body->scope()->RecursivelyCaptureAllVariables();
6741 return new_body;
6742 }
6743
6744
6362 SequenceNode* Parser::CloseBlock() { 6745 SequenceNode* Parser::CloseBlock() {
6363 SequenceNode* statements = current_block_->statements; 6746 SequenceNode* statements = current_block_->statements;
6364 if (current_block_->scope != NULL) { 6747 if (current_block_->scope != NULL) {
6365 // Record the begin and end token index of the scope. 6748 // Record the begin and end token index of the scope.
6366 ASSERT(statements != NULL); 6749 ASSERT(statements != NULL);
6367 current_block_->scope->set_begin_token_pos(statements->token_pos()); 6750 current_block_->scope->set_begin_token_pos(statements->token_pos());
6368 current_block_->scope->set_end_token_pos(TokenPos()); 6751 current_block_->scope->set_end_token_pos(TokenPos());
6369 } 6752 }
6370 current_block_ = current_block_->parent; 6753 current_block_ = current_block_->parent;
6371 return statements; 6754 return statements;
(...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after
7797 *outer_try_index = try_blocks_list_->outer_try_block()->try_index(); 8180 *outer_try_index = try_blocks_list_->outer_try_block()->try_index();
7798 } 8181 }
7799 } 8182 }
7800 } 8183 }
7801 } 8184 }
7802 // An async or async* has an implicitly created try-catch around the 8185 // An async or async* has an implicitly created try-catch around the
7803 // function body, so the await or yield inside the async closure should always 8186 // function body, so the await or yield inside the async closure should always
7804 // be created with a try scope. 8187 // be created with a try scope.
7805 ASSERT((*try_scope != NULL) || 8188 ASSERT((*try_scope != NULL) ||
7806 innermost_function().IsAsyncFunction() || 8189 innermost_function().IsAsyncFunction() ||
8190 innermost_function().IsAsyncGenerator() ||
7807 innermost_function().IsSyncGenClosure() || 8191 innermost_function().IsSyncGenClosure() ||
7808 innermost_function().IsSyncGenerator()); 8192 innermost_function().IsSyncGenerator());
7809 } 8193 }
7810 8194
7811 8195
7812 AstNode* Parser::ParseAwaitForStatement(String* label_name) { 8196 AstNode* Parser::ParseAwaitForStatement(String* label_name) {
7813 TRACE_PARSER("ParseAwaitForStatement"); 8197 TRACE_PARSER("ParseAwaitForStatement");
7814 ASSERT(IsAwaitKeyword()); 8198 ASSERT(IsAwaitKeyword());
7815 const intptr_t await_for_pos = TokenPos(); 8199 const intptr_t await_for_pos = TokenPos();
7816 ConsumeToken(); // await. 8200 ConsumeToken(); // await.
7817 ASSERT(CurrentToken() == Token::kFOR); 8201 ASSERT(CurrentToken() == Token::kFOR);
7818 ConsumeToken(); // for. 8202 ConsumeToken(); // for.
7819 ExpectToken(Token::kLPAREN); 8203 ExpectToken(Token::kLPAREN);
7820 8204
7821 if (!innermost_function().IsAsyncFunction() && 8205 if (!innermost_function().IsAsyncFunction() &&
7822 !innermost_function().IsAsyncClosure()) { 8206 !innermost_function().IsAsyncClosure() &&
8207 !innermost_function().IsAsyncGenerator() &&
8208 !innermost_function().IsAsyncGenClosure()) {
7823 ReportError(await_for_pos, 8209 ReportError(await_for_pos,
7824 "await for loop is only allowed in async function"); 8210 "await for loop is only allowed in an asynchronous function");
7825 } 8211 }
7826 8212
7827 // Parse loop variable. 8213 // Parse loop variable.
7828 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); 8214 bool loop_var_is_final = (CurrentToken() == Token::kFINAL);
7829 if (CurrentToken() == Token::kCONST) { 8215 if (CurrentToken() == Token::kCONST) {
7830 ReportError("Loop variable cannot be 'const'"); 8216 ReportError("Loop variable cannot be 'const'");
7831 } 8217 }
7832 bool new_loop_var = false; 8218 bool new_loop_var = false;
7833 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); 8219 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z);
7834 if (LookaheadToken(1) != Token::kIN) { 8220 if (LookaheadToken(1) != Token::kIN) {
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
8259 } 8645 }
8260 } 8646 }
8261 8647
8262 8648
8263 // Populate current scope of the try block with the saved exception and saved 8649 // Populate current scope of the try block with the saved exception and saved
8264 // stack trace. 8650 // stack trace.
8265 void Parser::SetupSavedExceptionAndStacktrace() { 8651 void Parser::SetupSavedExceptionAndStacktrace() {
8266 ASSERT(innermost_function().IsAsyncClosure() || 8652 ASSERT(innermost_function().IsAsyncClosure() ||
8267 innermost_function().IsAsyncFunction() || 8653 innermost_function().IsAsyncFunction() ||
8268 innermost_function().IsSyncGenClosure() || 8654 innermost_function().IsSyncGenClosure() ||
8269 innermost_function().IsSyncGenerator()); 8655 innermost_function().IsSyncGenerator() ||
8656 innermost_function().IsAsyncGenerator() ||
8657 innermost_function().IsAsyncGenClosure());
8270 // Add :saved_exception_var and :saved_stack_trace_var to current scope. 8658 // Add :saved_exception_var and :saved_stack_trace_var to current scope.
8271 // They will automatically get captured. 8659 // They will automatically get captured.
8272 // Parallel try statements share the same set of variables. 8660 // Parallel try statements share the same set of variables.
8273 LocalVariable* saved_exception_var = 8661 LocalVariable* saved_exception_var =
8274 current_block_->scope->LocalLookupVariable(Symbols::SavedExceptionVar()); 8662 current_block_->scope->LocalLookupVariable(Symbols::SavedExceptionVar());
8275 if (saved_exception_var == NULL) { 8663 if (saved_exception_var == NULL) {
8276 saved_exception_var = new (Z) LocalVariable( 8664 saved_exception_var = new (Z) LocalVariable(
8277 Scanner::kNoSourcePos, 8665 Scanner::kNoSourcePos,
8278 Symbols::SavedExceptionVar(), 8666 Symbols::SavedExceptionVar(),
8279 Type::ZoneHandle(Z, Type::DynamicType())); 8667 Type::ZoneHandle(Z, Type::DynamicType()));
(...skipping 13 matching lines...) Expand all
8293 } 8681 }
8294 8682
8295 8683
8296 // Generate code to load the exception object (:exception_var) into 8684 // Generate code to load the exception object (:exception_var) into
8297 // the saved exception variable (:saved_exception_var) used to rethrow. 8685 // the saved exception variable (:saved_exception_var) used to rethrow.
8298 void Parser::SaveExceptionAndStacktrace(LocalVariable* exception_var, 8686 void Parser::SaveExceptionAndStacktrace(LocalVariable* exception_var,
8299 LocalVariable* stack_trace_var) { 8687 LocalVariable* stack_trace_var) {
8300 ASSERT(innermost_function().IsAsyncClosure() || 8688 ASSERT(innermost_function().IsAsyncClosure() ||
8301 innermost_function().IsAsyncFunction() || 8689 innermost_function().IsAsyncFunction() ||
8302 innermost_function().IsSyncGenClosure() || 8690 innermost_function().IsSyncGenClosure() ||
8303 innermost_function().IsSyncGenerator()); 8691 innermost_function().IsSyncGenerator() ||
8692 innermost_function().IsAsyncGenClosure() ||
8693 innermost_function().IsAsyncGenerator());
8304 LocalVariable* saved_exception_var = current_block_->scope->LookupVariable( 8694 LocalVariable* saved_exception_var = current_block_->scope->LookupVariable(
8305 Symbols::SavedExceptionVar(), false); 8695 Symbols::SavedExceptionVar(), false);
8306 ASSERT(saved_exception_var != NULL); 8696 ASSERT(saved_exception_var != NULL);
8307 ASSERT(exception_var != NULL); 8697 ASSERT(exception_var != NULL);
8308 current_block_->statements->Add(new(Z) StoreLocalNode( 8698 current_block_->statements->Add(new(Z) StoreLocalNode(
8309 Scanner::kNoSourcePos, 8699 Scanner::kNoSourcePos,
8310 saved_exception_var, 8700 saved_exception_var,
8311 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); 8701 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
8312 8702
8313 // Generate code to load the stack trace object (:stack_trace_var) into 8703 // Generate code to load the stack trace object (:stack_trace_var) into
(...skipping 13 matching lines...) Expand all
8327 TRACE_PARSER("ParseFinallyBlock"); 8717 TRACE_PARSER("ParseFinallyBlock");
8328 OpenBlock(); 8718 OpenBlock();
8329 ExpectToken(Token::kLBRACE); 8719 ExpectToken(Token::kLBRACE);
8330 8720
8331 // In case of async closures we need to restore the saved try index of an 8721 // In case of async closures we need to restore the saved try index of an
8332 // outer try block (if it exists). The current try block has already been 8722 // outer try block (if it exists). The current try block has already been
8333 // removed from the stack of try blocks. 8723 // removed from the stack of try blocks.
8334 if ((innermost_function().IsAsyncClosure() || 8724 if ((innermost_function().IsAsyncClosure() ||
8335 innermost_function().IsAsyncFunction() || 8725 innermost_function().IsAsyncFunction() ||
8336 innermost_function().IsSyncGenClosure() || 8726 innermost_function().IsSyncGenClosure() ||
8337 innermost_function().IsSyncGenerator()) && 8727 innermost_function().IsSyncGenerator() ||
8728 innermost_function().IsAsyncGenerator() ||
8729 innermost_function().IsAsyncGenClosure()) &&
8338 (try_blocks_list_ != NULL)) { 8730 (try_blocks_list_ != NULL)) {
8339 // We need two unchain two scopes: finally clause, and the try block level. 8731 // We need two unchain two scopes: finally clause, and the try block level.
8340 current_block_->statements->Add( 8732 current_block_->statements->Add(
8341 AwaitTransformer::RestoreSavedTryContext( 8733 AwaitTransformer::RestoreSavedTryContext(
8342 Z, 8734 Z,
8343 current_block_->scope->parent()->parent(), 8735 current_block_->scope->parent()->parent(),
8344 try_blocks_list_->try_index())); 8736 try_blocks_list_->try_index()));
8345 } 8737 }
8346 8738
8347 ParseStatementSequence(); 8739 ParseStatementSequence();
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
8436 } else { 8828 } else {
8437 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); 8829 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType());
8438 } 8830 }
8439 if (CurrentToken() == Token::kCATCH) { 8831 if (CurrentToken() == Token::kCATCH) {
8440 ConsumeToken(); // Consume the 'catch'. 8832 ConsumeToken(); // Consume the 'catch'.
8441 ExpectToken(Token::kLPAREN); 8833 ExpectToken(Token::kLPAREN);
8442 exception_param.token_pos = TokenPos(); 8834 exception_param.token_pos = TokenPos();
8443 exception_param.name = ExpectIdentifier("identifier expected"); 8835 exception_param.name = ExpectIdentifier("identifier expected");
8444 if (CurrentToken() == Token::kCOMMA) { 8836 if (CurrentToken() == Token::kCOMMA) {
8445 ConsumeToken(); 8837 ConsumeToken();
8446 // TODO(hausner): Make implicit type be StackTrace, not dynamic.
8447 stack_trace_param.type = 8838 stack_trace_param.type =
8448 &AbstractType::ZoneHandle(Z, Type::DynamicType()); 8839 &AbstractType::ZoneHandle(Z, Type::DynamicType());
8449 stack_trace_param.token_pos = TokenPos(); 8840 stack_trace_param.token_pos = TokenPos();
8450 stack_trace_param.name = ExpectIdentifier("identifier expected"); 8841 stack_trace_param.name = ExpectIdentifier("identifier expected");
8451 } 8842 }
8452 ExpectToken(Token::kRPAREN); 8843 ExpectToken(Token::kRPAREN);
8453 } 8844 }
8454 8845
8455 // Create a block containing the catch clause parameters and the 8846 // Create a block containing the catch clause parameters and the
8456 // following code: 8847 // following code:
(...skipping 18 matching lines...) Expand all
8475 // A stack trace variable is specified in this block, so generate code 8866 // A stack trace variable is specified in this block, so generate code
8476 // to load the stack trace object (:stack_trace_var) into the stack 8867 // to load the stack trace object (:stack_trace_var) into the stack
8477 // trace variable specified in this block. 8868 // trace variable specified in this block.
8478 *needs_stack_trace = true; 8869 *needs_stack_trace = true;
8479 ASSERT(stack_trace_var != NULL); 8870 ASSERT(stack_trace_var != NULL);
8480 current_block_->statements->Add(new(Z) StoreLocalNode( 8871 current_block_->statements->Add(new(Z) StoreLocalNode(
8481 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( 8872 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode(
8482 catch_pos, stack_trace_var))); 8873 catch_pos, stack_trace_var)));
8483 } 8874 }
8484 8875
8485 // Add nested block with user-defined code. This blocks allows 8876 // Add nested block with user-defined code. This block allows
8486 // declarations in the body to shadow the catch parameters. 8877 // declarations in the body to shadow the catch parameters.
8487 CheckToken(Token::kLBRACE); 8878 CheckToken(Token::kLBRACE);
8488 8879
8489 // In case of async closures we need to restore the saved try index of an 8880 // In case of async closures we need to restore the saved try index of an
8490 // outer try block (if it exists). 8881 // outer try block (if it exists).
8491 ASSERT(try_blocks_list_ != NULL); 8882 ASSERT(try_blocks_list_ != NULL);
8492 if (innermost_function().IsAsyncClosure() || 8883 if (innermost_function().IsAsyncClosure() ||
8493 innermost_function().IsAsyncFunction() || 8884 innermost_function().IsAsyncFunction() ||
8494 innermost_function().IsSyncGenClosure() || 8885 innermost_function().IsSyncGenClosure() ||
8495 innermost_function().IsSyncGenerator()) { 8886 innermost_function().IsSyncGenerator() ||
8887 innermost_function().IsAsyncGenerator() ||
8888 innermost_function().IsAsyncGenClosure()) {
8496 if ((try_blocks_list_->outer_try_block() != NULL) && 8889 if ((try_blocks_list_->outer_try_block() != NULL) &&
8497 (try_blocks_list_->outer_try_block()->try_block() 8890 (try_blocks_list_->outer_try_block()->try_block()
8498 ->scope->function_level() == 8891 ->scope->function_level() ==
8499 current_block_->scope->function_level())) { 8892 current_block_->scope->function_level())) {
8500 // We need to unchain three scope levels: catch clause, catch 8893 // We need to unchain three scope levels: catch clause, catch
8501 // parameters, and the general try block. 8894 // parameters, and the general try block.
8502 current_block_->statements->Add( 8895 current_block_->statements->Add(
8503 AwaitTransformer::RestoreSavedTryContext( 8896 AwaitTransformer::RestoreSavedTryContext(
8504 Z, 8897 Z,
8505 current_block_->scope->parent()->parent()->parent(), 8898 current_block_->scope->parent()->parent()->parent(),
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
8609 // necessary in this case either, because no await could have been executed 9002 // necessary in this case either, because no await could have been executed
8610 // between the setup of :saved_try_context_var in the try clause and here 9003 // between the setup of :saved_try_context_var in the try clause and here
8611 // (it is the execution of an await that clears all stack-based variables). 9004 // (it is the execution of an await that clears all stack-based variables).
8612 9005
8613 // In case of async closures we need to restore the saved try index of an 9006 // In case of async closures we need to restore the saved try index of an
8614 // outer try block (if it exists). 9007 // outer try block (if it exists).
8615 ASSERT(try_blocks_list_ != NULL); 9008 ASSERT(try_blocks_list_ != NULL);
8616 if (innermost_function().IsAsyncClosure() || 9009 if (innermost_function().IsAsyncClosure() ||
8617 innermost_function().IsAsyncFunction() || 9010 innermost_function().IsAsyncFunction() ||
8618 innermost_function().IsSyncGenClosure() || 9011 innermost_function().IsSyncGenClosure() ||
8619 innermost_function().IsSyncGenerator()) { 9012 innermost_function().IsSyncGenerator() ||
9013 innermost_function().IsAsyncGenerator() ||
9014 innermost_function().IsAsyncGenClosure()) {
8620 if ((try_blocks_list_->outer_try_block() != NULL) && 9015 if ((try_blocks_list_->outer_try_block() != NULL) &&
8621 (try_blocks_list_->outer_try_block()->try_block() 9016 (try_blocks_list_->outer_try_block()->try_block()
8622 ->scope->function_level() == 9017 ->scope->function_level() ==
8623 current_block_->scope->function_level())) { 9018 current_block_->scope->function_level())) {
8624 // We need to unchain three scope levels (from the catch block and not 9019 // We need to unchain three scope levels (from the catch block and not
8625 // from the current block): catch clause, catch 9020 // from the current block): catch clause, catch
8626 // parameters, and the general try block. 9021 // parameters, and the general try block.
8627 current_block_->statements->Add( 9022 current_block_->statements->Add(
8628 AwaitTransformer::RestoreSavedTryContext( 9023 AwaitTransformer::RestoreSavedTryContext(
8629 Z, 9024 Z,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
8705 stack_trace_var = new(Z) LocalVariable( 9100 stack_trace_var = new(Z) LocalVariable(
8706 TokenPos(), 9101 TokenPos(),
8707 Symbols::StackTraceVar(), 9102 Symbols::StackTraceVar(),
8708 Type::ZoneHandle(Z, Type::DynamicType())); 9103 Type::ZoneHandle(Z, Type::DynamicType()));
8709 current_block_->scope->AddVariable(stack_trace_var); 9104 current_block_->scope->AddVariable(stack_trace_var);
8710 } 9105 }
8711 9106
8712 if (innermost_function().IsAsyncClosure() || 9107 if (innermost_function().IsAsyncClosure() ||
8713 innermost_function().IsAsyncFunction() || 9108 innermost_function().IsAsyncFunction() ||
8714 innermost_function().IsSyncGenClosure() || 9109 innermost_function().IsSyncGenClosure() ||
8715 innermost_function().IsSyncGenerator()) { 9110 innermost_function().IsSyncGenerator() ||
9111 innermost_function().IsAsyncGenClosure() ||
9112 innermost_function().IsAsyncGenerator()) {
8716 SetupSavedExceptionAndStacktrace(); 9113 SetupSavedExceptionAndStacktrace();
8717 } 9114 }
8718 9115
8719 const intptr_t try_pos = TokenPos(); 9116 const intptr_t try_pos = TokenPos();
8720 ConsumeToken(); // Consume the 'try'. 9117 ConsumeToken(); // Consume the 'try'.
8721 9118
8722 SourceLabel* try_label = NULL; 9119 SourceLabel* try_label = NULL;
8723 if (label_name != NULL) { 9120 if (label_name != NULL) {
8724 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); 9121 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement);
8725 OpenBlock(); 9122 OpenBlock();
8726 current_block_->scope->AddLabel(try_label); 9123 current_block_->scope->AddLabel(try_label);
8727 } 9124 }
8728 9125
8729 // Now parse the 'try' block. 9126 // Now parse the 'try' block.
8730 OpenBlock(); 9127 OpenBlock();
8731 PushTryBlock(current_block_); 9128 PushTryBlock(current_block_);
8732 ExpectToken(Token::kLBRACE); 9129 ExpectToken(Token::kLBRACE);
8733 9130
8734 if (innermost_function().IsAsyncClosure() || 9131 if (innermost_function().IsAsyncClosure() ||
8735 innermost_function().IsAsyncFunction() || 9132 innermost_function().IsAsyncFunction() ||
8736 innermost_function().IsSyncGenClosure() || 9133 innermost_function().IsSyncGenClosure() ||
8737 innermost_function().IsSyncGenerator()) { 9134 innermost_function().IsSyncGenerator() ||
9135 innermost_function().IsAsyncGenerator() ||
9136 innermost_function().IsAsyncGenClosure()) {
8738 SetupSavedTryContext(context_var); 9137 SetupSavedTryContext(context_var);
8739 } 9138 }
8740 9139
8741 ParseStatementSequence(); 9140 ParseStatementSequence();
8742 ExpectToken(Token::kRBRACE); 9141 ExpectToken(Token::kRBRACE);
8743 SequenceNode* try_block = CloseBlock(); 9142 SequenceNode* try_block = CloseBlock();
8744 9143
8745 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && 9144 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") &&
8746 (CurrentToken() != Token::kFINALLY)) { 9145 (CurrentToken() != Token::kFINALLY)) {
8747 ReportError("catch or finally clause expected"); 9146 ReportError("catch or finally clause expected");
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
8871 ReportError(jump_pos, "'break' to case clause label is illegal"); 9270 ReportError(jump_pos, "'break' to case clause label is illegal");
8872 } 9271 }
8873 if (target->FunctionLevel() != current_block_->scope->function_level()) { 9272 if (target->FunctionLevel() != current_block_->scope->function_level()) {
8874 ReportError(jump_pos, "'%s' target must be in same function context", 9273 ReportError(jump_pos, "'%s' target must be in same function context",
8875 Token::Str(jump_kind)); 9274 Token::Str(jump_kind));
8876 } 9275 }
8877 return new(Z) JumpNode(jump_pos, jump_kind, target); 9276 return new(Z) JumpNode(jump_pos, jump_kind, target);
8878 } 9277 }
8879 9278
8880 9279
9280 AstNode* Parser::ParseYieldStatement() {
9281 bool is_yield_each = false;
9282 const intptr_t yield_pos = TokenPos();
9283 ConsumeToken(); // yield reserved word.
9284 ASSERT(innermost_function().IsGenerator() ||
9285 innermost_function().IsSyncGenClosure() ||
9286 innermost_function().IsAsyncGenerator() ||
9287 innermost_function().IsAsyncGenClosure());
9288 if (CurrentToken() == Token::kMUL) {
9289 is_yield_each = true;
9290 ConsumeToken();
9291 }
9292 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
9293
9294 LetNode* yield = new(Z) LetNode(yield_pos);
9295 if (innermost_function().IsSyncGenerator() ||
9296 innermost_function().IsSyncGenClosure()) {
9297 // Yield statement in sync* function.
9298
9299 LocalVariable* iterator_param =
9300 LookupLocalScope(Symbols::IteratorParameter());
9301 ASSERT(iterator_param != NULL);
9302 // Generate :iterator.current = expr;
9303 AstNode* iterator =
9304 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param);
9305 AstNode* store_current =
9306 new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
9307 iterator,
9308 String::ZoneHandle(Symbols::Current().raw()),
9309 expr);
9310 yield->AddNode(store_current);
9311 if (is_yield_each) {
9312 // Generate :iterator.isYieldEach = true;
9313 AstNode* set_is_yield_each =
9314 new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
9315 iterator,
9316 String::ZoneHandle(Symbols::IsYieldEach().raw()),
9317 new(Z) LiteralNode(TokenPos(), Bool::True()));
9318 yield->AddNode(set_is_yield_each);
9319 }
9320 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
9321 await_marker->set_scope(current_block_->scope);
9322 yield->AddNode(await_marker);
9323 // Return true to indicate that a value has been generated.
9324 ReturnNode* return_true = new(Z) ReturnNode(yield_pos,
9325 new(Z) LiteralNode(TokenPos(), Bool::True()));
9326 return_true->set_return_type(ReturnNode::kContinuationTarget);
9327 yield->AddNode(return_true);
9328
9329 // If this expression is part of a try block, also append the code for
9330 // restoring the saved try context that lives on the stack and possibly the
9331 // saved try context of the outer try block.
9332 LocalScope* try_scope;
9333 int16_t try_index;
9334 LocalScope* outer_try_scope;
9335 int16_t outer_try_index;
9336 CheckAsyncOpInTryBlock(&try_scope, &try_index,
9337 &outer_try_scope, &outer_try_index);
9338 if (try_scope != NULL) {
9339 yield->AddNode(
9340 AwaitTransformer::RestoreSavedTryContext(Z,
9341 try_scope,
9342 try_index));
9343 if (outer_try_scope != NULL) {
9344 yield->AddNode(
9345 AwaitTransformer::RestoreSavedTryContext(Z,
9346 outer_try_scope,
9347 outer_try_index));
9348 }
9349 } else {
9350 ASSERT(outer_try_scope == NULL);
9351 }
9352 } else {
9353 // yield statement in async* function.
9354 ASSERT(innermost_function().IsAsyncGenerator() ||
9355 innermost_function().IsAsyncGenClosure());
9356
9357 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller());
9358 ASSERT(controller_var != NULL);
9359 // :controller.add[Stream](expr);
9360 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos);
9361 add_args->Add(expr);
9362 AstNode* add_call =
9363 new(Z) InstanceCallNode(yield_pos,
9364 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var),
9365 is_yield_each ? Symbols::AddStream() : Symbols::add(),
9366 add_args);
9367
9368
9369 // if (:controller.add[Stream](expr)) {
9370 // return;
9371 // }
9372 // await_marker;
9373 // continuation_return;
9374 // restore saved_try_context
9375
9376 SequenceNode* true_branch =
9377 new(Z) SequenceNode(Scanner::kNoSourcePos, current_block_->scope);
9378 AstNode* return_from_generator = new(Z) ReturnNode(yield_pos);
9379 true_branch->Add(return_from_generator);
9380 AddNodeForFinallyInlining(return_from_generator);
9381 AstNode* if_is_cancelled =
9382 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL);
9383 yield->AddNode(if_is_cancelled);
9384
9385 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
9386 await_marker->set_scope(current_block_->scope);
9387 yield->AddNode(await_marker);
9388 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos);
9389 continuation_return->set_return_type(ReturnNode::kContinuationTarget);
9390 yield->AddNode(continuation_return);
9391
9392 // If this expression is part of a try block, also append the code for
9393 // restoring the saved try context that lives on the stack and possibly the
9394 // saved try context of the outer try block.
9395 LocalScope* try_scope;
9396 int16_t try_index;
9397 LocalScope* outer_try_scope;
9398 int16_t outer_try_index;
9399 CheckAsyncOpInTryBlock(&try_scope, &try_index,
9400 &outer_try_scope, &outer_try_index);
9401 if (try_scope != NULL) {
9402 yield->AddNode(
9403 AwaitTransformer::RestoreSavedTryContext(Z,
9404 try_scope,
9405 try_index));
9406 if (outer_try_scope != NULL) {
9407 yield->AddNode(
9408 AwaitTransformer::RestoreSavedTryContext(Z,
9409 outer_try_scope,
9410 outer_try_index));
9411 }
9412 } else {
9413 ASSERT(outer_try_scope == NULL);
9414 }
9415 }
9416 return yield;
9417 }
9418
9419
8881 AstNode* Parser::ParseStatement() { 9420 AstNode* Parser::ParseStatement() {
8882 TRACE_PARSER("ParseStatement"); 9421 TRACE_PARSER("ParseStatement");
8883 AstNode* statement = NULL; 9422 AstNode* statement = NULL;
8884 intptr_t label_pos = 0; 9423 intptr_t label_pos = 0;
8885 String* label_name = NULL; 9424 String* label_name = NULL;
8886 if (IsIdentifier()) { 9425 if (IsIdentifier()) {
8887 if (LookaheadToken(1) == Token::kCOLON) { 9426 if (LookaheadToken(1) == Token::kCOLON) {
8888 // Statement starts with a label. 9427 // Statement starts with a label.
8889 label_name = CurrentLiteral(); 9428 label_name = CurrentLiteral();
8890 label_pos = TokenPos(); 9429 label_pos = TokenPos();
(...skipping 19 matching lines...) Expand all
8910 statement = ParseTryStatement(label_name); 9449 statement = ParseTryStatement(label_name);
8911 } else if (token == Token::kRETURN) { 9450 } else if (token == Token::kRETURN) {
8912 const intptr_t return_pos = TokenPos(); 9451 const intptr_t return_pos = TokenPos();
8913 ConsumeToken(); 9452 ConsumeToken();
8914 if (CurrentToken() != Token::kSEMICOLON) { 9453 if (CurrentToken() != Token::kSEMICOLON) {
8915 const intptr_t expr_pos = TokenPos(); 9454 const intptr_t expr_pos = TokenPos();
8916 if (current_function().IsGenerativeConstructor() && 9455 if (current_function().IsGenerativeConstructor() &&
8917 (current_block_->scope->function_level() == 0)) { 9456 (current_block_->scope->function_level() == 0)) {
8918 ReportError(expr_pos, 9457 ReportError(expr_pos,
8919 "return of a value is not allowed in constructors"); 9458 "return of a value is not allowed in constructors");
8920 } else if (current_function().IsGenerator()) { 9459 } else if (current_function().IsGeneratorClosure() &&
9460 (current_block_->scope->function_level() == 0)) {
8921 ReportError(expr_pos, "generator functions may not return a value"); 9461 ReportError(expr_pos, "generator functions may not return a value");
8922 } 9462 }
8923 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); 9463 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
8924 statement = new(Z) ReturnNode(statement_pos, expr); 9464 statement = new(Z) ReturnNode(statement_pos, expr);
8925 } else { 9465 } else {
8926 if (current_function().IsSyncGenClosure() && 9466 if (current_function().IsSyncGenClosure() &&
8927 (current_block_->scope->function_level() == 0)) { 9467 (current_block_->scope->function_level() == 0)) {
8928 // In a synchronous generator, return without an expression 9468 // In a synchronous generator, return without an expression
8929 // returns false, signaling that the iterator terminates and 9469 // returns false, signaling that the iterator terminates and
8930 // did not yield a value. 9470 // did not yield a value.
8931 statement = new(Z) ReturnNode(statement_pos, 9471 statement = new(Z) ReturnNode(statement_pos,
8932 new(Z) LiteralNode(return_pos, Bool::False())); 9472 new(Z) LiteralNode(return_pos, Bool::False()));
8933 } else { 9473 } else {
8934 statement = new(Z) ReturnNode(statement_pos); 9474 statement = new(Z) ReturnNode(statement_pos);
8935 } 9475 }
8936 } 9476 }
8937 AddNodeForFinallyInlining(statement); 9477 AddNodeForFinallyInlining(statement);
8938 ExpectSemicolon(); 9478 ExpectSemicolon();
8939 } else if (IsYieldKeyword()) { 9479 } else if (IsYieldKeyword()) {
8940 bool is_yield_each = false; 9480 statement = ParseYieldStatement();
8941 ConsumeToken();
8942 ASSERT(innermost_function().IsGenerator() ||
8943 innermost_function().IsSyncGenClosure());
8944 if (CurrentToken() == Token::kMUL) {
8945 is_yield_each = true;
8946 ConsumeToken();
8947 }
8948 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
8949 LocalVariable* iterator_param =
8950 LookupLocalScope(Symbols::IteratorParameter());
8951 ASSERT(iterator_param != NULL);
8952 // Generate :iterator.current = expr;
8953 AstNode* iterator =
8954 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param);
8955 AstNode* store_current =
8956 new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
8957 iterator,
8958 String::ZoneHandle(Symbols::Current().raw()),
8959 expr);
8960 LetNode* yield = new(Z) LetNode(statement_pos);
8961 yield->AddNode(store_current);
8962 if (is_yield_each) {
8963 // Generate :iterator.isYieldEach = true;
8964 AstNode* set_is_yield_each =
8965 new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
8966 iterator,
8967 String::ZoneHandle(Symbols::IsYieldEach().raw()),
8968 new(Z) LiteralNode(TokenPos(), Bool::True()));
8969 yield->AddNode(set_is_yield_each);
8970 }
8971 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
8972 await_marker->set_scope(current_block_->scope);
8973 yield->AddNode(await_marker);
8974 // Return true to indicate that a value has been generated.
8975 ReturnNode* return_true = new(Z) ReturnNode(statement_pos,
8976 new(Z) LiteralNode(TokenPos(), Bool::True()));
8977 return_true->set_return_type(ReturnNode::kContinuationTarget);
8978 yield->AddNode(return_true);
8979
8980 // If this expression is part of a try block, also append the code for
8981 // restoring the saved try context that lives on the stack and possibly the
8982 // saved try context of the outer try block.
8983 LocalScope* try_scope;
8984 int16_t try_index;
8985 LocalScope* outer_try_scope;
8986 int16_t outer_try_index;
8987 CheckAsyncOpInTryBlock(&try_scope, &try_index,
8988 &outer_try_scope, &outer_try_index);
8989 if (try_scope != NULL) {
8990 yield->AddNode(
8991 AwaitTransformer::RestoreSavedTryContext(Z,
8992 try_scope,
8993 try_index));
8994 if (outer_try_scope != NULL) {
8995 yield->AddNode(
8996 AwaitTransformer::RestoreSavedTryContext(Z,
8997 outer_try_scope,
8998 outer_try_index));
8999 }
9000 } else {
9001 ASSERT(outer_try_scope == NULL);
9002 }
9003
9004 statement = yield;
9005 ExpectSemicolon(); 9481 ExpectSemicolon();
9006 } else if (token == Token::kIF) { 9482 } else if (token == Token::kIF) {
9007 statement = ParseIfStatement(label_name); 9483 statement = ParseIfStatement(label_name);
9008 } else if (token == Token::kASSERT) { 9484 } else if (token == Token::kASSERT) {
9009 statement = ParseAssertStatement(); 9485 statement = ParseAssertStatement();
9010 ExpectSemicolon(); 9486 ExpectSemicolon();
9011 } else if (IsVariableDeclaration()) { 9487 } else if (IsVariableDeclaration()) {
9012 statement = ParseVariableDeclarationList(); 9488 statement = ParseVariableDeclarationList();
9013 ExpectSemicolon(); 9489 ExpectSemicolon();
9014 } else if (IsFunctionDeclaration()) { 9490 } else if (IsFunctionDeclaration()) {
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after
9855 } 10331 }
9856 10332
9857 10333
9858 AstNode* Parser::ParseUnaryExpr() { 10334 AstNode* Parser::ParseUnaryExpr() {
9859 TRACE_PARSER("ParseUnaryExpr"); 10335 TRACE_PARSER("ParseUnaryExpr");
9860 AstNode* expr = NULL; 10336 AstNode* expr = NULL;
9861 const intptr_t op_pos = TokenPos(); 10337 const intptr_t op_pos = TokenPos();
9862 if (IsAwaitKeyword()) { 10338 if (IsAwaitKeyword()) {
9863 TRACE_PARSER("ParseAwaitExpr"); 10339 TRACE_PARSER("ParseAwaitExpr");
9864 if (!innermost_function().IsAsyncFunction() && 10340 if (!innermost_function().IsAsyncFunction() &&
9865 !innermost_function().IsAsyncClosure()) { 10341 !innermost_function().IsAsyncClosure() &&
9866 ReportError("await operator is only allowed in async function"); 10342 !innermost_function().IsAsyncGenerator() &&
10343 !innermost_function().IsAsyncGenClosure()) {
10344 ReportError("await operator is only allowed in an asynchronous function");
9867 } 10345 }
9868 ConsumeToken(); 10346 ConsumeToken();
9869 parsed_function()->record_await(); 10347 parsed_function()->record_await();
9870 10348
9871 LocalScope* try_scope; 10349 LocalScope* try_scope;
9872 int16_t try_index; 10350 int16_t try_index;
9873 LocalScope* outer_try_scope; 10351 LocalScope* outer_try_scope;
9874 int16_t outer_try_index; 10352 int16_t outer_try_index;
9875 CheckAsyncOpInTryBlock(&try_scope, &try_index, 10353 CheckAsyncOpInTryBlock(&try_scope, &try_index,
9876 &outer_try_scope, &outer_try_index); 10354 &outer_try_scope, &outer_try_index);
(...skipping 2829 matching lines...) Expand 10 before | Expand all | Expand 10 after
12706 void Parser::SkipQualIdent() { 13184 void Parser::SkipQualIdent() {
12707 ASSERT(IsIdentifier()); 13185 ASSERT(IsIdentifier());
12708 ConsumeToken(); 13186 ConsumeToken();
12709 if (CurrentToken() == Token::kPERIOD) { 13187 if (CurrentToken() == Token::kPERIOD) {
12710 ConsumeToken(); // Consume the kPERIOD token. 13188 ConsumeToken(); // Consume the kPERIOD token.
12711 ExpectIdentifier("identifier expected after '.'"); 13189 ExpectIdentifier("identifier expected after '.'");
12712 } 13190 }
12713 } 13191 }
12714 13192
12715 } // namespace dart 13193 } // namespace dart
OLDNEW
« runtime/vm/object.h ('K') | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698