| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
| 9 #include "vm/ast_transformer.h" | 9 #include "vm/ast_transformer.h" |
| 10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
| (...skipping 3097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3108 AddFormalParamsToScope(¶ms, current_block_->scope); | 3108 AddFormalParamsToScope(¶ms, 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(¶ms); |
| 3120 SetupDefaultsForOptionalParams(¶ms, default_parameter_values); |
| 3121 AddFormalParamsToScope(¶ms, 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, ¶ms); | 3133 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); |
| 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(¶ms, func); | 3138 AddFormalParamsToFunction(¶ms, func); |
| 3125 } | 3139 } |
| 3126 SetupDefaultsForOptionalParams(¶ms, default_parameter_values); | 3140 SetupDefaultsForOptionalParams(¶ms, 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 const intptr_t try_end_pos = innermost_function().end_token_pos(); |
| 5993 |
| 5994 // The try-block (closure body code) has been parsed. We are now |
| 5995 // generating the code for the catch block. |
| 5955 try_blocks_list_->enter_catch(); | 5996 try_blocks_list_->enter_catch(); |
| 5997 OpenBlock(); // Catch handler list. |
| 5998 OpenBlock(); // Catch block. |
| 5956 | 5999 |
| 5957 OpenBlock(); | 6000 // Add the exception and stack trace parameters to the scope. |
| 5958 OpenBlock(); | |
| 5959 const AbstractType& dynamic_type = | 6001 const AbstractType& dynamic_type = |
| 5960 AbstractType::ZoneHandle(Z, Type::DynamicType()); | 6002 AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 5961 CatchParamDesc exception_param; | 6003 CatchParamDesc exception_param; |
| 5962 CatchParamDesc stack_trace_param; | 6004 CatchParamDesc stack_trace_param; |
| 5963 exception_param.token_pos = Scanner::kNoSourcePos; | 6005 exception_param.token_pos = Scanner::kNoSourcePos; |
| 5964 exception_param.type = &dynamic_type; | 6006 exception_param.type = &dynamic_type; |
| 5965 exception_param.name = &Symbols::ExceptionParameter(); | 6007 exception_param.name = &Symbols::ExceptionParameter(); |
| 5966 stack_trace_param.token_pos = Scanner::kNoSourcePos; | 6008 stack_trace_param.token_pos = Scanner::kNoSourcePos; |
| 5967 stack_trace_param.type = &dynamic_type; | 6009 stack_trace_param.type = &dynamic_type; |
| 5968 stack_trace_param.name = &Symbols::StackTraceParameter(); | 6010 stack_trace_param.name = &Symbols::StackTraceParameter(); |
| 5969 | |
| 5970 AddCatchParamsToScope( | 6011 AddCatchParamsToScope( |
| 5971 &exception_param, &stack_trace_param, current_block_->scope); | 6012 &exception_param, &stack_trace_param, current_block_->scope); |
| 5972 | 6013 |
| 6014 // Generate code to save the exception object and stack trace |
| 6015 // in local variables. |
| 5973 LocalVariable* context_var = current_block_->scope->LookupVariable( | 6016 LocalVariable* context_var = current_block_->scope->LookupVariable( |
| 5974 Symbols::SavedTryContextVar(), false); | 6017 Symbols::SavedTryContextVar(), false); |
| 5975 ASSERT(context_var != NULL); | 6018 ASSERT(context_var != NULL); |
| 5976 | 6019 |
| 5977 LocalVariable* exception_var = current_block_->scope->LookupVariable( | 6020 LocalVariable* exception_var = current_block_->scope->LookupVariable( |
| 5978 Symbols::ExceptionVar(), false); | 6021 Symbols::ExceptionVar(), false); |
| 5979 ASSERT(exception_var != NULL); | 6022 ASSERT(exception_var != NULL); |
| 5980 if (exception_param.var != NULL) { | 6023 if (exception_param.var != NULL) { |
| 5981 // Generate code to load the exception object (:exception_var) into | 6024 // Generate code to load the exception object (:exception_var) into |
| 5982 // the exception variable specified in this block. | 6025 // the exception variable specified in this block. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5995 // trace variable specified in this block. | 6038 // trace variable specified in this block. |
| 5996 current_block_->statements->Add(new(Z) StoreLocalNode( | 6039 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 5997 Scanner::kNoSourcePos, | 6040 Scanner::kNoSourcePos, |
| 5998 stack_trace_param.var, | 6041 stack_trace_param.var, |
| 5999 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); | 6042 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); |
| 6000 } | 6043 } |
| 6001 | 6044 |
| 6002 AddSavedExceptionAndStacktraceToScope( | 6045 AddSavedExceptionAndStacktraceToScope( |
| 6003 exception_var, stack_trace_var, current_block_->scope); | 6046 exception_var, stack_trace_var, current_block_->scope); |
| 6004 | 6047 |
| 6048 parsed_function()->reset_saved_try_ctx_vars(); |
| 6049 |
| 6050 // Catch block: add the error to the stream. |
| 6051 // :controller.AddError(:exception, :stack_trace); |
| 6052 // return; // The finally block will close the stream. |
| 6053 LocalVariable* controller = |
| 6054 current_block_->scope->LookupVariable(Symbols::Controller(), false); |
| 6055 ASSERT(controller != NULL); |
| 6056 ArgumentListNode* args = |
| 6057 new(Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6058 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); |
| 6059 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); |
| 6060 current_block_->statements->Add( |
| 6061 new(Z) InstanceCallNode(try_end_pos, |
| 6062 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), |
| 6063 Symbols::AddError(), |
| 6064 args)); |
| 6065 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); |
| 6066 current_block_->statements->Add(return_node); |
| 6067 AstNode* catch_block = CloseBlock(); |
| 6068 current_block_->statements->Add(catch_block); |
| 6069 SequenceNode* catch_handler_list = CloseBlock(); |
| 6070 |
| 6071 TryBlocks* try_block = PopTryBlock(); |
| 6072 ASSERT(try_blocks_list_ == NULL); // We popped the outermost try block. |
| 6073 |
| 6074 // Finally block: closing the stream and returning. (Note: the return |
| 6075 // is necessary otherwise the back-end will append a rethrow of the |
| 6076 // current exception.) |
| 6077 // :controller.close(); |
| 6078 // return; |
| 6079 // We need to inline this code in all recorded exit points. |
| 6080 intptr_t node_index = 0; |
| 6081 SequenceNode* finally_clause = NULL; |
| 6082 do { |
| 6083 OpenBlock(); |
| 6084 ArgumentListNode* no_args = |
| 6085 new(Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6086 current_block_->statements->Add( |
| 6087 new(Z) InstanceCallNode(try_end_pos, |
| 6088 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), |
| 6089 Symbols::Close(), |
| 6090 no_args)); |
| 6091 |
| 6092 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); |
| 6093 current_block_->statements->Add(return_node); |
| 6094 |
| 6095 finally_clause = CloseBlock(); |
| 6096 AstNode* node_to_inline = try_block->GetNodeToInlineFinally(node_index); |
| 6097 if (node_to_inline != NULL) { |
| 6098 InlinedFinallyNode* node = |
| 6099 new(Z) InlinedFinallyNode(try_end_pos, |
| 6100 finally_clause, |
| 6101 context_var, |
| 6102 // No outer try statement |
| 6103 CatchClauseNode::kInvalidTryIndex); |
| 6104 finally_clause = NULL; |
| 6105 AddFinallyBlockToNode(node_to_inline, node); |
| 6106 node_index++; |
| 6107 } |
| 6108 } while (finally_clause == NULL); |
| 6109 |
| 6110 const GrowableObjectArray& handler_types = |
| 6111 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
| 6112 handler_types.Add(dynamic_type); // Catch block handles all exceptions. |
| 6113 |
| 6114 CatchClauseNode* catch_clause = new(Z) CatchClauseNode( |
| 6115 Scanner::kNoSourcePos, |
| 6116 catch_handler_list, |
| 6117 Array::ZoneHandle(Z, Array::MakeArray(handler_types)), |
| 6118 context_var, |
| 6119 exception_var, |
| 6120 stack_trace_var, |
| 6121 AllocateTryIndex(), |
| 6122 true); |
| 6123 |
| 6124 const intptr_t try_index = try_block->try_index(); |
| 6125 |
| 6126 AstNode* try_catch_node = |
| 6127 new(Z) TryCatchNode(Scanner::kNoSourcePos, |
| 6128 body, |
| 6129 context_var, |
| 6130 catch_clause, |
| 6131 finally_clause, |
| 6132 try_index); |
| 6133 current_block_->statements->Add(try_catch_node); |
| 6134 return CloseBlock(); |
| 6135 } |
| 6136 |
| 6137 |
| 6138 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { |
| 6139 // This is the outermost try-catch of the function. |
| 6005 ASSERT(try_blocks_list_ != NULL); | 6140 ASSERT(try_blocks_list_ != NULL); |
| 6006 ASSERT(innermost_function().IsAsyncClosure() || | 6141 ASSERT(try_blocks_list_->outer_try_block() == NULL); |
| 6007 innermost_function().IsAsyncFunction()); | 6142 ASSERT(innermost_function().IsAsyncClosure()); |
| 6008 if ((try_blocks_list_->outer_try_block() != NULL) && | 6143 |
| 6009 (try_blocks_list_->outer_try_block()->try_block() | 6144 try_blocks_list_->enter_catch(); |
| 6010 ->scope->function_level() == | 6145 |
| 6011 current_block_->scope->function_level())) { | 6146 OpenBlock(); // Catch handler list. |
| 6012 // We need to unchain three scope levels: catch clause, catch | 6147 OpenBlock(); // Catch block. |
| 6013 // parameters, and the general try block. | 6148 const AbstractType& dynamic_type = |
| 6014 RestoreSavedTryContext( | 6149 AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 6015 current_block_->scope->parent()->parent()->parent(), | 6150 CatchParamDesc exception_param; |
| 6016 try_blocks_list_->outer_try_block()->try_index(), | 6151 CatchParamDesc stack_trace_param; |
| 6017 current_block_->statements); | 6152 exception_param.token_pos = Scanner::kNoSourcePos; |
| 6018 } else { | 6153 exception_param.type = &dynamic_type; |
| 6019 parsed_function()->reset_saved_try_ctx_vars(); | 6154 exception_param.name = &Symbols::ExceptionParameter(); |
| 6155 stack_trace_param.token_pos = Scanner::kNoSourcePos; |
| 6156 stack_trace_param.type = &dynamic_type; |
| 6157 stack_trace_param.name = &Symbols::StackTraceParameter(); |
| 6158 |
| 6159 AddCatchParamsToScope( |
| 6160 &exception_param, &stack_trace_param, current_block_->scope); |
| 6161 |
| 6162 LocalVariable* context_var = current_block_->scope->LookupVariable( |
| 6163 Symbols::SavedTryContextVar(), false); |
| 6164 ASSERT(context_var != NULL); |
| 6165 LocalVariable* exception_var = current_block_->scope->LookupVariable( |
| 6166 Symbols::ExceptionVar(), false); |
| 6167 if (exception_param.var != NULL) { |
| 6168 // Generate code to load the exception object (:exception_var) into |
| 6169 // the exception variable specified in this block. |
| 6170 ASSERT(exception_var != NULL); |
| 6171 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 6172 Scanner::kNoSourcePos, |
| 6173 exception_param.var, |
| 6174 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); |
| 6175 } |
| 6176 LocalVariable* stack_trace_var = |
| 6177 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false); |
| 6178 if (stack_trace_param.var != NULL) { |
| 6179 // A stack trace variable is specified in this block, so generate code |
| 6180 // to load the stack trace object (:stack_trace_var) into the stack |
| 6181 // trace variable specified in this block. |
| 6182 ASSERT(stack_trace_var != NULL); |
| 6183 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 6184 Scanner::kNoSourcePos, |
| 6185 stack_trace_param.var, |
| 6186 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); |
| 6020 } | 6187 } |
| 6021 | 6188 |
| 6022 // Complete the async future with an error. | 6189 AddSavedExceptionAndStacktraceToScope( |
| 6023 // Since we control the catch block there is no need to generate a nested | 6190 exception_var, stack_trace_var, current_block_->scope); |
| 6024 // if/then/else. | 6191 |
| 6192 parsed_function()->reset_saved_try_ctx_vars(); |
| 6193 |
| 6194 // Complete the async future with an error. This catch block executes |
| 6195 // unconditionally, there is no need to generate a type check for. |
| 6025 LocalVariable* async_completer = current_block_->scope->LookupVariable( | 6196 LocalVariable* async_completer = current_block_->scope->LookupVariable( |
| 6026 Symbols::AsyncCompleter(), false); | 6197 Symbols::AsyncCompleter(), false); |
| 6027 ASSERT(async_completer != NULL); | 6198 ASSERT(async_completer != NULL); |
| 6028 ArgumentListNode* completer_args = | 6199 ArgumentListNode* completer_args = |
| 6029 new (Z) ArgumentListNode(Scanner::kNoSourcePos); | 6200 new (Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6030 completer_args->Add( | 6201 completer_args->Add( |
| 6031 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); | 6202 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); |
| 6032 completer_args->Add( | 6203 completer_args->Add( |
| 6033 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); | 6204 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); |
| 6034 current_block_->statements->Add(new (Z) InstanceCallNode( | 6205 current_block_->statements->Add(new (Z) InstanceCallNode( |
| (...skipping 24 matching lines...) Expand all Loading... |
| 6059 context_var, | 6230 context_var, |
| 6060 exception_var, | 6231 exception_var, |
| 6061 stack_trace_var, | 6232 stack_trace_var, |
| 6062 CatchClauseNode::kInvalidTryIndex, | 6233 CatchClauseNode::kInvalidTryIndex, |
| 6063 true); | 6234 true); |
| 6064 AstNode* try_catch_node = new (Z) TryCatchNode( | 6235 AstNode* try_catch_node = new (Z) TryCatchNode( |
| 6065 Scanner::kNoSourcePos, | 6236 Scanner::kNoSourcePos, |
| 6066 try_block, | 6237 try_block, |
| 6067 context_var, | 6238 context_var, |
| 6068 catch_clause, | 6239 catch_clause, |
| 6069 NULL, | 6240 NULL, // No finally clause. |
| 6070 try_index); | 6241 try_index); |
| 6071 current_block_->statements->Add(try_catch_node); | 6242 current_block_->statements->Add(try_catch_node); |
| 6072 return CloseBlock(); | 6243 return CloseBlock(); |
| 6073 } | 6244 } |
| 6074 | 6245 |
| 6075 | 6246 |
| 6247 // Wrap the body of the async or arync* closure in a try/catch block. |
| 6076 void Parser::OpenAsyncTryBlock() { | 6248 void Parser::OpenAsyncTryBlock() { |
| 6077 // Manually wrapping the actual body into a try/catch block. | 6249 ASSERT(innermost_function().IsAsyncClosure() || |
| 6250 innermost_function().IsAsyncGenClosure()); |
| 6251 |
| 6078 LocalVariable* context_var = | 6252 LocalVariable* context_var = |
| 6079 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); | 6253 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); |
| 6080 if (context_var == NULL) { | 6254 if (context_var == NULL) { |
| 6081 context_var = new(Z) LocalVariable( | 6255 context_var = new(Z) LocalVariable( |
| 6082 TokenPos(), | 6256 TokenPos(), |
| 6083 Symbols::SavedTryContextVar(), | 6257 Symbols::SavedTryContextVar(), |
| 6084 Type::ZoneHandle(Z, Type::DynamicType())); | 6258 Type::ZoneHandle(Z, Type::DynamicType())); |
| 6085 current_block_->scope->AddVariable(context_var); | 6259 current_block_->scope->AddVariable(context_var); |
| 6086 } | 6260 } |
| 6087 LocalVariable* exception_var = | 6261 LocalVariable* exception_var = |
| (...skipping 10 matching lines...) Expand all Loading... |
| 6098 if (stack_trace_var == NULL) { | 6272 if (stack_trace_var == NULL) { |
| 6099 stack_trace_var = new(Z) LocalVariable( | 6273 stack_trace_var = new(Z) LocalVariable( |
| 6100 TokenPos(), | 6274 TokenPos(), |
| 6101 Symbols::StackTraceVar(), | 6275 Symbols::StackTraceVar(), |
| 6102 Type::ZoneHandle(Z, Type::DynamicType())); | 6276 Type::ZoneHandle(Z, Type::DynamicType())); |
| 6103 current_block_->scope->AddVariable(stack_trace_var); | 6277 current_block_->scope->AddVariable(stack_trace_var); |
| 6104 } | 6278 } |
| 6105 | 6279 |
| 6106 // Open the try block. | 6280 // Open the try block. |
| 6107 OpenBlock(); | 6281 OpenBlock(); |
| 6282 // This is the outermost try-catch in the function. |
| 6283 ASSERT(try_blocks_list_ == NULL); |
| 6108 PushTryBlock(current_block_); | 6284 PushTryBlock(current_block_); |
| 6109 | 6285 |
| 6110 if (innermost_function().IsAsyncClosure() || | 6286 SetupSavedTryContext(context_var); |
| 6111 innermost_function().IsAsyncFunction() || | |
| 6112 innermost_function().IsSyncGenClosure() || | |
| 6113 innermost_function().IsSyncGenerator()) { | |
| 6114 SetupSavedTryContext(context_var); | |
| 6115 } | |
| 6116 } | 6287 } |
| 6117 | 6288 |
| 6118 | 6289 |
| 6119 void Parser::AddSyncGenClosureParameters(ParamList* params) { | 6290 void Parser::AddSyncGenClosureParameters(ParamList* params) { |
| 6120 // Create the parameter list for the body closure of a sync generator: | 6291 // Create the parameter list for the body closure of a sync generator: |
| 6121 // 1) Implicit closure parameter; | 6292 // 1) Implicit closure parameter; |
| 6122 // 2) Iterator | 6293 // 2) Iterator |
| 6123 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | 6294 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 6124 // Add implicit closure parameter if not already present. | 6295 // Add implicit closure parameter if not already present. |
| 6125 if (params->parameters->length() == 0) { | 6296 if (params->parameters->length() == 0) { |
| 6126 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); | 6297 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); |
| 6127 } | 6298 } |
| 6128 ParamDesc iterator_param; | 6299 ParamDesc iterator_param; |
| 6129 iterator_param.name = &Symbols::IteratorParameter(); | 6300 iterator_param.name = &Symbols::IteratorParameter(); |
| 6130 iterator_param.type = &dynamic_type; | 6301 iterator_param.type = &dynamic_type; |
| 6131 params->parameters->Add(iterator_param); | 6302 params->parameters->Add(iterator_param); |
| 6132 params->num_fixed_parameters++; | 6303 params->num_fixed_parameters++; |
| 6133 } | 6304 } |
| 6134 | 6305 |
| 6135 | 6306 |
| 6307 void Parser::AddAsyncGenClosureParameters(ParamList* params) { |
| 6308 // Create the parameter list for the body closure of an async generator: |
| 6309 // The closure has the same parameters as an asynchronous non-generator. |
| 6310 AddAsyncClosureParameters(params); |
| 6311 } |
| 6312 |
| 6313 |
| 6136 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) { | 6314 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) { |
| 6137 Function& body = Function::Handle(Z); | 6315 Function& body = Function::Handle(Z); |
| 6138 String& body_closure_name = String::Handle(Z); | 6316 String& body_closure_name = String::Handle(Z); |
| 6139 bool is_new_closure = false; | 6317 bool is_new_closure = false; |
| 6140 | 6318 |
| 6141 AddContinuationVariables(); | 6319 AddContinuationVariables(); |
| 6142 | 6320 |
| 6143 // Check whether a function for the body of this generator | 6321 // Check whether a function for the body of this generator |
| 6144 // function has already been created by a previous | 6322 // function has already been created by a previous |
| 6145 // compilation. | 6323 // compilation. |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6236 iterable_constructor, | 6414 iterable_constructor, |
| 6237 arguments); | 6415 arguments); |
| 6238 ReturnNode* return_node = | 6416 ReturnNode* return_node = |
| 6239 new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable); | 6417 new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable); |
| 6240 current_block_->statements->Add(return_node); | 6418 current_block_->statements->Add(return_node); |
| 6241 return CloseBlock(); | 6419 return CloseBlock(); |
| 6242 } | 6420 } |
| 6243 | 6421 |
| 6244 | 6422 |
| 6245 void Parser::AddAsyncClosureParameters(ParamList* params) { | 6423 void Parser::AddAsyncClosureParameters(ParamList* params) { |
| 6246 // Async closures have two optional parameters: | 6424 // Async closures have three optional parameters: |
| 6247 // * A continuation result. | 6425 // * A continuation result. |
| 6248 // * A continuation error. | 6426 // * A continuation error. |
| 6249 // * A continuation stack trace. | 6427 // * A continuation stack trace. |
| 6250 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | 6428 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 6251 // Add implicit closure parameter if not yet present. | 6429 // Add implicit closure parameter if not yet present. |
| 6252 if (params->parameters->length() == 0) { | 6430 if (params->parameters->length() == 0) { |
| 6253 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); | 6431 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); |
| 6254 } | 6432 } |
| 6255 ParamDesc result_param; | 6433 ParamDesc result_param; |
| 6256 result_param.name = &Symbols::AsyncOperationParam(); | 6434 result_param.name = &Symbols::AsyncOperationParam(); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6365 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); | 6543 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); |
| 6366 async_op_var->set_is_captured(); | 6544 async_op_var->set_is_captured(); |
| 6367 LocalVariable* async_completer = new(Z) LocalVariable( | 6545 LocalVariable* async_completer = new(Z) LocalVariable( |
| 6368 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); | 6546 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); |
| 6369 current_block_->scope->AddVariable(async_completer); | 6547 current_block_->scope->AddVariable(async_completer); |
| 6370 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); | 6548 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); |
| 6371 async_completer->set_is_captured(); | 6549 async_completer->set_is_captured(); |
| 6372 } | 6550 } |
| 6373 | 6551 |
| 6374 | 6552 |
| 6553 void Parser::AddAsyncGeneratorVariables() { |
| 6554 // Add to current block's scope: |
| 6555 // var :controller; |
| 6556 // This variable is used by the nested async generator closure to |
| 6557 // store the StreamController object to which the yielded expressions |
| 6558 // are added. |
| 6559 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 6560 LocalVariable* controller_var = new(Z) LocalVariable( |
| 6561 Scanner::kNoSourcePos, Symbols::Controller(), dynamic_type); |
| 6562 current_block_->scope->AddVariable(controller_var); |
| 6563 current_block_->scope->CaptureVariable(Symbols::Controller()); |
| 6564 controller_var->set_is_captured(); |
| 6565 |
| 6566 LocalVariable* async_op_var = new(Z) LocalVariable( |
| 6567 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type); |
| 6568 current_block_->scope->AddVariable(async_op_var); |
| 6569 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); |
| 6570 async_op_var->set_is_captured(); |
| 6571 } |
| 6572 |
| 6573 |
| 6574 RawFunction* Parser::OpenAsyncGeneratorFunction(intptr_t async_func_pos) { |
| 6575 TRACE_PARSER("OpenAsyncGeneratorFunction"); |
| 6576 AddContinuationVariables(); |
| 6577 AddAsyncGeneratorVariables(); |
| 6578 |
| 6579 Function& closure = Function::Handle(Z); |
| 6580 bool is_new_closure = false; |
| 6581 |
| 6582 // Check whether a function for the asynchronous function body of |
| 6583 // this async generator has already been created by a previous |
| 6584 // compilation of this function. |
| 6585 const Function& found_func = Function::Handle( |
| 6586 Z, current_class().LookupClosureFunction(async_func_pos)); |
| 6587 if (!found_func.IsNull() && |
| 6588 (found_func.token_pos() == async_func_pos) && |
| 6589 (found_func.script() == innermost_function().script()) && |
| 6590 (found_func.parent_function() == innermost_function().raw())) { |
| 6591 ASSERT(found_func.IsAsyncGenClosure()); |
| 6592 closure = found_func.raw(); |
| 6593 } else { |
| 6594 // Create the closure containing the body of this async generator function. |
| 6595 const String& async_generator_name = |
| 6596 String::Handle(Z, innermost_function().name()); |
| 6597 String& closure_name = String::Handle(Z, |
| 6598 String::NewFormatted("<%s_async_gen_body>", |
| 6599 async_generator_name.ToCString())); |
| 6600 closure = Function::NewClosureFunction( |
| 6601 String::Handle(Z, Symbols::New(closure_name)), |
| 6602 innermost_function(), |
| 6603 async_func_pos); |
| 6604 closure.set_is_generated_body(true); |
| 6605 closure.set_result_type(AbstractType::Handle(Type::DynamicType())); |
| 6606 is_new_closure = true; |
| 6607 } |
| 6608 |
| 6609 ParamList closure_params; |
| 6610 AddAsyncGenClosureParameters(&closure_params); |
| 6611 |
| 6612 if (is_new_closure) { |
| 6613 // Add the parameters to the newly created closure. |
| 6614 AddFormalParamsToFunction(&closure_params, closure); |
| 6615 |
| 6616 // Create and set the signature class of the closure. |
| 6617 const String& sig = String::Handle(Z, closure.Signature()); |
| 6618 Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig)); |
| 6619 if (sig_cls.IsNull()) { |
| 6620 sig_cls = |
| 6621 Class::NewSignatureClass(sig, closure, script_, closure.token_pos()); |
| 6622 library_.AddClass(sig_cls); |
| 6623 } |
| 6624 closure.set_signature_class(sig_cls); |
| 6625 const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType()); |
| 6626 if (!sig_type.IsFinalized()) { |
| 6627 ClassFinalizer::FinalizeType( |
| 6628 sig_cls, sig_type, ClassFinalizer::kCanonicalize); |
| 6629 } |
| 6630 ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved()); |
| 6631 ASSERT(closure.NumParameters() == closure_params.parameters->length()); |
| 6632 } |
| 6633 |
| 6634 OpenFunctionBlock(closure); |
| 6635 AddFormalParamsToScope(&closure_params, current_block_->scope); |
| 6636 OpenBlock(); |
| 6637 async_temp_scope_ = current_block_->scope; |
| 6638 return closure.raw(); |
| 6639 } |
| 6640 |
| 6641 |
| 6642 // Generate the Ast nodes for the implicit code of the async* function. |
| 6643 // |
| 6644 // f(...) async* { |
| 6645 // var :controller; |
| 6646 // var :await_jump_var = -1; |
| 6647 // var :await_context_var; |
| 6648 // f_async_body() { |
| 6649 // ... source code of f ... |
| 6650 // } |
| 6651 // :controller = new _AsyncStarStreamController(f_async_body); |
| 6652 // return :controller.stream; |
| 6653 // } |
| 6654 SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure, |
| 6655 SequenceNode* closure_body) { |
| 6656 TRACE_PARSER("CloseAsyncGeneratorFunction"); |
| 6657 ASSERT(!closure.IsNull()); |
| 6658 ASSERT(closure_body != NULL); |
| 6659 |
| 6660 // The block for the async closure body has already been closed. Close the |
| 6661 // corresponding function block. |
| 6662 CloseBlock(); |
| 6663 |
| 6664 // Make sure the implicit variables of the async generator function |
| 6665 // are captured. |
| 6666 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 6667 closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
| 6668 closure_body->scope()->LookupVariable(Symbols::Controller(), false); |
| 6669 |
| 6670 const Class& controller_class = Class::Handle(Z, |
| 6671 Library::LookupCoreClass(Symbols::_AsyncStarStreamController())); |
| 6672 ASSERT(!controller_class.IsNull()); |
| 6673 const Function& controller_constructor = Function::ZoneHandle(Z, |
| 6674 controller_class.LookupConstructorAllowPrivate( |
| 6675 Symbols::_AsyncStarStreamControllerConstructor())); |
| 6676 |
| 6677 // :await_jump_var = -1; |
| 6678 LocalVariable* jump_var = |
| 6679 current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 6680 LiteralNode* init_value = |
| 6681 new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1))); |
| 6682 current_block_->statements->Add( |
| 6683 new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value)); |
| 6684 |
| 6685 // Add to AST: |
| 6686 // :async_op = <closure>; (containing the original body) |
| 6687 LocalVariable* async_op_var = |
| 6688 current_block_->scope->LookupVariable(Symbols::AsyncOperation(), false); |
| 6689 ClosureNode* cn = new(Z) ClosureNode( |
| 6690 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); |
| 6691 StoreLocalNode* store_async_op = new (Z) StoreLocalNode( |
| 6692 Scanner::kNoSourcePos, |
| 6693 async_op_var, |
| 6694 cn); |
| 6695 current_block_->statements->Add(store_async_op); |
| 6696 |
| 6697 // :controller = new _AsyncStarStreamController(body_closure); |
| 6698 ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6699 ClosureNode* closure_obj = new(Z) ClosureNode( |
| 6700 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); |
| 6701 arguments->Add(closure_obj); |
| 6702 ConstructorCallNode* controller_constructor_call = |
| 6703 new(Z) ConstructorCallNode(Scanner::kNoSourcePos, |
| 6704 TypeArguments::ZoneHandle(Z), |
| 6705 controller_constructor, |
| 6706 arguments); |
| 6707 LocalVariable* controller_var = |
| 6708 current_block_->scope->LookupVariable(Symbols::Controller(), false); |
| 6709 StoreLocalNode* store_controller = |
| 6710 new(Z) StoreLocalNode(Scanner::kNoSourcePos, |
| 6711 controller_var, |
| 6712 controller_constructor_call); |
| 6713 current_block_->statements->Add(store_controller); |
| 6714 |
| 6715 // return :controller.stream; |
| 6716 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos, |
| 6717 new(Z) InstanceGetterNode(Scanner::kNoSourcePos, |
| 6718 new(Z) LoadLocalNode(Scanner::kNoSourcePos, |
| 6719 controller_var), |
| 6720 Symbols::Stream())); |
| 6721 current_block_->statements->Add(return_node); |
| 6722 return CloseBlock(); |
| 6723 } |
| 6724 |
| 6725 |
| 6726 void Parser::OpenAsyncGeneratorClosure() { |
| 6727 async_temp_scope_ = current_block_->scope; |
| 6728 OpenAsyncTryBlock(); |
| 6729 } |
| 6730 |
| 6731 |
| 6732 SequenceNode* Parser::CloseAsyncGeneratorClosure(SequenceNode* body) { |
| 6733 // TODO(hausner): Is the temporary expression necessary? |
| 6734 // We need a temporary expression to store intermediate return values. |
| 6735 parsed_function()->EnsureExpressionTemp(); |
| 6736 |
| 6737 SequenceNode* new_body = CloseAsyncGeneratorTryBlock(body); |
| 6738 ASSERT(new_body != NULL); |
| 6739 ASSERT(new_body->scope() != NULL); |
| 6740 |
| 6741 // Implicitly mark those variables below as captured. We currently mark all |
| 6742 // variables of all scopes as captured, but as soon as we do something |
| 6743 // smarter we rely on these internal variables to be available. |
| 6744 new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 6745 new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
| 6746 new_body->scope()->LookupVariable(Symbols::Controller(), false); |
| 6747 new_body->scope()->LookupVariable(Symbols::AsyncOperationParam(), false); |
| 6748 new_body->scope()->LookupVariable(Symbols::AsyncOperationErrorParam(), false); |
| 6749 new_body->scope()->LookupVariable( |
| 6750 Symbols::AsyncOperationStackTraceParam(), false); |
| 6751 new_body->scope()->RecursivelyCaptureAllVariables(); |
| 6752 return new_body; |
| 6753 } |
| 6754 |
| 6755 |
| 6375 SequenceNode* Parser::CloseBlock() { | 6756 SequenceNode* Parser::CloseBlock() { |
| 6376 SequenceNode* statements = current_block_->statements; | 6757 SequenceNode* statements = current_block_->statements; |
| 6377 if (current_block_->scope != NULL) { | 6758 if (current_block_->scope != NULL) { |
| 6378 // Record the begin and end token index of the scope. | 6759 // Record the begin and end token index of the scope. |
| 6379 ASSERT(statements != NULL); | 6760 ASSERT(statements != NULL); |
| 6380 current_block_->scope->set_begin_token_pos(statements->token_pos()); | 6761 current_block_->scope->set_begin_token_pos(statements->token_pos()); |
| 6381 current_block_->scope->set_end_token_pos(TokenPos()); | 6762 current_block_->scope->set_end_token_pos(TokenPos()); |
| 6382 } | 6763 } |
| 6383 current_block_ = current_block_->parent; | 6764 current_block_ = current_block_->parent; |
| 6384 return statements; | 6765 return statements; |
| (...skipping 1395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7780 AstNode* Parser::ParseAwaitForStatement(String* label_name) { | 8161 AstNode* Parser::ParseAwaitForStatement(String* label_name) { |
| 7781 TRACE_PARSER("ParseAwaitForStatement"); | 8162 TRACE_PARSER("ParseAwaitForStatement"); |
| 7782 ASSERT(IsAwaitKeyword()); | 8163 ASSERT(IsAwaitKeyword()); |
| 7783 const intptr_t await_for_pos = TokenPos(); | 8164 const intptr_t await_for_pos = TokenPos(); |
| 7784 ConsumeToken(); // await. | 8165 ConsumeToken(); // await. |
| 7785 ASSERT(CurrentToken() == Token::kFOR); | 8166 ASSERT(CurrentToken() == Token::kFOR); |
| 7786 ConsumeToken(); // for. | 8167 ConsumeToken(); // for. |
| 7787 ExpectToken(Token::kLPAREN); | 8168 ExpectToken(Token::kLPAREN); |
| 7788 | 8169 |
| 7789 if (!innermost_function().IsAsyncFunction() && | 8170 if (!innermost_function().IsAsyncFunction() && |
| 7790 !innermost_function().IsAsyncClosure()) { | 8171 !innermost_function().IsAsyncClosure() && |
| 8172 !innermost_function().IsAsyncGenerator() && |
| 8173 !innermost_function().IsAsyncGenClosure()) { |
| 7791 ReportError(await_for_pos, | 8174 ReportError(await_for_pos, |
| 7792 "await for loop is only allowed in async function"); | 8175 "await for loop is only allowed in an asynchronous function"); |
| 7793 } | 8176 } |
| 7794 | 8177 |
| 7795 // Parse loop variable. | 8178 // Parse loop variable. |
| 7796 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); | 8179 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); |
| 7797 if (CurrentToken() == Token::kCONST) { | 8180 if (CurrentToken() == Token::kCONST) { |
| 7798 ReportError("Loop variable cannot be 'const'"); | 8181 ReportError("Loop variable cannot be 'const'"); |
| 7799 } | 8182 } |
| 7800 bool new_loop_var = false; | 8183 bool new_loop_var = false; |
| 7801 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); | 8184 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); |
| 7802 if (LookaheadToken(1) != Token::kIN) { | 8185 if (LookaheadToken(1) != Token::kIN) { |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8220 | 8603 |
| 8221 // Populate local scope of the catch block with the saved exception and saved | 8604 // Populate local scope of the catch block with the saved exception and saved |
| 8222 // stack trace. | 8605 // stack trace. |
| 8223 void Parser::AddSavedExceptionAndStacktraceToScope( | 8606 void Parser::AddSavedExceptionAndStacktraceToScope( |
| 8224 LocalVariable* exception_var, | 8607 LocalVariable* exception_var, |
| 8225 LocalVariable* stack_trace_var, | 8608 LocalVariable* stack_trace_var, |
| 8226 LocalScope* scope) { | 8609 LocalScope* scope) { |
| 8227 ASSERT(innermost_function().IsAsyncClosure() || | 8610 ASSERT(innermost_function().IsAsyncClosure() || |
| 8228 innermost_function().IsAsyncFunction() || | 8611 innermost_function().IsAsyncFunction() || |
| 8229 innermost_function().IsSyncGenClosure() || | 8612 innermost_function().IsSyncGenClosure() || |
| 8230 innermost_function().IsSyncGenerator()); | 8613 innermost_function().IsSyncGenerator() || |
| 8614 innermost_function().IsAsyncGenerator() || |
| 8615 innermost_function().IsAsyncGenClosure()); |
| 8231 // Add :saved_exception_var and :saved_stack_trace_var to scope. | 8616 // Add :saved_exception_var and :saved_stack_trace_var to scope. |
| 8232 // They will automatically get captured. | 8617 // They will automatically get captured. |
| 8233 LocalVariable* saved_exception_var = new (Z) LocalVariable( | 8618 LocalVariable* saved_exception_var = new (Z) LocalVariable( |
| 8234 Scanner::kNoSourcePos, | 8619 Scanner::kNoSourcePos, |
| 8235 Symbols::SavedExceptionVar(), | 8620 Symbols::SavedExceptionVar(), |
| 8236 Type::ZoneHandle(Z, Type::DynamicType())); | 8621 Type::ZoneHandle(Z, Type::DynamicType())); |
| 8237 saved_exception_var->set_is_final(); | 8622 saved_exception_var->set_is_final(); |
| 8238 scope->AddVariable(saved_exception_var); | 8623 scope->AddVariable(saved_exception_var); |
| 8239 LocalVariable* saved_stack_trace_var = new (Z) LocalVariable( | 8624 LocalVariable* saved_stack_trace_var = new (Z) LocalVariable( |
| 8240 Scanner::kNoSourcePos, | 8625 Scanner::kNoSourcePos, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 8271 TRACE_PARSER("ParseFinallyBlock"); | 8656 TRACE_PARSER("ParseFinallyBlock"); |
| 8272 OpenBlock(); | 8657 OpenBlock(); |
| 8273 ExpectToken(Token::kLBRACE); | 8658 ExpectToken(Token::kLBRACE); |
| 8274 | 8659 |
| 8275 // In case of async closures we need to restore the saved try index of an | 8660 // In case of async closures we need to restore the saved try index of an |
| 8276 // outer try block (if it exists). The current try block has already been | 8661 // outer try block (if it exists). The current try block has already been |
| 8277 // removed from the stack of try blocks. | 8662 // removed from the stack of try blocks. |
| 8278 if ((innermost_function().IsAsyncClosure() || | 8663 if ((innermost_function().IsAsyncClosure() || |
| 8279 innermost_function().IsAsyncFunction() || | 8664 innermost_function().IsAsyncFunction() || |
| 8280 innermost_function().IsSyncGenClosure() || | 8665 innermost_function().IsSyncGenClosure() || |
| 8281 innermost_function().IsSyncGenerator()) && | 8666 innermost_function().IsSyncGenerator() || |
| 8667 innermost_function().IsAsyncGenerator() || |
| 8668 innermost_function().IsAsyncGenClosure()) && |
| 8282 (try_blocks_list_ != NULL)) { | 8669 (try_blocks_list_ != NULL)) { |
| 8283 // We need two unchain two scopes: finally clause, and the try block level. | 8670 // We need two unchain two scopes: finally clause, and the try block level. |
| 8284 RestoreSavedTryContext(current_block_->scope->parent()->parent(), | 8671 RestoreSavedTryContext(current_block_->scope->parent()->parent(), |
| 8285 try_blocks_list_->try_index(), | 8672 try_blocks_list_->try_index(), |
| 8286 current_block_->statements); | 8673 current_block_->statements); |
| 8287 } else { | 8674 } else { |
| 8288 parsed_function()->reset_saved_try_ctx_vars(); | 8675 parsed_function()->reset_saved_try_ctx_vars(); |
| 8289 } | 8676 } |
| 8290 | 8677 |
| 8291 ParseStatementSequence(); | 8678 ParseStatementSequence(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8380 } else { | 8767 } else { |
| 8381 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); | 8768 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 8382 } | 8769 } |
| 8383 if (CurrentToken() == Token::kCATCH) { | 8770 if (CurrentToken() == Token::kCATCH) { |
| 8384 ConsumeToken(); // Consume the 'catch'. | 8771 ConsumeToken(); // Consume the 'catch'. |
| 8385 ExpectToken(Token::kLPAREN); | 8772 ExpectToken(Token::kLPAREN); |
| 8386 exception_param.token_pos = TokenPos(); | 8773 exception_param.token_pos = TokenPos(); |
| 8387 exception_param.name = ExpectIdentifier("identifier expected"); | 8774 exception_param.name = ExpectIdentifier("identifier expected"); |
| 8388 if (CurrentToken() == Token::kCOMMA) { | 8775 if (CurrentToken() == Token::kCOMMA) { |
| 8389 ConsumeToken(); | 8776 ConsumeToken(); |
| 8390 // TODO(hausner): Make implicit type be StackTrace, not dynamic. | |
| 8391 stack_trace_param.type = | 8777 stack_trace_param.type = |
| 8392 &AbstractType::ZoneHandle(Z, Type::DynamicType()); | 8778 &AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 8393 stack_trace_param.token_pos = TokenPos(); | 8779 stack_trace_param.token_pos = TokenPos(); |
| 8394 stack_trace_param.name = ExpectIdentifier("identifier expected"); | 8780 stack_trace_param.name = ExpectIdentifier("identifier expected"); |
| 8395 } | 8781 } |
| 8396 ExpectToken(Token::kRPAREN); | 8782 ExpectToken(Token::kRPAREN); |
| 8397 } | 8783 } |
| 8398 | 8784 |
| 8399 // Create a block containing the catch clause parameters and the | 8785 // Create a block containing the catch clause parameters and the |
| 8400 // following code: | 8786 // following code: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 8419 // A stack trace variable is specified in this block, so generate code | 8805 // A stack trace variable is specified in this block, so generate code |
| 8420 // to load the stack trace object (:stack_trace_var) into the stack | 8806 // to load the stack trace object (:stack_trace_var) into the stack |
| 8421 // trace variable specified in this block. | 8807 // trace variable specified in this block. |
| 8422 *needs_stack_trace = true; | 8808 *needs_stack_trace = true; |
| 8423 ASSERT(stack_trace_var != NULL); | 8809 ASSERT(stack_trace_var != NULL); |
| 8424 current_block_->statements->Add(new(Z) StoreLocalNode( | 8810 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 8425 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( | 8811 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( |
| 8426 catch_pos, stack_trace_var))); | 8812 catch_pos, stack_trace_var))); |
| 8427 } | 8813 } |
| 8428 | 8814 |
| 8429 // Add nested block with user-defined code. This blocks allows | 8815 // Add nested block with user-defined code. This block allows |
| 8430 // declarations in the body to shadow the catch parameters. | 8816 // declarations in the body to shadow the catch parameters. |
| 8431 CheckToken(Token::kLBRACE); | 8817 CheckToken(Token::kLBRACE); |
| 8432 | 8818 |
| 8433 // In case of async closures we need to restore the saved try index of an | 8819 // In case of async closures we need to restore the saved try index of an |
| 8434 // outer try block (if it exists). | 8820 // outer try block (if it exists). |
| 8435 ASSERT(try_blocks_list_ != NULL); | 8821 ASSERT(try_blocks_list_ != NULL); |
| 8436 if (innermost_function().IsAsyncClosure() || | 8822 if (innermost_function().IsAsyncClosure() || |
| 8437 innermost_function().IsAsyncFunction() || | 8823 innermost_function().IsAsyncFunction() || |
| 8438 innermost_function().IsSyncGenClosure() || | 8824 innermost_function().IsSyncGenClosure() || |
| 8439 innermost_function().IsSyncGenerator()) { | 8825 innermost_function().IsSyncGenerator() || |
| 8826 innermost_function().IsAsyncGenerator() || |
| 8827 innermost_function().IsAsyncGenClosure()) { |
| 8440 if ((try_blocks_list_->outer_try_block() != NULL) && | 8828 if ((try_blocks_list_->outer_try_block() != NULL) && |
| 8441 (try_blocks_list_->outer_try_block()->try_block() | 8829 (try_blocks_list_->outer_try_block()->try_block() |
| 8442 ->scope->function_level() == | 8830 ->scope->function_level() == |
| 8443 current_block_->scope->function_level())) { | 8831 current_block_->scope->function_level())) { |
| 8444 // We need to unchain three scope levels: catch clause, catch | 8832 // We need to unchain three scope levels: catch clause, catch |
| 8445 // parameters, and the general try block. | 8833 // parameters, and the general try block. |
| 8446 RestoreSavedTryContext( | 8834 RestoreSavedTryContext( |
| 8447 current_block_->scope->parent()->parent()->parent(), | 8835 current_block_->scope->parent()->parent()->parent(), |
| 8448 try_blocks_list_->outer_try_block()->try_index(), | 8836 try_blocks_list_->outer_try_block()->try_index(), |
| 8449 current_block_->statements); | 8837 current_block_->statements); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8541 while (!type_tests.is_empty()) { | 8929 while (!type_tests.is_empty()) { |
| 8542 AstNode* type_test = type_tests.RemoveLast(); | 8930 AstNode* type_test = type_tests.RemoveLast(); |
| 8543 SequenceNode* catch_block = catch_blocks.RemoveLast(); | 8931 SequenceNode* catch_block = catch_blocks.RemoveLast(); |
| 8544 | 8932 |
| 8545 // In case of async closures we need to restore the saved try index of an | 8933 // In case of async closures we need to restore the saved try index of an |
| 8546 // outer try block (if it exists). | 8934 // outer try block (if it exists). |
| 8547 ASSERT(try_blocks_list_ != NULL); | 8935 ASSERT(try_blocks_list_ != NULL); |
| 8548 if (innermost_function().IsAsyncClosure() || | 8936 if (innermost_function().IsAsyncClosure() || |
| 8549 innermost_function().IsAsyncFunction() || | 8937 innermost_function().IsAsyncFunction() || |
| 8550 innermost_function().IsSyncGenClosure() || | 8938 innermost_function().IsSyncGenClosure() || |
| 8551 innermost_function().IsSyncGenerator()) { | 8939 innermost_function().IsSyncGenerator() || |
| 8940 innermost_function().IsAsyncGenerator() || |
| 8941 innermost_function().IsAsyncGenClosure()) { |
| 8552 if ((try_blocks_list_->outer_try_block() != NULL) && | 8942 if ((try_blocks_list_->outer_try_block() != NULL) && |
| 8553 (try_blocks_list_->outer_try_block()->try_block() | 8943 (try_blocks_list_->outer_try_block()->try_block() |
| 8554 ->scope->function_level() == | 8944 ->scope->function_level() == |
| 8555 current_block_->scope->function_level())) { | 8945 current_block_->scope->function_level())) { |
| 8556 // We need to unchain three scope levels: catch clause, catch | 8946 // We need to unchain three scope levels: catch clause, catch |
| 8557 // parameters, and the general try block. | 8947 // parameters, and the general try block. |
| 8558 RestoreSavedTryContext( | 8948 RestoreSavedTryContext( |
| 8559 current_block_->scope->parent()->parent(), | 8949 current_block_->scope->parent()->parent(), |
| 8560 try_blocks_list_->outer_try_block()->try_index(), | 8950 try_blocks_list_->outer_try_block()->try_index(), |
| 8561 current_block_->statements); | 8951 current_block_->statements); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8594 parsed_function()->set_async_saved_try_ctx_name(async_saved_try_ctx_name); | 8984 parsed_function()->set_async_saved_try_ctx_name(async_saved_try_ctx_name); |
| 8595 } | 8985 } |
| 8596 | 8986 |
| 8597 | 8987 |
| 8598 // Restore the currently relevant :saved_try_context_var on the stack | 8988 // Restore the currently relevant :saved_try_context_var on the stack |
| 8599 // from the captured :async_saved_try_ctx_var_. | 8989 // from the captured :async_saved_try_ctx_var_. |
| 8600 // * Try blocks: Set the context variable for this try block. | 8990 // * Try blocks: Set the context variable for this try block. |
| 8601 // * Catch/finally blocks: Set the context variable for any outer try block (if | 8991 // * Catch/finally blocks: Set the context variable for any outer try block (if |
| 8602 // existent). | 8992 // existent). |
| 8603 // | 8993 // |
| 8604 // Also save the captured variable and the stack variable to be able to set | 8994 // Also save the captured variable and the stack variable in the parsed |
| 8605 // it after a function continues execution (await). | 8995 // function so we are able to set it after a function continues |
| 8996 // execution (await/yield). |
| 8606 void Parser::RestoreSavedTryContext(LocalScope* saved_try_context_scope, | 8997 void Parser::RestoreSavedTryContext(LocalScope* saved_try_context_scope, |
| 8607 int16_t try_index, | 8998 int16_t try_index, |
| 8608 SequenceNode* target) { | 8999 SequenceNode* target) { |
| 8609 LocalVariable* saved_try_ctx = saved_try_context_scope->LookupVariable( | 9000 LocalVariable* saved_try_ctx = saved_try_context_scope->LookupVariable( |
| 8610 Symbols::SavedTryContextVar(), false); | 9001 Symbols::SavedTryContextVar(), false); |
| 8611 ASSERT((saved_try_ctx != NULL) && !saved_try_ctx->is_captured()); | 9002 ASSERT((saved_try_ctx != NULL) && !saved_try_ctx->is_captured()); |
| 8612 const String& async_saved_try_ctx_name = | 9003 const String& async_saved_try_ctx_name = |
| 8613 BuildAsyncSavedTryContextName(Z, try_index); | 9004 BuildAsyncSavedTryContextName(Z, try_index); |
| 8614 LocalVariable* async_saved_try_ctx = | 9005 LocalVariable* async_saved_try_ctx = |
| 8615 target->scope()->LookupVariable(async_saved_try_ctx_name, false); | 9006 target->scope()->LookupVariable(async_saved_try_ctx_name, false); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8680 } | 9071 } |
| 8681 | 9072 |
| 8682 // Now parse the 'try' block. | 9073 // Now parse the 'try' block. |
| 8683 OpenBlock(); | 9074 OpenBlock(); |
| 8684 PushTryBlock(current_block_); | 9075 PushTryBlock(current_block_); |
| 8685 ExpectToken(Token::kLBRACE); | 9076 ExpectToken(Token::kLBRACE); |
| 8686 | 9077 |
| 8687 if (innermost_function().IsAsyncClosure() || | 9078 if (innermost_function().IsAsyncClosure() || |
| 8688 innermost_function().IsAsyncFunction() || | 9079 innermost_function().IsAsyncFunction() || |
| 8689 innermost_function().IsSyncGenClosure() || | 9080 innermost_function().IsSyncGenClosure() || |
| 8690 innermost_function().IsSyncGenerator()) { | 9081 innermost_function().IsSyncGenerator() || |
| 9082 innermost_function().IsAsyncGenerator() || |
| 9083 innermost_function().IsAsyncGenClosure()) { |
| 8691 SetupSavedTryContext(context_var); | 9084 SetupSavedTryContext(context_var); |
| 8692 } | 9085 } |
| 8693 | 9086 |
| 8694 ParseStatementSequence(); | 9087 ParseStatementSequence(); |
| 8695 ExpectToken(Token::kRBRACE); | 9088 ExpectToken(Token::kRBRACE); |
| 8696 SequenceNode* try_block = CloseBlock(); | 9089 SequenceNode* try_block = CloseBlock(); |
| 8697 | 9090 |
| 8698 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 9091 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
| 8699 (CurrentToken() != Token::kFINALLY)) { | 9092 (CurrentToken() != Token::kFINALLY)) { |
| 8700 ReportError("catch or finally clause expected"); | 9093 ReportError("catch or finally clause expected"); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8824 ReportError(jump_pos, "'break' to case clause label is illegal"); | 9217 ReportError(jump_pos, "'break' to case clause label is illegal"); |
| 8825 } | 9218 } |
| 8826 if (target->FunctionLevel() != current_block_->scope->function_level()) { | 9219 if (target->FunctionLevel() != current_block_->scope->function_level()) { |
| 8827 ReportError(jump_pos, "'%s' target must be in same function context", | 9220 ReportError(jump_pos, "'%s' target must be in same function context", |
| 8828 Token::Str(jump_kind)); | 9221 Token::Str(jump_kind)); |
| 8829 } | 9222 } |
| 8830 return new(Z) JumpNode(jump_pos, jump_kind, target); | 9223 return new(Z) JumpNode(jump_pos, jump_kind, target); |
| 8831 } | 9224 } |
| 8832 | 9225 |
| 8833 | 9226 |
| 9227 AstNode* Parser::ParseYieldStatement() { |
| 9228 bool is_yield_each = false; |
| 9229 const intptr_t yield_pos = TokenPos(); |
| 9230 ConsumeToken(); // yield reserved word. |
| 9231 ASSERT(innermost_function().IsGenerator() || |
| 9232 innermost_function().IsSyncGenClosure() || |
| 9233 innermost_function().IsAsyncGenerator() || |
| 9234 innermost_function().IsAsyncGenClosure()); |
| 9235 if (CurrentToken() == Token::kMUL) { |
| 9236 is_yield_each = true; |
| 9237 ConsumeToken(); |
| 9238 } |
| 9239 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 9240 |
| 9241 LetNode* yield = new(Z) LetNode(yield_pos); |
| 9242 if (innermost_function().IsSyncGenerator() || |
| 9243 innermost_function().IsSyncGenClosure()) { |
| 9244 // Yield statement in sync* function. |
| 9245 |
| 9246 LocalVariable* iterator_param = |
| 9247 LookupLocalScope(Symbols::IteratorParameter()); |
| 9248 ASSERT(iterator_param != NULL); |
| 9249 // Generate :iterator.current = expr; |
| 9250 AstNode* iterator = |
| 9251 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param); |
| 9252 AstNode* store_current = |
| 9253 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, |
| 9254 iterator, |
| 9255 String::ZoneHandle(Symbols::Current().raw()), |
| 9256 expr); |
| 9257 yield->AddNode(store_current); |
| 9258 if (is_yield_each) { |
| 9259 // Generate :iterator.isYieldEach = true; |
| 9260 AstNode* set_is_yield_each = |
| 9261 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, |
| 9262 iterator, |
| 9263 String::ZoneHandle(Symbols::IsYieldEach().raw()), |
| 9264 new(Z) LiteralNode(TokenPos(), Bool::True())); |
| 9265 yield->AddNode(set_is_yield_each); |
| 9266 } |
| 9267 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); |
| 9268 await_marker->set_scope(current_block_->scope); |
| 9269 yield->AddNode(await_marker); |
| 9270 // Return true to indicate that a value has been generated. |
| 9271 ReturnNode* return_true = new(Z) ReturnNode(yield_pos, |
| 9272 new(Z) LiteralNode(TokenPos(), Bool::True())); |
| 9273 return_true->set_return_type(ReturnNode::kContinuationTarget); |
| 9274 yield->AddNode(return_true); |
| 9275 |
| 9276 // If this expression is part of a try block, also append the code for |
| 9277 // restoring the saved try context that lives on the stack. |
| 9278 const String& async_saved_try_ctx_name = |
| 9279 String::Handle(Z, parsed_function()->async_saved_try_ctx_name()); |
| 9280 if (!async_saved_try_ctx_name.IsNull()) { |
| 9281 LocalVariable* async_saved_try_ctx = |
| 9282 current_block_->scope->LookupVariable(async_saved_try_ctx_name, |
| 9283 false); |
| 9284 ASSERT(async_saved_try_ctx != NULL); |
| 9285 yield->AddNode(new (Z) StoreLocalNode( |
| 9286 Scanner::kNoSourcePos, |
| 9287 parsed_function()->saved_try_ctx(), |
| 9288 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx))); |
| 9289 } |
| 9290 } else { |
| 9291 // yield statement in async* function. |
| 9292 ASSERT(innermost_function().IsAsyncGenerator() || |
| 9293 innermost_function().IsAsyncGenClosure()); |
| 9294 |
| 9295 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller()); |
| 9296 ASSERT(controller_var != NULL); |
| 9297 // :controller.add[Stream](expr); |
| 9298 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos); |
| 9299 add_args->Add(expr); |
| 9300 AstNode* add_call = |
| 9301 new(Z) InstanceCallNode(yield_pos, |
| 9302 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var), |
| 9303 is_yield_each ? Symbols::AddStream() : Symbols::add(), |
| 9304 add_args); |
| 9305 |
| 9306 |
| 9307 // if (:controller.add[Stream](expr)) { |
| 9308 // return; |
| 9309 // } |
| 9310 // await_marker; |
| 9311 // continuation_return; |
| 9312 // |
| 9313 |
| 9314 SequenceNode* true_branch = |
| 9315 new(Z) SequenceNode(Scanner::kNoSourcePos, current_block_->scope); |
| 9316 AstNode* return_from_generator = new(Z) ReturnNode(yield_pos); |
| 9317 true_branch->Add(return_from_generator); |
| 9318 AddNodeForFinallyInlining(return_from_generator); |
| 9319 AstNode* if_is_cancelled = |
| 9320 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL); |
| 9321 yield->AddNode(if_is_cancelled); |
| 9322 |
| 9323 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); |
| 9324 await_marker->set_scope(current_block_->scope); |
| 9325 yield->AddNode(await_marker); |
| 9326 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos); |
| 9327 continuation_return->set_return_type(ReturnNode::kContinuationTarget); |
| 9328 yield->AddNode(continuation_return); |
| 9329 |
| 9330 // If this expression is part of a try block, also append the code for |
| 9331 // restoring the saved try context that lives on the stack. |
| 9332 const String& async_saved_try_ctx_name = |
| 9333 String::Handle(Z, parsed_function()->async_saved_try_ctx_name()); |
| 9334 if (!async_saved_try_ctx_name.IsNull()) { |
| 9335 LocalVariable* async_saved_try_ctx = |
| 9336 current_block_->scope->LookupVariable(async_saved_try_ctx_name, |
| 9337 false); |
| 9338 ASSERT(async_saved_try_ctx != NULL); |
| 9339 yield->AddNode(new (Z) StoreLocalNode( |
| 9340 Scanner::kNoSourcePos, |
| 9341 parsed_function()->saved_try_ctx(), |
| 9342 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx))); |
| 9343 } |
| 9344 } |
| 9345 return yield; |
| 9346 } |
| 9347 |
| 9348 |
| 8834 AstNode* Parser::ParseStatement() { | 9349 AstNode* Parser::ParseStatement() { |
| 8835 TRACE_PARSER("ParseStatement"); | 9350 TRACE_PARSER("ParseStatement"); |
| 8836 AstNode* statement = NULL; | 9351 AstNode* statement = NULL; |
| 8837 intptr_t label_pos = 0; | 9352 intptr_t label_pos = 0; |
| 8838 String* label_name = NULL; | 9353 String* label_name = NULL; |
| 8839 if (IsIdentifier()) { | 9354 if (IsIdentifier()) { |
| 8840 if (LookaheadToken(1) == Token::kCOLON) { | 9355 if (LookaheadToken(1) == Token::kCOLON) { |
| 8841 // Statement starts with a label. | 9356 // Statement starts with a label. |
| 8842 label_name = CurrentLiteral(); | 9357 label_name = CurrentLiteral(); |
| 8843 label_pos = TokenPos(); | 9358 label_pos = TokenPos(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 8863 statement = ParseTryStatement(label_name); | 9378 statement = ParseTryStatement(label_name); |
| 8864 } else if (token == Token::kRETURN) { | 9379 } else if (token == Token::kRETURN) { |
| 8865 const intptr_t return_pos = TokenPos(); | 9380 const intptr_t return_pos = TokenPos(); |
| 8866 ConsumeToken(); | 9381 ConsumeToken(); |
| 8867 if (CurrentToken() != Token::kSEMICOLON) { | 9382 if (CurrentToken() != Token::kSEMICOLON) { |
| 8868 const intptr_t expr_pos = TokenPos(); | 9383 const intptr_t expr_pos = TokenPos(); |
| 8869 if (current_function().IsGenerativeConstructor() && | 9384 if (current_function().IsGenerativeConstructor() && |
| 8870 (current_block_->scope->function_level() == 0)) { | 9385 (current_block_->scope->function_level() == 0)) { |
| 8871 ReportError(expr_pos, | 9386 ReportError(expr_pos, |
| 8872 "return of a value is not allowed in constructors"); | 9387 "return of a value is not allowed in constructors"); |
| 8873 } else if (current_function().IsGenerator()) { | 9388 } else if (current_function().IsGeneratorClosure() && |
| 9389 (current_block_->scope->function_level() == 0)) { |
| 8874 ReportError(expr_pos, "generator functions may not return a value"); | 9390 ReportError(expr_pos, "generator functions may not return a value"); |
| 8875 } | 9391 } |
| 8876 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 9392 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 8877 statement = new(Z) ReturnNode(statement_pos, expr); | 9393 statement = new(Z) ReturnNode(statement_pos, expr); |
| 8878 } else { | 9394 } else { |
| 8879 if (current_function().IsSyncGenClosure() && | 9395 if (current_function().IsSyncGenClosure() && |
| 8880 (current_block_->scope->function_level() == 0)) { | 9396 (current_block_->scope->function_level() == 0)) { |
| 8881 // In a synchronous generator, return without an expression | 9397 // In a synchronous generator, return without an expression |
| 8882 // returns false, signaling that the iterator terminates and | 9398 // returns false, signaling that the iterator terminates and |
| 8883 // did not yield a value. | 9399 // did not yield a value. |
| 8884 statement = new(Z) ReturnNode(statement_pos, | 9400 statement = new(Z) ReturnNode(statement_pos, |
| 8885 new(Z) LiteralNode(return_pos, Bool::False())); | 9401 new(Z) LiteralNode(return_pos, Bool::False())); |
| 8886 } else { | 9402 } else { |
| 8887 statement = new(Z) ReturnNode(statement_pos); | 9403 statement = new(Z) ReturnNode(statement_pos); |
| 8888 } | 9404 } |
| 8889 } | 9405 } |
| 8890 AddNodeForFinallyInlining(statement); | 9406 AddNodeForFinallyInlining(statement); |
| 8891 ExpectSemicolon(); | 9407 ExpectSemicolon(); |
| 8892 } else if (IsYieldKeyword()) { | 9408 } else if (IsYieldKeyword()) { |
| 8893 bool is_yield_each = false; | 9409 statement = ParseYieldStatement(); |
| 8894 ConsumeToken(); | |
| 8895 ASSERT(innermost_function().IsGenerator() || | |
| 8896 innermost_function().IsSyncGenClosure()); | |
| 8897 if (CurrentToken() == Token::kMUL) { | |
| 8898 is_yield_each = true; | |
| 8899 ConsumeToken(); | |
| 8900 } | |
| 8901 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | |
| 8902 LocalVariable* iterator_param = | |
| 8903 LookupLocalScope(Symbols::IteratorParameter()); | |
| 8904 ASSERT(iterator_param != NULL); | |
| 8905 // Generate :iterator.current = expr; | |
| 8906 AstNode* iterator = | |
| 8907 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param); | |
| 8908 AstNode* store_current = | |
| 8909 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 8910 iterator, | |
| 8911 String::ZoneHandle(Symbols::Current().raw()), | |
| 8912 expr); | |
| 8913 LetNode* yield = new(Z) LetNode(statement_pos); | |
| 8914 yield->AddNode(store_current); | |
| 8915 if (is_yield_each) { | |
| 8916 // Generate :iterator.isYieldEach = true; | |
| 8917 AstNode* set_is_yield_each = | |
| 8918 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 8919 iterator, | |
| 8920 String::ZoneHandle(Symbols::IsYieldEach().raw()), | |
| 8921 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 8922 yield->AddNode(set_is_yield_each); | |
| 8923 } | |
| 8924 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); | |
| 8925 await_marker->set_scope(current_block_->scope); | |
| 8926 yield->AddNode(await_marker); | |
| 8927 // Return true to indicate that a value has been generated. | |
| 8928 ReturnNode* return_true = new(Z) ReturnNode(statement_pos, | |
| 8929 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 8930 return_true->set_return_type(ReturnNode::kContinuationTarget); | |
| 8931 yield->AddNode(return_true); | |
| 8932 | |
| 8933 // If this expression is part of a try block, also append the code for | |
| 8934 // restoring the saved try context that lives on the stack. | |
| 8935 const String& async_saved_try_ctx_name = | |
| 8936 String::Handle(Z, parsed_function()->async_saved_try_ctx_name()); | |
| 8937 if (!async_saved_try_ctx_name.IsNull()) { | |
| 8938 LocalVariable* async_saved_try_ctx = | |
| 8939 current_block_->scope->LookupVariable(async_saved_try_ctx_name, | |
| 8940 false); | |
| 8941 ASSERT(async_saved_try_ctx != NULL); | |
| 8942 yield->AddNode(new (Z) StoreLocalNode( | |
| 8943 Scanner::kNoSourcePos, | |
| 8944 parsed_function()->saved_try_ctx(), | |
| 8945 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx))); | |
| 8946 } | |
| 8947 | |
| 8948 statement = yield; | |
| 8949 ExpectSemicolon(); | 9410 ExpectSemicolon(); |
| 8950 } else if (token == Token::kIF) { | 9411 } else if (token == Token::kIF) { |
| 8951 statement = ParseIfStatement(label_name); | 9412 statement = ParseIfStatement(label_name); |
| 8952 } else if (token == Token::kASSERT) { | 9413 } else if (token == Token::kASSERT) { |
| 8953 statement = ParseAssertStatement(); | 9414 statement = ParseAssertStatement(); |
| 8954 ExpectSemicolon(); | 9415 ExpectSemicolon(); |
| 8955 } else if (IsVariableDeclaration()) { | 9416 } else if (IsVariableDeclaration()) { |
| 8956 statement = ParseVariableDeclarationList(); | 9417 statement = ParseVariableDeclarationList(); |
| 8957 ExpectSemicolon(); | 9418 ExpectSemicolon(); |
| 8958 } else if (IsFunctionDeclaration()) { | 9419 } else if (IsFunctionDeclaration()) { |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9804 } | 10265 } |
| 9805 | 10266 |
| 9806 | 10267 |
| 9807 AstNode* Parser::ParseUnaryExpr() { | 10268 AstNode* Parser::ParseUnaryExpr() { |
| 9808 TRACE_PARSER("ParseUnaryExpr"); | 10269 TRACE_PARSER("ParseUnaryExpr"); |
| 9809 AstNode* expr = NULL; | 10270 AstNode* expr = NULL; |
| 9810 const intptr_t op_pos = TokenPos(); | 10271 const intptr_t op_pos = TokenPos(); |
| 9811 if (IsAwaitKeyword()) { | 10272 if (IsAwaitKeyword()) { |
| 9812 TRACE_PARSER("ParseAwaitExpr"); | 10273 TRACE_PARSER("ParseAwaitExpr"); |
| 9813 if (!innermost_function().IsAsyncFunction() && | 10274 if (!innermost_function().IsAsyncFunction() && |
| 9814 !innermost_function().IsAsyncClosure()) { | 10275 !innermost_function().IsAsyncClosure() && |
| 9815 ReportError("await operator is only allowed in async function"); | 10276 !innermost_function().IsAsyncGenerator() && |
| 10277 !innermost_function().IsAsyncGenClosure()) { |
| 10278 ReportError("await operator is only allowed in an asynchronous function"); |
| 9816 } | 10279 } |
| 9817 ConsumeToken(); | 10280 ConsumeToken(); |
| 9818 parsed_function()->record_await(); | 10281 parsed_function()->record_await(); |
| 9819 expr = new (Z) AwaitNode(op_pos, ParseUnaryExpr()); | 10282 expr = new (Z) AwaitNode(op_pos, ParseUnaryExpr()); |
| 9820 } else if (IsPrefixOperator(CurrentToken())) { | 10283 } else if (IsPrefixOperator(CurrentToken())) { |
| 9821 Token::Kind unary_op = CurrentToken(); | 10284 Token::Kind unary_op = CurrentToken(); |
| 9822 if (unary_op == Token::kSUB) { | 10285 if (unary_op == Token::kSUB) { |
| 9823 unary_op = Token::kNEGATE; | 10286 unary_op = Token::kNEGATE; |
| 9824 } | 10287 } |
| 9825 ConsumeToken(); | 10288 ConsumeToken(); |
| (...skipping 2816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12642 void Parser::SkipQualIdent() { | 13105 void Parser::SkipQualIdent() { |
| 12643 ASSERT(IsIdentifier()); | 13106 ASSERT(IsIdentifier()); |
| 12644 ConsumeToken(); | 13107 ConsumeToken(); |
| 12645 if (CurrentToken() == Token::kPERIOD) { | 13108 if (CurrentToken() == Token::kPERIOD) { |
| 12646 ConsumeToken(); // Consume the kPERIOD token. | 13109 ConsumeToken(); // Consume the kPERIOD token. |
| 12647 ExpectIdentifier("identifier expected after '.'"); | 13110 ExpectIdentifier("identifier expected after '.'"); |
| 12648 } | 13111 } |
| 12649 } | 13112 } |
| 12650 | 13113 |
| 12651 } // namespace dart | 13114 } // namespace dart |
| OLD | NEW |