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