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

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 3097 matching lines...) Expand 10 before | Expand all | Expand 10 after
3108 AddFormalParamsToScope(&params, current_block_->scope); 3108 AddFormalParamsToScope(&params, current_block_->scope);
3109 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); 3109 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
3110 if (!Function::Handle(func.parent_function()).IsGetterFunction()) { 3110 if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
3111 // Parse and discard any formal parameters. They are accessed as 3111 // Parse and discard any formal parameters. They are accessed as
3112 // context variables. 3112 // context variables.
3113 ParamList discarded_params; 3113 ParamList discarded_params;
3114 ParseFormalParameterList(allow_explicit_default_values, 3114 ParseFormalParameterList(allow_explicit_default_values,
3115 false, 3115 false,
3116 &discarded_params); 3116 &discarded_params);
3117 } 3117 }
3118 } else if (func.IsAsyncGenClosure()) {
3119 AddAsyncGenClosureParameters(&params);
3120 SetupDefaultsForOptionalParams(&params, default_parameter_values);
3121 AddFormalParamsToScope(&params, current_block_->scope);
3122 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
3123 ASSERT(func.NumParameters() == params.parameters->length());
3124 if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
3125 // Parse and discard any formal parameters. They are accessed as
3126 // context variables.
3127 ParamList discarded_params;
3128 ParseFormalParameterList(allow_explicit_default_values,
3129 false,
3130 &discarded_params);
3131 }
3118 } else { 3132 } else {
3119 ParseFormalParameterList(allow_explicit_default_values, false, &params); 3133 ParseFormalParameterList(allow_explicit_default_values, false, &params);
3120 3134
3121 // The number of parameters and their type are not yet set in local 3135 // The number of parameters and their type are not yet set in local
3122 // functions, since they are not 'top-level' parsed. 3136 // functions, since they are not 'top-level' parsed.
3123 if (func.IsLocalFunction()) { 3137 if (func.IsLocalFunction()) {
3124 AddFormalParamsToFunction(&params, func); 3138 AddFormalParamsToFunction(&params, func);
3125 } 3139 }
3126 SetupDefaultsForOptionalParams(&params, default_parameter_values); 3140 SetupDefaultsForOptionalParams(&params, default_parameter_values);
3127 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); 3141 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
3176 ASSERT(func.is_debuggable()); 3190 ASSERT(func.is_debuggable());
3177 OpenAsyncClosure(); 3191 OpenAsyncClosure();
3178 } else if (func.IsSyncGenerator()) { 3192 } else if (func.IsSyncGenerator()) {
3179 // The code of a sync generator is synthesized. Disable debugging. 3193 // The code of a sync generator is synthesized. Disable debugging.
3180 func.set_is_debuggable(false); 3194 func.set_is_debuggable(false);
3181 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos()); 3195 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos());
3182 } else if (func.IsSyncGenClosure()) { 3196 } else if (func.IsSyncGenClosure()) {
3183 // The closure containing the body of a sync generator is debuggable. 3197 // The closure containing the body of a sync generator is debuggable.
3184 ASSERT(func.is_debuggable()); 3198 ASSERT(func.is_debuggable());
3185 async_temp_scope_ = current_block_->scope; 3199 async_temp_scope_ = current_block_->scope;
3200 } else if (func.IsAsyncGenerator()) {
3201 func.set_is_debuggable(false);
3202 generated_body_closure = OpenAsyncGeneratorFunction(func.token_pos());
3203 } else if (func.IsAsyncGenClosure()) {
3204 // The closure containing the body of an async* function is debuggable.
3205 ASSERT(func.is_debuggable());
3206 OpenAsyncGeneratorClosure();
3186 } 3207 }
3187 3208
3188 BoolScope allow_await(&this->await_is_keyword_, 3209 BoolScope allow_await(&this->await_is_keyword_,
3189 func.IsAsyncOrGenerator() || func.is_generated_body()); 3210 func.IsAsyncOrGenerator() || func.is_generated_body());
3190 intptr_t end_token_pos = 0; 3211 intptr_t end_token_pos = 0;
3191 if (CurrentToken() == Token::kLBRACE) { 3212 if (CurrentToken() == Token::kLBRACE) {
3192 ConsumeToken(); 3213 ConsumeToken();
3193 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { 3214 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) {
3194 const Class& owner = Class::Handle(Z, func.Owner()); 3215 const Class& owner = Class::Handle(Z, func.Owner());
3195 if (!owner.IsObjectClass()) { 3216 if (!owner.IsObjectClass()) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3253 if (func.IsAsyncFunction()) { 3274 if (func.IsAsyncFunction()) {
3254 body = CloseAsyncFunction(generated_body_closure, body); 3275 body = CloseAsyncFunction(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.IsAsyncClosure()) { 3277 } else if (func.IsAsyncClosure()) {
3257 body = CloseAsyncClosure(body); 3278 body = CloseAsyncClosure(body);
3258 } else if (func.IsSyncGenerator()) { 3279 } else if (func.IsSyncGenerator()) {
3259 body = CloseSyncGenFunction(generated_body_closure, body); 3280 body = CloseSyncGenFunction(generated_body_closure, body);
3260 generated_body_closure.set_end_token_pos(end_token_pos); 3281 generated_body_closure.set_end_token_pos(end_token_pos);
3261 } else if (func.IsSyncGenClosure()) { 3282 } else if (func.IsSyncGenClosure()) {
3262 body->scope()->RecursivelyCaptureAllVariables(); 3283 body->scope()->RecursivelyCaptureAllVariables();
3284 } else if (func.IsAsyncGenerator()) {
3285 body = CloseAsyncGeneratorFunction(generated_body_closure, body);
3286 generated_body_closure.set_end_token_pos(end_token_pos);
3287 } else if (func.IsAsyncGenClosure()) {
3288 body = CloseAsyncGeneratorClosure(body);
3263 } 3289 }
3264 current_block_->statements->Add(body); 3290 current_block_->statements->Add(body);
3265 innermost_function_ = saved_innermost_function.raw(); 3291 innermost_function_ = saved_innermost_function.raw();
3266 last_used_try_index_ = saved_try_index; 3292 last_used_try_index_ = saved_try_index;
3267 async_temp_scope_ = saved_async_temp_scope; 3293 async_temp_scope_ = saved_async_temp_scope;
3268 parsed_function()->set_saved_try_ctx(saved_saved_try_ctx); 3294 parsed_function()->set_saved_try_ctx(saved_saved_try_ctx);
3269 parsed_function()->set_async_saved_try_ctx_name( 3295 parsed_function()->set_async_saved_try_ctx_name(
3270 saved_async_saved_try_ctx_name); 3296 saved_async_saved_try_ctx_name);
3271 return CloseBlock(); 3297 return CloseBlock();
3272 } 3298 }
(...skipping 1980 matching lines...) Expand 10 before | Expand all | Expand 10 after
5253 ExpectSemicolon(); // Reports error. 5279 ExpectSemicolon(); // Reports error.
5254 } 5280 }
5255 } 5281 }
5256 } 5282 }
5257 5283
5258 5284
5259 RawFunction::AsyncModifier Parser::ParseFunctionModifier() { 5285 RawFunction::AsyncModifier Parser::ParseFunctionModifier() {
5260 if (CurrentLiteral()->raw() == Symbols::Async().raw()) { 5286 if (CurrentLiteral()->raw() == Symbols::Async().raw()) {
5261 ConsumeToken(); 5287 ConsumeToken();
5262 if (CurrentToken() == Token::kMUL) { 5288 if (CurrentToken() == Token::kMUL) {
5263 ReportError("async* generator functions are not yet supported"); 5289 const bool enableAsyncStar = true;
5290 if (!enableAsyncStar) {
5291 ReportError("async* generator functions are not yet supported");
5292 }
5264 ConsumeToken(); 5293 ConsumeToken();
5265 return RawFunction::kAsyncGen; 5294 return RawFunction::kAsyncGen;
5266 } else { 5295 } else {
5267 return RawFunction::kAsync; 5296 return RawFunction::kAsync;
5268 } 5297 }
5269 } else if ((CurrentLiteral()->raw() == Symbols::Sync().raw()) && 5298 } else if ((CurrentLiteral()->raw() == Symbols::Sync().raw()) &&
5270 (LookaheadToken(1) == Token::kMUL)) { 5299 (LookaheadToken(1) == Token::kMUL)) {
5271 const bool enableSyncStar = true; 5300 const bool enableSyncStar = true;
5272 if (!enableSyncStar) { 5301 if (!enableSyncStar) {
5273 ReportError("sync* generator functions are not yet supported"); 5302 ReportError("sync* generator functions are not yet supported");
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after
5944 5973
5945 void Parser::OpenAsyncClosure() { 5974 void Parser::OpenAsyncClosure() {
5946 TRACE_PARSER("OpenAsyncClosure"); 5975 TRACE_PARSER("OpenAsyncClosure");
5947 5976
5948 async_temp_scope_ = current_block_->scope; 5977 async_temp_scope_ = current_block_->scope;
5949 5978
5950 OpenAsyncTryBlock(); 5979 OpenAsyncTryBlock();
5951 } 5980 }
5952 5981
5953 5982
5954 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { 5983 SequenceNode* Parser::CloseAsyncGeneratorTryBlock(SequenceNode *body) {
5984 TRACE_PARSER("CloseAsyncGeneratorTryBlock");
5985 // The generated try-catch-finally that wraps the async generator function
5986 // body is the outermost try statement.
5987 ASSERT(try_blocks_list_ != NULL);
5988 ASSERT(try_blocks_list_->outer_try_block() == NULL);
5989 // We only get here when parsing an async generator body.
5990 ASSERT(innermost_function().IsAsyncGenClosure());
5991
5992 // The try-block (closure body code) has been parsed. We are now
5993 // generating the code for the catch block.
5955 try_blocks_list_->enter_catch(); 5994 try_blocks_list_->enter_catch();
5995 OpenBlock(); // Catch handler list.
5996 OpenBlock(); // Catch block.
5956 5997
5957 OpenBlock(); 5998 // Add the exception and stack trace parameters to the scope.
5958 OpenBlock();
5959 const AbstractType& dynamic_type = 5999 const AbstractType& dynamic_type =
5960 AbstractType::ZoneHandle(Z, Type::DynamicType()); 6000 AbstractType::ZoneHandle(Z, Type::DynamicType());
5961 CatchParamDesc exception_param; 6001 CatchParamDesc exception_param;
5962 CatchParamDesc stack_trace_param; 6002 CatchParamDesc stack_trace_param;
5963 exception_param.token_pos = Scanner::kNoSourcePos; 6003 exception_param.token_pos = Scanner::kNoSourcePos;
5964 exception_param.type = &dynamic_type; 6004 exception_param.type = &dynamic_type;
5965 exception_param.name = &Symbols::ExceptionParameter(); 6005 exception_param.name = &Symbols::ExceptionParameter();
5966 stack_trace_param.token_pos = Scanner::kNoSourcePos; 6006 stack_trace_param.token_pos = Scanner::kNoSourcePos;
5967 stack_trace_param.type = &dynamic_type; 6007 stack_trace_param.type = &dynamic_type;
5968 stack_trace_param.name = &Symbols::StackTraceParameter(); 6008 stack_trace_param.name = &Symbols::StackTraceParameter();
5969
5970 AddCatchParamsToScope( 6009 AddCatchParamsToScope(
5971 &exception_param, &stack_trace_param, current_block_->scope); 6010 &exception_param, &stack_trace_param, current_block_->scope);
5972 6011
6012 // Generate code to save the exception object and stack trace
6013 // in local variables.
5973 LocalVariable* context_var = current_block_->scope->LookupVariable( 6014 LocalVariable* context_var = current_block_->scope->LookupVariable(
5974 Symbols::SavedTryContextVar(), false); 6015 Symbols::SavedTryContextVar(), false);
5975 ASSERT(context_var != NULL); 6016 ASSERT(context_var != NULL);
5976 LocalVariable* exception_var = current_block_->scope->LookupVariable( 6017 LocalVariable* exception_var = current_block_->scope->LookupVariable(
5977 Symbols::ExceptionVar(), false); 6018 Symbols::ExceptionVar(), false);
5978 if (exception_param.var != NULL) { 6019 if (exception_param.var != NULL) {
5979 // Generate code to load the exception object (:exception_var) into 6020 // Generate code to load the exception object (:exception_var) into
5980 // the exception variable specified in this block. 6021 // the exception variable specified in this block.
5981 ASSERT(exception_var != NULL); 6022 ASSERT(exception_var != NULL);
5982 current_block_->statements->Add(new(Z) StoreLocalNode( 6023 current_block_->statements->Add(new(Z) StoreLocalNode(
5983 Scanner::kNoSourcePos, 6024 Scanner::kNoSourcePos,
5984 exception_param.var, 6025 exception_param.var,
5985 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); 6026 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
5986 } 6027 }
5987 LocalVariable* stack_trace_var = 6028 LocalVariable* stack_trace_var =
5988 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false); 6029 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false);
5989 if (stack_trace_param.var != NULL) { 6030 if (stack_trace_param.var != NULL) {
5990 // A stack trace variable is specified in this block, so generate code 6031 // A stack trace variable is specified in this block, so generate code
5991 // to load the stack trace object (:stack_trace_var) into the stack 6032 // to load the stack trace object (:stack_trace_var) into the stack
5992 // trace variable specified in this block. 6033 // trace variable specified in this block.
5993 ASSERT(stack_trace_var != NULL); 6034 ASSERT(stack_trace_var != NULL);
5994 current_block_->statements->Add(new(Z) StoreLocalNode( 6035 current_block_->statements->Add(new(Z) StoreLocalNode(
5995 Scanner::kNoSourcePos, 6036 Scanner::kNoSourcePos,
5996 stack_trace_param.var, 6037 stack_trace_param.var,
5997 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); 6038 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
5998 } 6039 }
5999 6040
6041 parsed_function()->reset_saved_try_ctx_vars();
6042
6043 // Catch block: add the error to the stream.
6044 // :controller.AddError(:exception, :stack_trace);
6045 // return; // The finally block will close the stream.
6046 LocalVariable* controller =
6047 current_block_->scope->LookupVariable(Symbols::Controller(), false);
6048 ASSERT(controller != NULL);
6049 ArgumentListNode* args =
6050 new(Z) ArgumentListNode(Scanner::kNoSourcePos);
6051 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var));
6052 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var));
6053 current_block_->statements->Add(
6054 new(Z) InstanceCallNode(TokenPos(),
6055 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller),
6056 Symbols::AddError(),
6057 args));
6058 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos);
6059 current_block_->statements->Add(return_node);
6060 AstNode* catch_block = CloseBlock();
6061 current_block_->statements->Add(catch_block);
6062 SequenceNode* catch_handler_list = CloseBlock();
6063
6064 TryBlocks* try_block = PopTryBlock();
6065 ASSERT(try_blocks_list_ == NULL); // We popped the outermost try block.
6066
6067 // Finally block: closing the stream and returning. (Note: the return
6068 // is necessary otherwise the back-end will append a rethrow of the
6069 // current exception.)
6070 // :controller.close();
6071 // return;
6072 // We need to inline this code in all recorded exit points.
6073 intptr_t node_index = 0;
6074 SequenceNode* finally_clause = NULL;
6075 do {
6076 OpenBlock();
6077 ArgumentListNode* no_args =
6078 new(Z) ArgumentListNode(Scanner::kNoSourcePos);
6079 current_block_->statements->Add(
6080 new(Z) InstanceCallNode(TokenPos(),
6081 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller),
6082 Symbols::Close(),
6083 no_args));
6084
6085 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos);
6086 current_block_->statements->Add(return_node);
6087
6088 finally_clause = CloseBlock();
6089 AstNode* node_to_inline = try_block->GetNodeToInlineFinally(node_index);
6090 if (node_to_inline != NULL) {
6091 InlinedFinallyNode* node =
6092 new(Z) InlinedFinallyNode(TokenPos(),
6093 finally_clause,
6094 context_var,
6095 // No outer try statement
6096 CatchClauseNode::kInvalidTryIndex);
6097 finally_clause = NULL;
6098 AddFinallyBlockToNode(node_to_inline, node);
6099 node_index++;
6100 }
6101 } while (finally_clause == NULL);
6102
6103 const GrowableObjectArray& handler_types =
6104 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
6105 handler_types.Add(dynamic_type); // Catch block handles all exceptions.
6106
6107 CatchClauseNode* catch_clause = new(Z) CatchClauseNode(
6108 Scanner::kNoSourcePos,
6109 catch_handler_list,
6110 Array::ZoneHandle(Z, Array::MakeArray(handler_types)),
6111 context_var,
6112 exception_var,
6113 stack_trace_var,
6114 AllocateTryIndex(),
6115 true);
6116
6117 const intptr_t try_index = try_block->try_index();
6118
6119 AstNode* try_catch_node =
6120 new(Z) TryCatchNode(Scanner::kNoSourcePos,
6121 body,
6122 context_var,
6123 catch_clause,
6124 finally_clause,
6125 try_index);
6126 current_block_->statements->Add(try_catch_node);
6127 return CloseBlock();
6128 }
6129
6130
6131 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) {
6132 // This is the outermost try-catch of the function.
6000 ASSERT(try_blocks_list_ != NULL); 6133 ASSERT(try_blocks_list_ != NULL);
6001 ASSERT(innermost_function().IsAsyncClosure() || 6134 ASSERT(try_blocks_list_->outer_try_block() == NULL);
6002 innermost_function().IsAsyncFunction()); 6135 ASSERT(innermost_function().IsAsyncClosure());
6003 if ((try_blocks_list_->outer_try_block() != NULL) && 6136
6004 (try_blocks_list_->outer_try_block()->try_block() 6137 try_blocks_list_->enter_catch();
6005 ->scope->function_level() == 6138
6006 current_block_->scope->function_level())) { 6139 OpenBlock(); // Catch handler list.
6007 // We need to unchain three scope levels: catch clause, catch 6140 OpenBlock(); // Catch block.
6008 // parameters, and the general try block. 6141 const AbstractType& dynamic_type =
6009 RestoreSavedTryContext( 6142 AbstractType::ZoneHandle(Z, Type::DynamicType());
6010 current_block_->scope->parent()->parent()->parent(), 6143 CatchParamDesc exception_param;
6011 try_blocks_list_->outer_try_block()->try_index(), 6144 CatchParamDesc stack_trace_param;
6012 current_block_->statements); 6145 exception_param.token_pos = Scanner::kNoSourcePos;
6013 } else { 6146 exception_param.type = &dynamic_type;
6014 parsed_function()->reset_saved_try_ctx_vars(); 6147 exception_param.name = &Symbols::ExceptionParameter();
6148 stack_trace_param.token_pos = Scanner::kNoSourcePos;
6149 stack_trace_param.type = &dynamic_type;
6150 stack_trace_param.name = &Symbols::StackTraceParameter();
6151
6152 AddCatchParamsToScope(
6153 &exception_param, &stack_trace_param, current_block_->scope);
6154
6155 LocalVariable* context_var = current_block_->scope->LookupVariable(
6156 Symbols::SavedTryContextVar(), false);
6157 ASSERT(context_var != NULL);
6158 LocalVariable* exception_var = current_block_->scope->LookupVariable(
6159 Symbols::ExceptionVar(), false);
6160 if (exception_param.var != NULL) {
6161 // Generate code to load the exception object (:exception_var) into
6162 // the exception variable specified in this block.
6163 ASSERT(exception_var != NULL);
6164 current_block_->statements->Add(new(Z) StoreLocalNode(
6165 Scanner::kNoSourcePos,
6166 exception_param.var,
6167 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
6168 }
6169 LocalVariable* stack_trace_var =
6170 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false);
6171 if (stack_trace_param.var != NULL) {
6172 // A stack trace variable is specified in this block, so generate code
6173 // to load the stack trace object (:stack_trace_var) into the stack
6174 // trace variable specified in this block.
6175 ASSERT(stack_trace_var != NULL);
6176 current_block_->statements->Add(new(Z) StoreLocalNode(
6177 Scanner::kNoSourcePos,
6178 stack_trace_param.var,
6179 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
6015 } 6180 }
6016 6181
6017 // Complete the async future with an error. 6182 parsed_function()->reset_saved_try_ctx_vars();
6018 // Since we control the catch block there is no need to generate a nested 6183
6019 // if/then/else. 6184 // Complete the async future with an error. This catch block executes
6185 // unconditionally, there is no need to generate a type check for.
6020 LocalVariable* async_completer = current_block_->scope->LookupVariable( 6186 LocalVariable* async_completer = current_block_->scope->LookupVariable(
6021 Symbols::AsyncCompleter(), false); 6187 Symbols::AsyncCompleter(), false);
6022 ASSERT(async_completer != NULL); 6188 ASSERT(async_completer != NULL);
6023 ArgumentListNode* completer_args = 6189 ArgumentListNode* completer_args =
6024 new (Z) ArgumentListNode(Scanner::kNoSourcePos); 6190 new (Z) ArgumentListNode(Scanner::kNoSourcePos);
6025 completer_args->Add( 6191 completer_args->Add(
6026 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); 6192 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var));
6027 completer_args->Add( 6193 completer_args->Add(
6028 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); 6194 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var));
6029 current_block_->statements->Add(new (Z) InstanceCallNode( 6195 current_block_->statements->Add(new (Z) InstanceCallNode(
(...skipping 24 matching lines...) Expand all
6054 context_var, 6220 context_var,
6055 exception_var, 6221 exception_var,
6056 stack_trace_var, 6222 stack_trace_var,
6057 CatchClauseNode::kInvalidTryIndex, 6223 CatchClauseNode::kInvalidTryIndex,
6058 true); 6224 true);
6059 AstNode* try_catch_node = new (Z) TryCatchNode( 6225 AstNode* try_catch_node = new (Z) TryCatchNode(
6060 Scanner::kNoSourcePos, 6226 Scanner::kNoSourcePos,
6061 try_block, 6227 try_block,
6062 context_var, 6228 context_var,
6063 catch_clause, 6229 catch_clause,
6064 NULL, 6230 NULL, // No finally clause.
6065 try_index); 6231 try_index);
6066 current_block_->statements->Add(try_catch_node); 6232 current_block_->statements->Add(try_catch_node);
6067 return CloseBlock(); 6233 return CloseBlock();
6068 } 6234 }
6069 6235
6070 6236
6237 // Wrap the body of the async or arync* closure in a try/catch block.
6071 void Parser::OpenAsyncTryBlock() { 6238 void Parser::OpenAsyncTryBlock() {
6072 // Manually wrapping the actual body into a try/catch block. 6239 ASSERT(innermost_function().IsAsyncClosure() ||
6240 innermost_function().IsAsyncGenClosure());
6241
6073 LocalVariable* context_var = 6242 LocalVariable* context_var =
6074 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); 6243 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar());
6075 if (context_var == NULL) { 6244 if (context_var == NULL) {
6076 context_var = new(Z) LocalVariable( 6245 context_var = new(Z) LocalVariable(
6077 TokenPos(), 6246 TokenPos(),
6078 Symbols::SavedTryContextVar(), 6247 Symbols::SavedTryContextVar(),
6079 Type::ZoneHandle(Z, Type::DynamicType())); 6248 Type::ZoneHandle(Z, Type::DynamicType()));
6080 current_block_->scope->AddVariable(context_var); 6249 current_block_->scope->AddVariable(context_var);
6081 } 6250 }
6082 LocalVariable* exception_var = 6251 LocalVariable* exception_var =
(...skipping 10 matching lines...) Expand all
6093 if (stack_trace_var == NULL) { 6262 if (stack_trace_var == NULL) {
6094 stack_trace_var = new(Z) LocalVariable( 6263 stack_trace_var = new(Z) LocalVariable(
6095 TokenPos(), 6264 TokenPos(),
6096 Symbols::StackTraceVar(), 6265 Symbols::StackTraceVar(),
6097 Type::ZoneHandle(Z, Type::DynamicType())); 6266 Type::ZoneHandle(Z, Type::DynamicType()));
6098 current_block_->scope->AddVariable(stack_trace_var); 6267 current_block_->scope->AddVariable(stack_trace_var);
6099 } 6268 }
6100 6269
6101 // Open the try block. 6270 // Open the try block.
6102 OpenBlock(); 6271 OpenBlock();
6272 // This is the outermost try-catch in the function.
6273 ASSERT(try_blocks_list_ == NULL);
6103 PushTryBlock(current_block_); 6274 PushTryBlock(current_block_);
6104 6275
6105 if (innermost_function().IsAsyncClosure() || 6276 SetupSavedTryContext(context_var);
6106 innermost_function().IsAsyncFunction() ||
6107 innermost_function().IsSyncGenClosure() ||
6108 innermost_function().IsSyncGenerator()) {
6109 SetupSavedTryContext(context_var);
6110 }
6111 } 6277 }
6112 6278
6113 6279
6114 void Parser::AddSyncGenClosureParameters(ParamList* params) { 6280 void Parser::AddSyncGenClosureParameters(ParamList* params) {
6115 // Create the parameter list for the body closure of a sync generator: 6281 // Create the parameter list for the body closure of a sync generator:
6116 // 1) Implicit closure parameter; 6282 // 1) Implicit closure parameter;
6117 // 2) Iterator 6283 // 2) Iterator
6118 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); 6284 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
6119 // Add implicit closure parameter if not already present. 6285 // Add implicit closure parameter if not already present.
6120 if (params->parameters->length() == 0) { 6286 if (params->parameters->length() == 0) {
6121 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); 6287 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type);
6122 } 6288 }
6123 ParamDesc iterator_param; 6289 ParamDesc iterator_param;
6124 iterator_param.name = &Symbols::IteratorParameter(); 6290 iterator_param.name = &Symbols::IteratorParameter();
6125 iterator_param.type = &dynamic_type; 6291 iterator_param.type = &dynamic_type;
6126 params->parameters->Add(iterator_param); 6292 params->parameters->Add(iterator_param);
6127 params->num_fixed_parameters++; 6293 params->num_fixed_parameters++;
6128 } 6294 }
6129 6295
6130 6296
6297 void Parser::AddAsyncGenClosureParameters(ParamList* params) {
6298 // Create the parameter list for the body closure of an async generator:
6299 // The closure has the same parameters as an asynchronous non-generator.
6300 AddAsyncClosureParameters(params);
6301 }
6302
6303
6131 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) { 6304 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) {
6132 Function& body = Function::Handle(Z); 6305 Function& body = Function::Handle(Z);
6133 String& body_closure_name = String::Handle(Z); 6306 String& body_closure_name = String::Handle(Z);
6134 bool is_new_closure = false; 6307 bool is_new_closure = false;
6135 6308
6136 AddContinuationVariables(); 6309 AddContinuationVariables();
6137 6310
6138 // Check whether a function for the body of this generator 6311 // Check whether a function for the body of this generator
6139 // function has already been created by a previous 6312 // function has already been created by a previous
6140 // compilation. 6313 // compilation.
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
6231 iterable_constructor, 6404 iterable_constructor,
6232 arguments); 6405 arguments);
6233 ReturnNode* return_node = 6406 ReturnNode* return_node =
6234 new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable); 6407 new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable);
6235 current_block_->statements->Add(return_node); 6408 current_block_->statements->Add(return_node);
6236 return CloseBlock(); 6409 return CloseBlock();
6237 } 6410 }
6238 6411
6239 6412
6240 void Parser::AddAsyncClosureParameters(ParamList* params) { 6413 void Parser::AddAsyncClosureParameters(ParamList* params) {
6241 // Async closures have two optional parameters: 6414 // Async closures have three optional parameters:
6242 // * A continuation result. 6415 // * A continuation result.
6243 // * A continuation error. 6416 // * A continuation error.
6244 // * A continuation stack trace. 6417 // * A continuation stack trace.
6245 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); 6418 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
6246 // Add implicit closure parameter if not yet present. 6419 // Add implicit closure parameter if not yet present.
6247 if (params->parameters->length() == 0) { 6420 if (params->parameters->length() == 0) {
6248 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); 6421 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type);
6249 } 6422 }
6250 ParamDesc result_param; 6423 ParamDesc result_param;
6251 result_param.name = &Symbols::AsyncOperationParam(); 6424 result_param.name = &Symbols::AsyncOperationParam();
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
6360 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); 6533 current_block_->scope->CaptureVariable(Symbols::AsyncOperation());
6361 async_op_var->set_is_captured(); 6534 async_op_var->set_is_captured();
6362 LocalVariable* async_completer = new(Z) LocalVariable( 6535 LocalVariable* async_completer = new(Z) LocalVariable(
6363 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); 6536 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type);
6364 current_block_->scope->AddVariable(async_completer); 6537 current_block_->scope->AddVariable(async_completer);
6365 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); 6538 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter());
6366 async_completer->set_is_captured(); 6539 async_completer->set_is_captured();
6367 } 6540 }
6368 6541
6369 6542
6543 void Parser::AddAsyncGeneratorVariables() {
6544 // Add to current block's scope:
6545 // var :controller;
6546 // This variable is used by the nested async generator closure to
6547 // store the StreamController object to which the yielded expressions
6548 // are added.
6549 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
6550 LocalVariable* controller_var = new(Z) LocalVariable(
6551 Scanner::kNoSourcePos, Symbols::Controller(), dynamic_type);
6552 current_block_->scope->AddVariable(controller_var);
6553 current_block_->scope->CaptureVariable(Symbols::Controller());
6554 controller_var->set_is_captured();
6555
6556 LocalVariable* async_op_var = new(Z) LocalVariable(
6557 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type);
6558 current_block_->scope->AddVariable(async_op_var);
6559 current_block_->scope->CaptureVariable(Symbols::AsyncOperation());
6560 async_op_var->set_is_captured();
6561 }
6562
6563
6564 RawFunction* Parser::OpenAsyncGeneratorFunction(intptr_t async_func_pos) {
6565 TRACE_PARSER("OpenAsyncGeneratorFunction");
6566 AddContinuationVariables();
6567 AddAsyncGeneratorVariables();
6568
6569 Function& closure = Function::Handle(Z);
6570 bool is_new_closure = false;
6571
6572 // Check whether a function for the asynchronous function body of
6573 // this async generator has already been created by a previous
6574 // compilation of this function.
6575 const Function& found_func = Function::Handle(
6576 Z, current_class().LookupClosureFunction(async_func_pos));
6577 if (!found_func.IsNull() &&
6578 (found_func.token_pos() == async_func_pos) &&
6579 (found_func.script() == innermost_function().script()) &&
6580 (found_func.parent_function() == innermost_function().raw())) {
6581 ASSERT(found_func.IsAsyncGenClosure());
6582 closure = found_func.raw();
6583 } else {
6584 // Create the closure containing the body of this async generator function.
6585 const String& async_generator_name =
6586 String::Handle(Z, innermost_function().name());
6587 String& closure_name = String::Handle(Z,
6588 String::NewFormatted("<%s_async_gen_body>",
6589 async_generator_name.ToCString()));
6590 closure = Function::NewClosureFunction(
6591 String::Handle(Z, Symbols::New(closure_name)),
6592 innermost_function(),
6593 async_func_pos);
6594 closure.set_is_generated_body(true);
6595 closure.set_result_type(AbstractType::Handle(Type::DynamicType()));
6596 is_new_closure = true;
6597 }
6598
6599 ParamList closure_params;
6600 AddAsyncGenClosureParameters(&closure_params);
6601
6602 if (is_new_closure) {
6603 // Add the parameters to the newly created closure.
6604 AddFormalParamsToFunction(&closure_params, closure);
6605
6606 // Create and set the signature class of the closure.
6607 const String& sig = String::Handle(Z, closure.Signature());
6608 Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
6609 if (sig_cls.IsNull()) {
6610 sig_cls =
6611 Class::NewSignatureClass(sig, closure, script_, closure.token_pos());
6612 library_.AddClass(sig_cls);
6613 }
6614 closure.set_signature_class(sig_cls);
6615 const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
6616 if (!sig_type.IsFinalized()) {
6617 ClassFinalizer::FinalizeType(
6618 sig_cls, sig_type, ClassFinalizer::kCanonicalize);
6619 }
6620 ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved());
6621 ASSERT(closure.NumParameters() == closure_params.parameters->length());
6622 }
6623
6624 OpenFunctionBlock(closure);
6625 AddFormalParamsToScope(&closure_params, current_block_->scope);
6626 OpenBlock();
6627 async_temp_scope_ = current_block_->scope;
6628 return closure.raw();
6629 }
6630
6631
6632 // Generate the Ast nodes for the implicit code of the async* function.
6633 //
6634 // f(...) async* {
6635 // var :controller;
6636 // var :await_jump_var = -1;
6637 // var :await_context_var;
6638 // f_async_body() {
6639 // ... source code of f ...
6640 // }
6641 // :controller = new _AsyncStarStreamController(f_async_body);
6642 // return :controller.stream;
6643 // }
6644 SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure,
6645 SequenceNode* closure_body) {
6646 TRACE_PARSER("CloseAsyncGeneratorFunction");
6647 ASSERT(!closure.IsNull());
6648 ASSERT(closure_body != NULL);
6649
6650 // The block for the async closure body has already been closed. Close the
6651 // corresponding function block.
6652 CloseBlock();
6653
6654 // Make sure the implicit variables of the async generator function
6655 // are captured.
6656 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
6657 closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false);
6658 closure_body->scope()->LookupVariable(Symbols::Controller(), false);
6659
6660 const Class& controller_class = Class::Handle(Z,
6661 Library::LookupCoreClass(Symbols::_AsyncStarStreamController()));
6662 ASSERT(!controller_class.IsNull());
6663 const Function& controller_constructor = Function::ZoneHandle(Z,
6664 controller_class.LookupConstructorAllowPrivate(
6665 Symbols::_AsyncStarStreamControllerConstructor()));
6666
6667 // :await_jump_var = -1;
6668 LocalVariable* jump_var =
6669 current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false);
6670 LiteralNode* init_value =
6671 new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
6672 current_block_->statements->Add(
6673 new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value));
6674
6675 // Add to AST:
6676 // :async_op = <closure>; (containing the original body)
6677 LocalVariable* async_op_var =
6678 current_block_->scope->LookupVariable(Symbols::AsyncOperation(), false);
6679 ClosureNode* cn = new(Z) ClosureNode(
6680 Scanner::kNoSourcePos, closure, NULL, closure_body->scope());
6681 StoreLocalNode* store_async_op = new (Z) StoreLocalNode(
6682 Scanner::kNoSourcePos,
6683 async_op_var,
6684 cn);
6685 current_block_->statements->Add(store_async_op);
6686
6687 // :controller = new _AsyncStarStreamController(body_closure);
6688 ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
6689 ClosureNode* closure_obj = new(Z) ClosureNode(
6690 Scanner::kNoSourcePos, closure, NULL, closure_body->scope());
6691 arguments->Add(closure_obj);
6692 ConstructorCallNode* controller_constructor_call =
6693 new(Z) ConstructorCallNode(Scanner::kNoSourcePos,
6694 TypeArguments::ZoneHandle(Z),
6695 controller_constructor,
6696 arguments);
6697 LocalVariable* controller_var =
6698 current_block_->scope->LookupVariable(Symbols::Controller(), false);
6699 StoreLocalNode* store_controller =
6700 new(Z) StoreLocalNode(Scanner::kNoSourcePos,
6701 controller_var,
6702 controller_constructor_call);
6703 current_block_->statements->Add(store_controller);
6704
6705 // return :controller.stream;
6706 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos,
6707 new(Z) InstanceGetterNode(Scanner::kNoSourcePos,
6708 new(Z) LoadLocalNode(Scanner::kNoSourcePos,
6709 controller_var),
6710 Symbols::Stream()));
6711 current_block_->statements->Add(return_node);
6712 return CloseBlock();
6713 }
6714
6715
6716 void Parser::OpenAsyncGeneratorClosure() {
6717 async_temp_scope_ = current_block_->scope;
6718 OpenAsyncTryBlock();
6719 }
6720
6721
6722 SequenceNode* Parser::CloseAsyncGeneratorClosure(SequenceNode* body) {
6723 // TODO(hausner): Is the temporary expression necessary?
6724 // We need a temporary expression to store intermediate return values.
6725 parsed_function()->EnsureExpressionTemp();
6726
6727 SequenceNode* new_body = CloseAsyncGeneratorTryBlock(body);
6728 ASSERT(new_body != NULL);
6729 ASSERT(new_body->scope() != NULL);
6730
6731 // Implicitly mark those variables below as captured. We currently mark all
6732 // variables of all scopes as captured, but as soon as we do something
6733 // smarter we rely on these internal variables to be available.
6734 new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
6735 new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false);
6736 new_body->scope()->LookupVariable(Symbols::Controller(), false);
6737 new_body->scope()->LookupVariable(Symbols::AsyncOperationParam(), false);
6738 new_body->scope()->LookupVariable(Symbols::AsyncOperationErrorParam(), false);
6739 new_body->scope()->LookupVariable(
6740 Symbols::AsyncOperationStackTraceParam(), false);
6741 new_body->scope()->RecursivelyCaptureAllVariables();
6742 return new_body;
6743 }
6744
6745
6370 SequenceNode* Parser::CloseBlock() { 6746 SequenceNode* Parser::CloseBlock() {
6371 SequenceNode* statements = current_block_->statements; 6747 SequenceNode* statements = current_block_->statements;
6372 if (current_block_->scope != NULL) { 6748 if (current_block_->scope != NULL) {
6373 // Record the begin and end token index of the scope. 6749 // Record the begin and end token index of the scope.
6374 ASSERT(statements != NULL); 6750 ASSERT(statements != NULL);
6375 current_block_->scope->set_begin_token_pos(statements->token_pos()); 6751 current_block_->scope->set_begin_token_pos(statements->token_pos());
6376 current_block_->scope->set_end_token_pos(TokenPos()); 6752 current_block_->scope->set_end_token_pos(TokenPos());
6377 } 6753 }
6378 current_block_ = current_block_->parent; 6754 current_block_ = current_block_->parent;
6379 return statements; 6755 return statements;
(...skipping 1395 matching lines...) Expand 10 before | Expand all | Expand 10 after
7775 AstNode* Parser::ParseAwaitForStatement(String* label_name) { 8151 AstNode* Parser::ParseAwaitForStatement(String* label_name) {
7776 TRACE_PARSER("ParseAwaitForStatement"); 8152 TRACE_PARSER("ParseAwaitForStatement");
7777 ASSERT(IsAwaitKeyword()); 8153 ASSERT(IsAwaitKeyword());
7778 const intptr_t await_for_pos = TokenPos(); 8154 const intptr_t await_for_pos = TokenPos();
7779 ConsumeToken(); // await. 8155 ConsumeToken(); // await.
7780 ASSERT(CurrentToken() == Token::kFOR); 8156 ASSERT(CurrentToken() == Token::kFOR);
7781 ConsumeToken(); // for. 8157 ConsumeToken(); // for.
7782 ExpectToken(Token::kLPAREN); 8158 ExpectToken(Token::kLPAREN);
7783 8159
7784 if (!innermost_function().IsAsyncFunction() && 8160 if (!innermost_function().IsAsyncFunction() &&
7785 !innermost_function().IsAsyncClosure()) { 8161 !innermost_function().IsAsyncClosure() &&
8162 !innermost_function().IsAsyncGenerator() &&
8163 !innermost_function().IsAsyncGenClosure()) {
7786 ReportError(await_for_pos, 8164 ReportError(await_for_pos,
7787 "await for loop is only allowed in async function"); 8165 "await for loop is only allowed in an asynchronous function");
7788 } 8166 }
7789 8167
7790 // Parse loop variable. 8168 // Parse loop variable.
7791 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); 8169 bool loop_var_is_final = (CurrentToken() == Token::kFINAL);
7792 if (CurrentToken() == Token::kCONST) { 8170 if (CurrentToken() == Token::kCONST) {
7793 ReportError("Loop variable cannot be 'const'"); 8171 ReportError("Loop variable cannot be 'const'");
7794 } 8172 }
7795 bool new_loop_var = false; 8173 bool new_loop_var = false;
7796 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); 8174 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z);
7797 if (LookaheadToken(1) != Token::kIN) { 8175 if (LookaheadToken(1) != Token::kIN) {
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
8216 TRACE_PARSER("ParseFinallyBlock"); 8594 TRACE_PARSER("ParseFinallyBlock");
8217 OpenBlock(); 8595 OpenBlock();
8218 ExpectToken(Token::kLBRACE); 8596 ExpectToken(Token::kLBRACE);
8219 8597
8220 // In case of async closures we need to restore the saved try index of an 8598 // In case of async closures we need to restore the saved try index of an
8221 // outer try block (if it exists). The current try block has already been 8599 // outer try block (if it exists). The current try block has already been
8222 // removed from the stack of try blocks. 8600 // removed from the stack of try blocks.
8223 if ((innermost_function().IsAsyncClosure() || 8601 if ((innermost_function().IsAsyncClosure() ||
8224 innermost_function().IsAsyncFunction() || 8602 innermost_function().IsAsyncFunction() ||
8225 innermost_function().IsSyncGenClosure() || 8603 innermost_function().IsSyncGenClosure() ||
8226 innermost_function().IsSyncGenerator()) && 8604 innermost_function().IsSyncGenerator() ||
8605 innermost_function().IsAsyncGenerator() ||
8606 innermost_function().IsAsyncGenClosure()) &&
8227 (try_blocks_list_ != NULL)) { 8607 (try_blocks_list_ != NULL)) {
8228 // We need two unchain two scopes: finally clause, and the try block level. 8608 // We need two unchain two scopes: finally clause, and the try block level.
8229 RestoreSavedTryContext(current_block_->scope->parent()->parent(), 8609 RestoreSavedTryContext(current_block_->scope->parent()->parent(),
8230 try_blocks_list_->try_index(), 8610 try_blocks_list_->try_index(),
8231 current_block_->statements); 8611 current_block_->statements);
8232 } else { 8612 } else {
8233 parsed_function()->reset_saved_try_ctx_vars(); 8613 parsed_function()->reset_saved_try_ctx_vars();
8234 } 8614 }
8235 8615
8236 ParseStatementSequence(); 8616 ParseStatementSequence();
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
8325 } else { 8705 } else {
8326 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); 8706 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType());
8327 } 8707 }
8328 if (CurrentToken() == Token::kCATCH) { 8708 if (CurrentToken() == Token::kCATCH) {
8329 ConsumeToken(); // Consume the 'catch'. 8709 ConsumeToken(); // Consume the 'catch'.
8330 ExpectToken(Token::kLPAREN); 8710 ExpectToken(Token::kLPAREN);
8331 exception_param.token_pos = TokenPos(); 8711 exception_param.token_pos = TokenPos();
8332 exception_param.name = ExpectIdentifier("identifier expected"); 8712 exception_param.name = ExpectIdentifier("identifier expected");
8333 if (CurrentToken() == Token::kCOMMA) { 8713 if (CurrentToken() == Token::kCOMMA) {
8334 ConsumeToken(); 8714 ConsumeToken();
8335 // TODO(hausner): Make implicit type be StackTrace, not dynamic.
8336 stack_trace_param.type = 8715 stack_trace_param.type =
8337 &AbstractType::ZoneHandle(Z, Type::DynamicType()); 8716 &AbstractType::ZoneHandle(Z, Type::DynamicType());
8338 stack_trace_param.token_pos = TokenPos(); 8717 stack_trace_param.token_pos = TokenPos();
8339 stack_trace_param.name = ExpectIdentifier("identifier expected"); 8718 stack_trace_param.name = ExpectIdentifier("identifier expected");
8340 } 8719 }
8341 ExpectToken(Token::kRPAREN); 8720 ExpectToken(Token::kRPAREN);
8342 } 8721 }
8343 8722
8344 // Create a block containing the catch clause parameters and the 8723 // Create a block containing the catch clause parameters and the
8345 // following code: 8724 // following code:
(...skipping 16 matching lines...) Expand all
8362 // A stack trace variable is specified in this block, so generate code 8741 // A stack trace variable is specified in this block, so generate code
8363 // to load the stack trace object (:stack_trace_var) into the stack 8742 // to load the stack trace object (:stack_trace_var) into the stack
8364 // trace variable specified in this block. 8743 // trace variable specified in this block.
8365 *needs_stack_trace = true; 8744 *needs_stack_trace = true;
8366 ASSERT(stack_trace_var != NULL); 8745 ASSERT(stack_trace_var != NULL);
8367 current_block_->statements->Add(new(Z) StoreLocalNode( 8746 current_block_->statements->Add(new(Z) StoreLocalNode(
8368 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( 8747 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode(
8369 catch_pos, stack_trace_var))); 8748 catch_pos, stack_trace_var)));
8370 } 8749 }
8371 8750
8372 // Add nested block with user-defined code. This blocks allows 8751 // Add nested block with user-defined code. This block allows
8373 // declarations in the body to shadow the catch parameters. 8752 // declarations in the body to shadow the catch parameters.
8374 CheckToken(Token::kLBRACE); 8753 CheckToken(Token::kLBRACE);
8375 8754
8376 // In case of async closures we need to restore the saved try index of an 8755 // In case of async closures we need to restore the saved try index of an
8377 // outer try block (if it exists). 8756 // outer try block (if it exists).
8378 ASSERT(try_blocks_list_ != NULL); 8757 ASSERT(try_blocks_list_ != NULL);
8379 if (innermost_function().IsAsyncClosure() || 8758 if (innermost_function().IsAsyncClosure() ||
8380 innermost_function().IsAsyncFunction() || 8759 innermost_function().IsAsyncFunction() ||
8381 innermost_function().IsSyncGenClosure() || 8760 innermost_function().IsSyncGenClosure() ||
8382 innermost_function().IsSyncGenerator()) { 8761 innermost_function().IsSyncGenerator() ||
8762 innermost_function().IsAsyncGenerator() ||
8763 innermost_function().IsAsyncGenClosure()) {
8383 if ((try_blocks_list_->outer_try_block() != NULL) && 8764 if ((try_blocks_list_->outer_try_block() != NULL) &&
8384 (try_blocks_list_->outer_try_block()->try_block() 8765 (try_blocks_list_->outer_try_block()->try_block()
8385 ->scope->function_level() == 8766 ->scope->function_level() ==
8386 current_block_->scope->function_level())) { 8767 current_block_->scope->function_level())) {
8387 // We need to unchain three scope levels: catch clause, catch 8768 // We need to unchain three scope levels: catch clause, catch
8388 // parameters, and the general try block. 8769 // parameters, and the general try block.
8389 RestoreSavedTryContext( 8770 RestoreSavedTryContext(
8390 current_block_->scope->parent()->parent()->parent(), 8771 current_block_->scope->parent()->parent()->parent(),
8391 try_blocks_list_->outer_try_block()->try_index(), 8772 try_blocks_list_->outer_try_block()->try_index(),
8392 current_block_->statements); 8773 current_block_->statements);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
8482 while (!type_tests.is_empty()) { 8863 while (!type_tests.is_empty()) {
8483 AstNode* type_test = type_tests.RemoveLast(); 8864 AstNode* type_test = type_tests.RemoveLast();
8484 SequenceNode* catch_block = catch_blocks.RemoveLast(); 8865 SequenceNode* catch_block = catch_blocks.RemoveLast();
8485 8866
8486 // In case of async closures we need to restore the saved try index of an 8867 // In case of async closures we need to restore the saved try index of an
8487 // outer try block (if it exists). 8868 // outer try block (if it exists).
8488 ASSERT(try_blocks_list_ != NULL); 8869 ASSERT(try_blocks_list_ != NULL);
8489 if (innermost_function().IsAsyncClosure() || 8870 if (innermost_function().IsAsyncClosure() ||
8490 innermost_function().IsAsyncFunction() || 8871 innermost_function().IsAsyncFunction() ||
8491 innermost_function().IsSyncGenClosure() || 8872 innermost_function().IsSyncGenClosure() ||
8492 innermost_function().IsSyncGenerator()) { 8873 innermost_function().IsSyncGenerator() ||
8874 innermost_function().IsAsyncGenerator() ||
8875 innermost_function().IsAsyncGenClosure()) {
8493 if ((try_blocks_list_->outer_try_block() != NULL) && 8876 if ((try_blocks_list_->outer_try_block() != NULL) &&
8494 (try_blocks_list_->outer_try_block()->try_block() 8877 (try_blocks_list_->outer_try_block()->try_block()
8495 ->scope->function_level() == 8878 ->scope->function_level() ==
8496 current_block_->scope->function_level())) { 8879 current_block_->scope->function_level())) {
8497 // We need to unchain three scope levels: catch clause, catch 8880 // We need to unchain three scope levels: catch clause, catch
8498 // parameters, and the general try block. 8881 // parameters, and the general try block.
8499 RestoreSavedTryContext( 8882 RestoreSavedTryContext(
8500 current_block_->scope->parent()->parent(), 8883 current_block_->scope->parent()->parent(),
8501 try_blocks_list_->outer_try_block()->try_index(), 8884 try_blocks_list_->outer_try_block()->try_index(),
8502 current_block_->statements); 8885 current_block_->statements);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
8621 } 9004 }
8622 9005
8623 // Now parse the 'try' block. 9006 // Now parse the 'try' block.
8624 OpenBlock(); 9007 OpenBlock();
8625 PushTryBlock(current_block_); 9008 PushTryBlock(current_block_);
8626 ExpectToken(Token::kLBRACE); 9009 ExpectToken(Token::kLBRACE);
8627 9010
8628 if (innermost_function().IsAsyncClosure() || 9011 if (innermost_function().IsAsyncClosure() ||
8629 innermost_function().IsAsyncFunction() || 9012 innermost_function().IsAsyncFunction() ||
8630 innermost_function().IsSyncGenClosure() || 9013 innermost_function().IsSyncGenClosure() ||
8631 innermost_function().IsSyncGenerator()) { 9014 innermost_function().IsSyncGenerator() ||
9015 innermost_function().IsAsyncGenerator() ||
9016 innermost_function().IsAsyncGenClosure()) {
8632 SetupSavedTryContext(context_var); 9017 SetupSavedTryContext(context_var);
8633 } 9018 }
8634 9019
8635 ParseStatementSequence(); 9020 ParseStatementSequence();
8636 ExpectToken(Token::kRBRACE); 9021 ExpectToken(Token::kRBRACE);
8637 SequenceNode* try_block = CloseBlock(); 9022 SequenceNode* try_block = CloseBlock();
8638 9023
8639 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && 9024 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") &&
8640 (CurrentToken() != Token::kFINALLY)) { 9025 (CurrentToken() != Token::kFINALLY)) {
8641 ReportError("catch or finally clause expected"); 9026 ReportError("catch or finally clause expected");
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
8765 ReportError(jump_pos, "'break' to case clause label is illegal"); 9150 ReportError(jump_pos, "'break' to case clause label is illegal");
8766 } 9151 }
8767 if (target->FunctionLevel() != current_block_->scope->function_level()) { 9152 if (target->FunctionLevel() != current_block_->scope->function_level()) {
8768 ReportError(jump_pos, "'%s' target must be in same function context", 9153 ReportError(jump_pos, "'%s' target must be in same function context",
8769 Token::Str(jump_kind)); 9154 Token::Str(jump_kind));
8770 } 9155 }
8771 return new(Z) JumpNode(jump_pos, jump_kind, target); 9156 return new(Z) JumpNode(jump_pos, jump_kind, target);
8772 } 9157 }
8773 9158
8774 9159
9160 AstNode* Parser::ParseYieldStatement() {
9161 bool is_yield_each = false;
9162 const intptr_t yield_pos = TokenPos();
9163 ConsumeToken(); // yield reserved word.
9164 ASSERT(innermost_function().IsGenerator() ||
9165 innermost_function().IsSyncGenClosure() ||
9166 innermost_function().IsAsyncGenerator() ||
9167 innermost_function().IsAsyncGenClosure());
9168 if (CurrentToken() == Token::kMUL) {
9169 is_yield_each = true;
9170 ConsumeToken();
9171 }
9172 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
9173
9174 LetNode* yield = new(Z) LetNode(yield_pos);
9175 if (innermost_function().IsSyncGenerator() ||
9176 innermost_function().IsSyncGenClosure()) {
9177 // Yield statement in sync* function.
9178
9179 LocalVariable* iterator_param =
9180 LookupLocalScope(Symbols::IteratorParameter());
9181 ASSERT(iterator_param != NULL);
9182 // Generate :iterator.current = expr;
9183 AstNode* iterator =
9184 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param);
9185 AstNode* store_current =
9186 new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
9187 iterator,
9188 String::ZoneHandle(Symbols::Current().raw()),
9189 expr);
9190 yield->AddNode(store_current);
9191 if (is_yield_each) {
9192 // Generate :iterator.isYieldEach = true;
9193 AstNode* set_is_yield_each =
9194 new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
9195 iterator,
9196 String::ZoneHandle(Symbols::IsYieldEach().raw()),
9197 new(Z) LiteralNode(TokenPos(), Bool::True()));
9198 yield->AddNode(set_is_yield_each);
9199 }
9200 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
9201 await_marker->set_scope(current_block_->scope);
9202 yield->AddNode(await_marker);
9203 // Return true to indicate that a value has been generated.
9204 ReturnNode* return_true = new(Z) ReturnNode(yield_pos,
9205 new(Z) LiteralNode(TokenPos(), Bool::True()));
9206 return_true->set_return_type(ReturnNode::kContinuationTarget);
9207 yield->AddNode(return_true);
9208
9209 // If this expression is part of a try block, also append the code for
9210 // restoring the saved try context that lives on the stack.
9211 const String& async_saved_try_ctx_name =
9212 String::Handle(Z, parsed_function()->async_saved_try_ctx_name());
9213 if (!async_saved_try_ctx_name.IsNull()) {
9214 LocalVariable* async_saved_try_ctx =
9215 current_block_->scope->LookupVariable(async_saved_try_ctx_name,
9216 false);
9217 ASSERT(async_saved_try_ctx != NULL);
9218 yield->AddNode(new (Z) StoreLocalNode(
9219 Scanner::kNoSourcePos,
9220 parsed_function()->saved_try_ctx(),
9221 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx)));
9222 }
9223 } else {
9224 // yield statement in async* function.
9225 ASSERT(innermost_function().IsAsyncGenerator() ||
9226 innermost_function().IsAsyncGenClosure());
9227
9228 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller());
9229 ASSERT(controller_var != NULL);
9230 // :controller.add[Stream](expr);
9231 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos);
9232 add_args->Add(expr);
9233 AstNode* add_call =
9234 new(Z) InstanceCallNode(yield_pos,
9235 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var),
9236 is_yield_each ? Symbols::AddStream() : Symbols::add(),
9237 add_args);
9238
9239 // if (:controller.isPaused) {
9240 // await_marker;
9241 // continuation_return;
9242 // }
9243 /*
9244 AstNode* is_paused = new(Z) InstanceGetterNode(
9245 Scanner::kNoSourcePos,
9246 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var),
9247 Symbols::isPaused());*/
9248
9249 SequenceNode* true_branch =
9250 new(Z) SequenceNode(Scanner::kNoSourcePos, current_block_->scope);
9251 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
9252 await_marker->set_scope(current_block_->scope);
9253 true_branch->Add(await_marker);
9254 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos);
9255 continuation_return->set_return_type(ReturnNode::kContinuationTarget);
9256 true_branch->Add(continuation_return);
9257
9258 AstNode* if_is_paused =
9259 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL);
9260 yield->AddNode(if_is_paused);
9261 }
9262 return yield;
9263 }
9264
9265
8775 AstNode* Parser::ParseStatement() { 9266 AstNode* Parser::ParseStatement() {
8776 TRACE_PARSER("ParseStatement"); 9267 TRACE_PARSER("ParseStatement");
8777 AstNode* statement = NULL; 9268 AstNode* statement = NULL;
8778 intptr_t label_pos = 0; 9269 intptr_t label_pos = 0;
8779 String* label_name = NULL; 9270 String* label_name = NULL;
8780 if (IsIdentifier()) { 9271 if (IsIdentifier()) {
8781 if (LookaheadToken(1) == Token::kCOLON) { 9272 if (LookaheadToken(1) == Token::kCOLON) {
8782 // Statement starts with a label. 9273 // Statement starts with a label.
8783 label_name = CurrentLiteral(); 9274 label_name = CurrentLiteral();
8784 label_pos = TokenPos(); 9275 label_pos = TokenPos();
(...skipping 19 matching lines...) Expand all
8804 statement = ParseTryStatement(label_name); 9295 statement = ParseTryStatement(label_name);
8805 } else if (token == Token::kRETURN) { 9296 } else if (token == Token::kRETURN) {
8806 const intptr_t return_pos = TokenPos(); 9297 const intptr_t return_pos = TokenPos();
8807 ConsumeToken(); 9298 ConsumeToken();
8808 if (CurrentToken() != Token::kSEMICOLON) { 9299 if (CurrentToken() != Token::kSEMICOLON) {
8809 const intptr_t expr_pos = TokenPos(); 9300 const intptr_t expr_pos = TokenPos();
8810 if (current_function().IsGenerativeConstructor() && 9301 if (current_function().IsGenerativeConstructor() &&
8811 (current_block_->scope->function_level() == 0)) { 9302 (current_block_->scope->function_level() == 0)) {
8812 ReportError(expr_pos, 9303 ReportError(expr_pos,
8813 "return of a value is not allowed in constructors"); 9304 "return of a value is not allowed in constructors");
8814 } else if (current_function().IsGenerator()) { 9305 } else if (current_function().IsGeneratorClosure() &&
9306 (current_block_->scope->function_level() == 0)) {
8815 ReportError(expr_pos, "generator functions may not return a value"); 9307 ReportError(expr_pos, "generator functions may not return a value");
8816 } 9308 }
8817 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); 9309 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
8818 statement = new(Z) ReturnNode(statement_pos, expr); 9310 statement = new(Z) ReturnNode(statement_pos, expr);
8819 } else { 9311 } else {
8820 if (current_function().IsSyncGenClosure() && 9312 if (current_function().IsSyncGenClosure() &&
8821 (current_block_->scope->function_level() == 0)) { 9313 (current_block_->scope->function_level() == 0)) {
8822 // In a synchronous generator, return without an expression 9314 // In a synchronous generator, return without an expression
8823 // returns false, signaling that the iterator terminates and 9315 // returns false, signaling that the iterator terminates and
8824 // did not yield a value. 9316 // did not yield a value.
8825 statement = new(Z) ReturnNode(statement_pos, 9317 statement = new(Z) ReturnNode(statement_pos,
8826 new(Z) LiteralNode(return_pos, Bool::False())); 9318 new(Z) LiteralNode(return_pos, Bool::False()));
8827 } else { 9319 } else {
8828 statement = new(Z) ReturnNode(statement_pos); 9320 statement = new(Z) ReturnNode(statement_pos);
8829 } 9321 }
8830 } 9322 }
8831 AddNodeForFinallyInlining(statement); 9323 AddNodeForFinallyInlining(statement);
8832 ExpectSemicolon(); 9324 ExpectSemicolon();
8833 } else if (IsYieldKeyword()) { 9325 } else if (IsYieldKeyword()) {
8834 bool is_yield_each = false; 9326 statement = ParseYieldStatement();
8835 ConsumeToken();
8836 ASSERT(innermost_function().IsGenerator() ||
8837 innermost_function().IsSyncGenClosure());
8838 if (CurrentToken() == Token::kMUL) {
8839 is_yield_each = true;
8840 ConsumeToken();
8841 }
8842 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
8843 LocalVariable* iterator_param =
8844 LookupLocalScope(Symbols::IteratorParameter());
8845 ASSERT(iterator_param != NULL);
8846 // Generate :iterator.current = expr;
8847 AstNode* iterator =
8848 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param);
8849 AstNode* store_current =
8850 new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
8851 iterator,
8852 String::ZoneHandle(Symbols::Current().raw()),
8853 expr);
8854 LetNode* yield = new(Z) LetNode(statement_pos);
8855 yield->AddNode(store_current);
8856 if (is_yield_each) {
8857 // Generate :iterator.isYieldEach = true;
8858 AstNode* set_is_yield_each =
8859 new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
8860 iterator,
8861 String::ZoneHandle(Symbols::IsYieldEach().raw()),
8862 new(Z) LiteralNode(TokenPos(), Bool::True()));
8863 yield->AddNode(set_is_yield_each);
8864 }
8865 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
8866 await_marker->set_scope(current_block_->scope);
8867 yield->AddNode(await_marker);
8868 // Return true to indicate that a value has been generated.
8869 ReturnNode* return_true = new(Z) ReturnNode(statement_pos,
8870 new(Z) LiteralNode(TokenPos(), Bool::True()));
8871 return_true->set_return_type(ReturnNode::kContinuationTarget);
8872 yield->AddNode(return_true);
8873
8874 // If this expression is part of a try block, also append the code for
8875 // restoring the saved try context that lives on the stack.
8876 const String& async_saved_try_ctx_name =
8877 String::Handle(Z, parsed_function()->async_saved_try_ctx_name());
8878 if (!async_saved_try_ctx_name.IsNull()) {
8879 LocalVariable* async_saved_try_ctx =
8880 current_block_->scope->LookupVariable(async_saved_try_ctx_name,
8881 false);
8882 ASSERT(async_saved_try_ctx != NULL);
8883 yield->AddNode(new (Z) StoreLocalNode(
8884 Scanner::kNoSourcePos,
8885 parsed_function()->saved_try_ctx(),
8886 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx)));
8887 }
8888
8889 statement = yield;
8890 ExpectSemicolon(); 9327 ExpectSemicolon();
8891 } else if (token == Token::kIF) { 9328 } else if (token == Token::kIF) {
8892 statement = ParseIfStatement(label_name); 9329 statement = ParseIfStatement(label_name);
8893 } else if (token == Token::kASSERT) { 9330 } else if (token == Token::kASSERT) {
8894 statement = ParseAssertStatement(); 9331 statement = ParseAssertStatement();
8895 ExpectSemicolon(); 9332 ExpectSemicolon();
8896 } else if (IsVariableDeclaration()) { 9333 } else if (IsVariableDeclaration()) {
8897 statement = ParseVariableDeclarationList(); 9334 statement = ParseVariableDeclarationList();
8898 ExpectSemicolon(); 9335 ExpectSemicolon();
8899 } else if (IsFunctionDeclaration()) { 9336 } else if (IsFunctionDeclaration()) {
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after
9730 } 10167 }
9731 10168
9732 10169
9733 AstNode* Parser::ParseUnaryExpr() { 10170 AstNode* Parser::ParseUnaryExpr() {
9734 TRACE_PARSER("ParseUnaryExpr"); 10171 TRACE_PARSER("ParseUnaryExpr");
9735 AstNode* expr = NULL; 10172 AstNode* expr = NULL;
9736 const intptr_t op_pos = TokenPos(); 10173 const intptr_t op_pos = TokenPos();
9737 if (IsAwaitKeyword()) { 10174 if (IsAwaitKeyword()) {
9738 TRACE_PARSER("ParseAwaitExpr"); 10175 TRACE_PARSER("ParseAwaitExpr");
9739 if (!innermost_function().IsAsyncFunction() && 10176 if (!innermost_function().IsAsyncFunction() &&
9740 !innermost_function().IsAsyncClosure()) { 10177 !innermost_function().IsAsyncClosure() &&
9741 ReportError("await operator is only allowed in async function"); 10178 !innermost_function().IsAsyncGenerator() &&
10179 !innermost_function().IsAsyncGenClosure()) {
10180 ReportError("await operator is only allowed in an asynchronous function");
9742 } 10181 }
9743 ConsumeToken(); 10182 ConsumeToken();
9744 parsed_function()->record_await(); 10183 parsed_function()->record_await();
9745 expr = new (Z) AwaitNode(op_pos, ParseUnaryExpr()); 10184 expr = new (Z) AwaitNode(op_pos, ParseUnaryExpr());
9746 } else if (IsPrefixOperator(CurrentToken())) { 10185 } else if (IsPrefixOperator(CurrentToken())) {
9747 Token::Kind unary_op = CurrentToken(); 10186 Token::Kind unary_op = CurrentToken();
9748 if (unary_op == Token::kSUB) { 10187 if (unary_op == Token::kSUB) {
9749 unary_op = Token::kNEGATE; 10188 unary_op = Token::kNEGATE;
9750 } 10189 }
9751 ConsumeToken(); 10190 ConsumeToken();
(...skipping 2816 matching lines...) Expand 10 before | Expand all | Expand 10 after
12568 void Parser::SkipQualIdent() { 13007 void Parser::SkipQualIdent() {
12569 ASSERT(IsIdentifier()); 13008 ASSERT(IsIdentifier());
12570 ConsumeToken(); 13009 ConsumeToken();
12571 if (CurrentToken() == Token::kPERIOD) { 13010 if (CurrentToken() == Token::kPERIOD) {
12572 ConsumeToken(); // Consume the kPERIOD token. 13011 ConsumeToken(); // Consume the kPERIOD token.
12573 ExpectIdentifier("identifier expected after '.'"); 13012 ExpectIdentifier("identifier expected after '.'");
12574 } 13013 }
12575 } 13014 }
12576 13015
12577 } // namespace dart 13016 } // namespace dart
OLDNEW
« runtime/lib/core_patch.dart ('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