| 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 // 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |