Chromium Code Reviews| 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 3086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3097 AddFormalParamsToScope(¶ms, current_block_->scope); | 3097 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 3098 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); | 3098 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); |
| 3099 if (!Function::Handle(func.parent_function()).IsGetterFunction()) { | 3099 if (!Function::Handle(func.parent_function()).IsGetterFunction()) { |
| 3100 // Parse and discard any formal parameters. They are accessed as | 3100 // Parse and discard any formal parameters. They are accessed as |
| 3101 // context variables. | 3101 // context variables. |
| 3102 ParamList discarded_params; | 3102 ParamList discarded_params; |
| 3103 ParseFormalParameterList(allow_explicit_default_values, | 3103 ParseFormalParameterList(allow_explicit_default_values, |
| 3104 false, | 3104 false, |
| 3105 &discarded_params); | 3105 &discarded_params); |
| 3106 } | 3106 } |
| 3107 } else if (func.IsAsyncGenClosure()) { | |
| 3108 AddAsyncGenClosureParameters(¶ms); | |
| 3109 SetupDefaultsForOptionalParams(¶ms, default_parameter_values); | |
| 3110 AddFormalParamsToScope(¶ms, current_block_->scope); | |
| 3111 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); | |
| 3112 if (!Function::Handle(func.parent_function()).IsGetterFunction()) { | |
| 3113 // Parse and discard any formal parameters. They are accessed as | |
| 3114 // context variables. | |
| 3115 ParamList discarded_params; | |
| 3116 ParseFormalParameterList(allow_explicit_default_values, | |
| 3117 false, | |
| 3118 &discarded_params); | |
| 3119 } | |
| 3107 } else { | 3120 } else { |
| 3108 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); | 3121 ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); |
| 3109 | 3122 |
| 3110 // The number of parameters and their type are not yet set in local | 3123 // The number of parameters and their type are not yet set in local |
| 3111 // functions, since they are not 'top-level' parsed. | 3124 // functions, since they are not 'top-level' parsed. |
| 3112 if (func.IsLocalFunction()) { | 3125 if (func.IsLocalFunction()) { |
| 3113 AddFormalParamsToFunction(¶ms, func); | 3126 AddFormalParamsToFunction(¶ms, func); |
| 3114 } | 3127 } |
| 3115 SetupDefaultsForOptionalParams(¶ms, default_parameter_values); | 3128 SetupDefaultsForOptionalParams(¶ms, default_parameter_values); |
| 3116 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); | 3129 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3165 ASSERT(func.is_debuggable()); | 3178 ASSERT(func.is_debuggable()); |
| 3166 OpenAsyncClosure(); | 3179 OpenAsyncClosure(); |
| 3167 } else if (func.IsSyncGenerator()) { | 3180 } else if (func.IsSyncGenerator()) { |
| 3168 // The code of a sync generator is synthesized. Disable debugging. | 3181 // The code of a sync generator is synthesized. Disable debugging. |
| 3169 func.set_is_debuggable(false); | 3182 func.set_is_debuggable(false); |
| 3170 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos()); | 3183 generated_body_closure = OpenSyncGeneratorFunction(func.token_pos()); |
| 3171 } else if (func.IsSyncGenClosure()) { | 3184 } else if (func.IsSyncGenClosure()) { |
| 3172 // The closure containing the body of a sync generator is debuggable. | 3185 // The closure containing the body of a sync generator is debuggable. |
| 3173 ASSERT(func.is_debuggable()); | 3186 ASSERT(func.is_debuggable()); |
| 3174 async_temp_scope_ = current_block_->scope; | 3187 async_temp_scope_ = current_block_->scope; |
| 3188 } else if (func.IsAsyncGenerator()) { | |
| 3189 func.set_is_debuggable(false); | |
| 3190 generated_body_closure = OpenAsyncGeneratorFunction(func.token_pos()); | |
| 3191 } else if (func.IsAsyncGenClosure()) { | |
| 3192 // The closure containing the body of an async* function is debuggable. | |
| 3193 ASSERT(func.is_debuggable()); | |
| 3194 OpenAsyncGeneratorClosure(); | |
| 3175 } | 3195 } |
| 3176 | 3196 |
| 3177 BoolScope allow_await(&this->await_is_keyword_, | 3197 BoolScope allow_await(&this->await_is_keyword_, |
| 3178 func.IsAsyncOrGenerator() || func.is_generated_body()); | 3198 func.IsAsyncOrGenerator() || func.is_generated_body()); |
| 3179 intptr_t end_token_pos = 0; | 3199 intptr_t end_token_pos = 0; |
| 3180 if (CurrentToken() == Token::kLBRACE) { | 3200 if (CurrentToken() == Token::kLBRACE) { |
| 3181 ConsumeToken(); | 3201 ConsumeToken(); |
| 3182 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { | 3202 if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) { |
| 3183 const Class& owner = Class::Handle(Z, func.Owner()); | 3203 const Class& owner = Class::Handle(Z, func.Owner()); |
| 3184 if (!owner.IsObjectClass()) { | 3204 if (!owner.IsObjectClass()) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3242 if (func.IsAsyncFunction()) { | 3262 if (func.IsAsyncFunction()) { |
| 3243 body = CloseAsyncFunction(generated_body_closure, body); | 3263 body = CloseAsyncFunction(generated_body_closure, body); |
| 3244 generated_body_closure.set_end_token_pos(end_token_pos); | 3264 generated_body_closure.set_end_token_pos(end_token_pos); |
| 3245 } else if (func.IsAsyncClosure()) { | 3265 } else if (func.IsAsyncClosure()) { |
| 3246 body = CloseAsyncClosure(body); | 3266 body = CloseAsyncClosure(body); |
| 3247 } else if (func.IsSyncGenerator()) { | 3267 } else if (func.IsSyncGenerator()) { |
| 3248 body = CloseSyncGenFunction(generated_body_closure, body); | 3268 body = CloseSyncGenFunction(generated_body_closure, body); |
| 3249 generated_body_closure.set_end_token_pos(end_token_pos); | 3269 generated_body_closure.set_end_token_pos(end_token_pos); |
| 3250 } else if (func.IsSyncGenClosure()) { | 3270 } else if (func.IsSyncGenClosure()) { |
| 3251 body->scope()->RecursivelyCaptureAllVariables(); | 3271 body->scope()->RecursivelyCaptureAllVariables(); |
| 3272 } else if (func.IsAsyncGenerator()) { | |
| 3273 body = CloseAsyncGeneratorFunction(generated_body_closure, body); | |
| 3274 generated_body_closure.set_end_token_pos(end_token_pos); | |
| 3275 } else if (func.IsAsyncGenClosure()) { | |
| 3276 body = CloseAsyncGeneratorClosure(body); | |
| 3252 } | 3277 } |
| 3253 current_block_->statements->Add(body); | 3278 current_block_->statements->Add(body); |
| 3254 innermost_function_ = saved_innermost_function.raw(); | 3279 innermost_function_ = saved_innermost_function.raw(); |
| 3255 last_used_try_index_ = saved_try_index; | 3280 last_used_try_index_ = saved_try_index; |
| 3256 async_temp_scope_ = saved_async_temp_scope; | 3281 async_temp_scope_ = saved_async_temp_scope; |
| 3257 parsed_function()->set_saved_try_ctx(saved_saved_try_ctx); | 3282 parsed_function()->set_saved_try_ctx(saved_saved_try_ctx); |
| 3258 parsed_function()->set_async_saved_try_ctx_name( | 3283 parsed_function()->set_async_saved_try_ctx_name( |
| 3259 saved_async_saved_try_ctx_name); | 3284 saved_async_saved_try_ctx_name); |
| 3260 return CloseBlock(); | 3285 return CloseBlock(); |
| 3261 } | 3286 } |
| (...skipping 1980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5242 ExpectSemicolon(); // Reports error. | 5267 ExpectSemicolon(); // Reports error. |
| 5243 } | 5268 } |
| 5244 } | 5269 } |
| 5245 } | 5270 } |
| 5246 | 5271 |
| 5247 | 5272 |
| 5248 RawFunction::AsyncModifier Parser::ParseFunctionModifier() { | 5273 RawFunction::AsyncModifier Parser::ParseFunctionModifier() { |
| 5249 if (CurrentLiteral()->raw() == Symbols::Async().raw()) { | 5274 if (CurrentLiteral()->raw() == Symbols::Async().raw()) { |
| 5250 ConsumeToken(); | 5275 ConsumeToken(); |
| 5251 if (CurrentToken() == Token::kMUL) { | 5276 if (CurrentToken() == Token::kMUL) { |
| 5252 ReportError("async* generator functions are not yet supported"); | 5277 const bool enableAsyncStar = true; |
| 5278 if (!enableAsyncStar) { | |
| 5279 ReportError("async* generator functions are not yet supported"); | |
| 5280 } | |
| 5253 ConsumeToken(); | 5281 ConsumeToken(); |
| 5254 return RawFunction::kAsyncGen; | 5282 return RawFunction::kAsyncGen; |
| 5255 } else { | 5283 } else { |
| 5256 return RawFunction::kAsync; | 5284 return RawFunction::kAsync; |
| 5257 } | 5285 } |
| 5258 } else if ((CurrentLiteral()->raw() == Symbols::Sync().raw()) && | 5286 } else if ((CurrentLiteral()->raw() == Symbols::Sync().raw()) && |
| 5259 (LookaheadToken(1) == Token::kMUL)) { | 5287 (LookaheadToken(1) == Token::kMUL)) { |
| 5260 const bool enableSyncStar = true; | 5288 const bool enableSyncStar = true; |
| 5261 if (!enableSyncStar) { | 5289 if (!enableSyncStar) { |
| 5262 ReportError("sync* generator functions are not yet supported"); | 5290 ReportError("sync* generator functions are not yet supported"); |
| (...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5933 | 5961 |
| 5934 void Parser::OpenAsyncClosure() { | 5962 void Parser::OpenAsyncClosure() { |
| 5935 TRACE_PARSER("OpenAsyncClosure"); | 5963 TRACE_PARSER("OpenAsyncClosure"); |
| 5936 | 5964 |
| 5937 async_temp_scope_ = current_block_->scope; | 5965 async_temp_scope_ = current_block_->scope; |
| 5938 | 5966 |
| 5939 OpenAsyncTryBlock(); | 5967 OpenAsyncTryBlock(); |
| 5940 } | 5968 } |
| 5941 | 5969 |
| 5942 | 5970 |
| 5943 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { | 5971 SequenceNode* Parser::CloseAsyncGeneratorTryBlock(SequenceNode *body) { |
| 5972 TRACE_PARSER("CloseAsyncGeneratorTryBlock"); | |
| 5973 // The generated try-catch-finally that wraps the async generator function | |
| 5974 // body is the outermost try statement. | |
| 5975 ASSERT(try_blocks_list_ != NULL); | |
| 5976 ASSERT(try_blocks_list_->outer_try_block() == NULL); | |
| 5977 // We only get here when parsing an async generator body. | |
| 5978 ASSERT(innermost_function().IsAsyncGenClosure()); | |
| 5979 | |
| 5980 // The try-block (closure body code) has been parsed. We are now | |
| 5981 // generating the code for the catch block. | |
| 5944 try_blocks_list_->enter_catch(); | 5982 try_blocks_list_->enter_catch(); |
| 5983 OpenBlock(); // Catch handler list. | |
| 5984 OpenBlock(); // Catch block. | |
| 5945 | 5985 |
| 5946 OpenBlock(); | 5986 // Add the exception and stack trace parameters to the scope. |
| 5947 OpenBlock(); | |
| 5948 const AbstractType& dynamic_type = | 5987 const AbstractType& dynamic_type = |
| 5949 AbstractType::ZoneHandle(Z, Type::DynamicType()); | 5988 AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 5950 CatchParamDesc exception_param; | 5989 CatchParamDesc exception_param; |
| 5951 CatchParamDesc stack_trace_param; | 5990 CatchParamDesc stack_trace_param; |
| 5952 exception_param.token_pos = Scanner::kNoSourcePos; | 5991 exception_param.token_pos = Scanner::kNoSourcePos; |
| 5953 exception_param.type = &dynamic_type; | 5992 exception_param.type = &dynamic_type; |
| 5954 exception_param.name = &Symbols::ExceptionParameter(); | 5993 exception_param.name = &Symbols::ExceptionParameter(); |
| 5955 stack_trace_param.token_pos = Scanner::kNoSourcePos; | 5994 stack_trace_param.token_pos = Scanner::kNoSourcePos; |
| 5956 stack_trace_param.type = &dynamic_type; | 5995 stack_trace_param.type = &dynamic_type; |
| 5957 stack_trace_param.name = &Symbols::StackTraceParameter(); | 5996 stack_trace_param.name = &Symbols::StackTraceParameter(); |
| 5958 | |
| 5959 AddCatchParamsToScope( | 5997 AddCatchParamsToScope( |
| 5960 &exception_param, &stack_trace_param, current_block_->scope); | 5998 &exception_param, &stack_trace_param, current_block_->scope); |
| 5961 | 5999 |
| 6000 // Generate code to save the exception object and stack trace | |
| 6001 // in local variables. | |
| 5962 LocalVariable* context_var = current_block_->scope->LookupVariable( | 6002 LocalVariable* context_var = current_block_->scope->LookupVariable( |
| 5963 Symbols::SavedTryContextVar(), false); | 6003 Symbols::SavedTryContextVar(), false); |
| 5964 ASSERT(context_var != NULL); | 6004 ASSERT(context_var != NULL); |
| 5965 LocalVariable* exception_var = current_block_->scope->LookupVariable( | 6005 LocalVariable* exception_var = current_block_->scope->LookupVariable( |
| 5966 Symbols::ExceptionVar(), false); | 6006 Symbols::ExceptionVar(), false); |
| 5967 if (exception_param.var != NULL) { | 6007 if (exception_param.var != NULL) { |
| 5968 // Generate code to load the exception object (:exception_var) into | 6008 // Generate code to load the exception object (:exception_var) into |
| 5969 // the exception variable specified in this block. | 6009 // the exception variable specified in this block. |
| 5970 ASSERT(exception_var != NULL); | 6010 ASSERT(exception_var != NULL); |
| 5971 current_block_->statements->Add(new(Z) StoreLocalNode( | 6011 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 5972 Scanner::kNoSourcePos, | 6012 Scanner::kNoSourcePos, |
| 5973 exception_param.var, | 6013 exception_param.var, |
| 5974 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); | 6014 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); |
| 5975 } | 6015 } |
| 5976 LocalVariable* stack_trace_var = | 6016 LocalVariable* stack_trace_var = |
| 5977 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false); | 6017 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false); |
| 5978 if (stack_trace_param.var != NULL) { | 6018 if (stack_trace_param.var != NULL) { |
| 5979 // A stack trace variable is specified in this block, so generate code | 6019 // A stack trace variable is specified in this block, so generate code |
| 5980 // to load the stack trace object (:stack_trace_var) into the stack | 6020 // to load the stack trace object (:stack_trace_var) into the stack |
| 5981 // trace variable specified in this block. | 6021 // trace variable specified in this block. |
| 5982 ASSERT(stack_trace_var != NULL); | 6022 ASSERT(stack_trace_var != NULL); |
| 5983 current_block_->statements->Add(new(Z) StoreLocalNode( | 6023 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 5984 Scanner::kNoSourcePos, | 6024 Scanner::kNoSourcePos, |
| 5985 stack_trace_param.var, | 6025 stack_trace_param.var, |
| 5986 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); | 6026 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); |
| 5987 } | 6027 } |
| 5988 | 6028 |
| 6029 parsed_function()->reset_saved_try_ctx_vars(); | |
| 6030 | |
| 6031 // Catch block: add the error to the stream. | |
| 6032 // :controller.AddError(:exception, :stack_trace); | |
| 6033 // return; // The finally block will close the stream. | |
| 6034 LocalVariable* controller = | |
| 6035 current_block_->scope->LookupVariable(Symbols::Controller(), false); | |
| 6036 ASSERT(controller != NULL); | |
| 6037 ArgumentListNode* args = | |
| 6038 new(Z) ArgumentListNode(Scanner::kNoSourcePos); | |
| 6039 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); | |
| 6040 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); | |
| 6041 current_block_->statements->Add( | |
| 6042 new(Z) InstanceCallNode(TokenPos(), | |
| 6043 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), | |
| 6044 Symbols::AddError(), | |
| 6045 args)); | |
| 6046 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); | |
| 6047 current_block_->statements->Add(return_node); | |
| 6048 AstNode* catch_block = CloseBlock(); | |
| 6049 current_block_->statements->Add(catch_block); | |
| 6050 SequenceNode* catch_handler_list = CloseBlock(); | |
| 6051 | |
| 6052 TryBlocks* try_block = PopTryBlock(); | |
| 6053 ASSERT(try_blocks_list_ == NULL); // We popped the outermost try block. | |
| 6054 | |
| 6055 // Finally block: closing the stream and returning. (Note: the return | |
| 6056 // is necessary otherwise the back-end will append a rethrow of the | |
| 6057 // current exception.) | |
| 6058 // :controller.close(); | |
| 6059 // return; | |
| 6060 // We need to inline this code in all recorded exit points. | |
| 6061 intptr_t node_index = 0; | |
| 6062 SequenceNode* finally_clause = NULL; | |
| 6063 do { | |
| 6064 OpenBlock(); | |
| 6065 ArgumentListNode* no_args = | |
| 6066 new(Z) ArgumentListNode(Scanner::kNoSourcePos); | |
| 6067 current_block_->statements->Add( | |
| 6068 new(Z) InstanceCallNode(TokenPos(), | |
| 6069 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), | |
| 6070 Symbols::Close(), | |
| 6071 no_args)); | |
| 6072 | |
| 6073 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); | |
| 6074 current_block_->statements->Add(return_node); | |
| 6075 | |
| 6076 finally_clause = CloseBlock(); | |
| 6077 AstNode* node_to_inline = try_block->GetNodeToInlineFinally(node_index); | |
| 6078 if (node_to_inline != NULL) { | |
| 6079 InlinedFinallyNode* node = | |
| 6080 new(Z) InlinedFinallyNode(TokenPos(), | |
| 6081 finally_clause, | |
| 6082 context_var, | |
| 6083 // No outer try statement | |
| 6084 CatchClauseNode::kInvalidTryIndex); | |
| 6085 finally_clause = NULL; | |
| 6086 AddFinallyBlockToNode(node_to_inline, node); | |
| 6087 node_index++; | |
| 6088 } | |
| 6089 } while (finally_clause == NULL); | |
| 6090 | |
| 6091 const GrowableObjectArray& handler_types = | |
| 6092 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); | |
| 6093 handler_types.Add(dynamic_type); // Catch block handles all exceptions. | |
| 6094 | |
| 6095 CatchClauseNode* catch_clause = new(Z) CatchClauseNode( | |
| 6096 Scanner::kNoSourcePos, | |
| 6097 catch_handler_list, | |
| 6098 Array::ZoneHandle(Z, Array::MakeArray(handler_types)), | |
| 6099 context_var, | |
| 6100 exception_var, | |
| 6101 stack_trace_var, | |
| 6102 AllocateTryIndex(), | |
| 6103 true); | |
| 6104 | |
| 6105 const intptr_t try_index = try_block->try_index(); | |
| 6106 | |
| 6107 AstNode* try_catch_node = | |
| 6108 new(Z) TryCatchNode(Scanner::kNoSourcePos, | |
| 6109 body, | |
| 6110 context_var, | |
| 6111 catch_clause, | |
| 6112 finally_clause, | |
| 6113 try_index); | |
| 6114 current_block_->statements->Add(try_catch_node); | |
| 6115 return CloseBlock(); | |
| 6116 } | |
| 6117 | |
| 6118 | |
| 6119 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { | |
| 6120 // This is the outermost try-catch of the function. | |
| 5989 ASSERT(try_blocks_list_ != NULL); | 6121 ASSERT(try_blocks_list_ != NULL); |
| 5990 ASSERT(innermost_function().IsAsyncClosure() || | 6122 ASSERT(try_blocks_list_->outer_try_block() == NULL); |
| 5991 innermost_function().IsAsyncFunction()); | 6123 ASSERT(innermost_function().IsAsyncClosure()); |
| 5992 if ((try_blocks_list_->outer_try_block() != NULL) && | 6124 |
| 5993 (try_blocks_list_->outer_try_block()->try_block() | 6125 try_blocks_list_->enter_catch(); |
| 5994 ->scope->function_level() == | 6126 |
| 5995 current_block_->scope->function_level())) { | 6127 OpenBlock(); // Catch handler list. |
| 5996 // We need to unchain three scope levels: catch clause, catch | 6128 OpenBlock(); // Catch block. |
| 5997 // parameters, and the general try block. | 6129 const AbstractType& dynamic_type = |
| 5998 RestoreSavedTryContext( | 6130 AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 5999 current_block_->scope->parent()->parent()->parent(), | 6131 CatchParamDesc exception_param; |
| 6000 try_blocks_list_->outer_try_block()->try_index(), | 6132 CatchParamDesc stack_trace_param; |
| 6001 current_block_->statements); | 6133 exception_param.token_pos = Scanner::kNoSourcePos; |
| 6002 } else { | 6134 exception_param.type = &dynamic_type; |
| 6003 parsed_function()->reset_saved_try_ctx_vars(); | 6135 exception_param.name = &Symbols::ExceptionParameter(); |
| 6136 stack_trace_param.token_pos = Scanner::kNoSourcePos; | |
| 6137 stack_trace_param.type = &dynamic_type; | |
| 6138 stack_trace_param.name = &Symbols::StackTraceParameter(); | |
| 6139 | |
| 6140 AddCatchParamsToScope( | |
| 6141 &exception_param, &stack_trace_param, current_block_->scope); | |
| 6142 | |
| 6143 LocalVariable* context_var = current_block_->scope->LookupVariable( | |
| 6144 Symbols::SavedTryContextVar(), false); | |
| 6145 ASSERT(context_var != NULL); | |
| 6146 LocalVariable* exception_var = current_block_->scope->LookupVariable( | |
| 6147 Symbols::ExceptionVar(), false); | |
| 6148 if (exception_param.var != NULL) { | |
| 6149 // Generate code to load the exception object (:exception_var) into | |
| 6150 // the exception variable specified in this block. | |
| 6151 ASSERT(exception_var != NULL); | |
| 6152 current_block_->statements->Add(new(Z) StoreLocalNode( | |
| 6153 Scanner::kNoSourcePos, | |
| 6154 exception_param.var, | |
| 6155 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); | |
| 6156 } | |
| 6157 LocalVariable* stack_trace_var = | |
| 6158 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false); | |
| 6159 if (stack_trace_param.var != NULL) { | |
| 6160 // A stack trace variable is specified in this block, so generate code | |
| 6161 // to load the stack trace object (:stack_trace_var) into the stack | |
| 6162 // trace variable specified in this block. | |
| 6163 ASSERT(stack_trace_var != NULL); | |
| 6164 current_block_->statements->Add(new(Z) StoreLocalNode( | |
| 6165 Scanner::kNoSourcePos, | |
| 6166 stack_trace_param.var, | |
| 6167 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); | |
| 6004 } | 6168 } |
| 6005 | 6169 |
| 6006 // Complete the async future with an error. | 6170 parsed_function()->reset_saved_try_ctx_vars(); |
| 6007 // Since we control the catch block there is no need to generate a nested | 6171 |
| 6008 // if/then/else. | 6172 // Complete the async future with an error. This catch block executes |
| 6173 // unconditionally, there is no need to generate a type check for. | |
| 6009 LocalVariable* async_completer = current_block_->scope->LookupVariable( | 6174 LocalVariable* async_completer = current_block_->scope->LookupVariable( |
| 6010 Symbols::AsyncCompleter(), false); | 6175 Symbols::AsyncCompleter(), false); |
| 6011 ASSERT(async_completer != NULL); | 6176 ASSERT(async_completer != NULL); |
| 6012 ArgumentListNode* completer_args = | 6177 ArgumentListNode* completer_args = |
| 6013 new (Z) ArgumentListNode(Scanner::kNoSourcePos); | 6178 new (Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6014 completer_args->Add( | 6179 completer_args->Add( |
| 6015 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); | 6180 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); |
| 6016 completer_args->Add( | 6181 completer_args->Add( |
| 6017 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); | 6182 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); |
| 6018 current_block_->statements->Add(new (Z) InstanceCallNode( | 6183 current_block_->statements->Add(new (Z) InstanceCallNode( |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 6043 context_var, | 6208 context_var, |
| 6044 exception_var, | 6209 exception_var, |
| 6045 stack_trace_var, | 6210 stack_trace_var, |
| 6046 CatchClauseNode::kInvalidTryIndex, | 6211 CatchClauseNode::kInvalidTryIndex, |
| 6047 true); | 6212 true); |
| 6048 AstNode* try_catch_node = new (Z) TryCatchNode( | 6213 AstNode* try_catch_node = new (Z) TryCatchNode( |
| 6049 Scanner::kNoSourcePos, | 6214 Scanner::kNoSourcePos, |
| 6050 try_block, | 6215 try_block, |
| 6051 context_var, | 6216 context_var, |
| 6052 catch_clause, | 6217 catch_clause, |
| 6053 NULL, | 6218 NULL, // No finally clause. |
| 6054 try_index); | 6219 try_index); |
| 6055 current_block_->statements->Add(try_catch_node); | 6220 current_block_->statements->Add(try_catch_node); |
| 6056 return CloseBlock(); | 6221 return CloseBlock(); |
| 6057 } | 6222 } |
| 6058 | 6223 |
| 6059 | 6224 |
| 6225 // Wrap the body of the async or arync* closure in a try/catch block. | |
| 6060 void Parser::OpenAsyncTryBlock() { | 6226 void Parser::OpenAsyncTryBlock() { |
| 6061 // Manually wrapping the actual body into a try/catch block. | 6227 ASSERT(innermost_function().IsAsyncClosure() || |
| 6228 innermost_function().IsAsyncGenClosure()); | |
| 6229 | |
| 6062 LocalVariable* context_var = | 6230 LocalVariable* context_var = |
| 6063 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); | 6231 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); |
| 6064 if (context_var == NULL) { | 6232 if (context_var == NULL) { |
| 6065 context_var = new(Z) LocalVariable( | 6233 context_var = new(Z) LocalVariable( |
| 6066 TokenPos(), | 6234 TokenPos(), |
| 6067 Symbols::SavedTryContextVar(), | 6235 Symbols::SavedTryContextVar(), |
| 6068 Type::ZoneHandle(Z, Type::DynamicType())); | 6236 Type::ZoneHandle(Z, Type::DynamicType())); |
| 6069 current_block_->scope->AddVariable(context_var); | 6237 current_block_->scope->AddVariable(context_var); |
| 6070 } | 6238 } |
| 6071 LocalVariable* exception_var = | 6239 LocalVariable* exception_var = |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 6082 if (stack_trace_var == NULL) { | 6250 if (stack_trace_var == NULL) { |
| 6083 stack_trace_var = new(Z) LocalVariable( | 6251 stack_trace_var = new(Z) LocalVariable( |
| 6084 TokenPos(), | 6252 TokenPos(), |
| 6085 Symbols::StackTraceVar(), | 6253 Symbols::StackTraceVar(), |
| 6086 Type::ZoneHandle(Z, Type::DynamicType())); | 6254 Type::ZoneHandle(Z, Type::DynamicType())); |
| 6087 current_block_->scope->AddVariable(stack_trace_var); | 6255 current_block_->scope->AddVariable(stack_trace_var); |
| 6088 } | 6256 } |
| 6089 | 6257 |
| 6090 // Open the try block. | 6258 // Open the try block. |
| 6091 OpenBlock(); | 6259 OpenBlock(); |
| 6260 // This is the outermost try-catch in the function. | |
| 6261 ASSERT(try_blocks_list_ == NULL); | |
| 6092 PushTryBlock(current_block_); | 6262 PushTryBlock(current_block_); |
| 6093 | 6263 |
| 6094 if (innermost_function().IsAsyncClosure() || | 6264 SetupSavedTryContext(context_var); |
| 6095 innermost_function().IsAsyncFunction() || | |
| 6096 innermost_function().IsSyncGenClosure() || | |
| 6097 innermost_function().IsSyncGenerator()) { | |
| 6098 SetupSavedTryContext(context_var); | |
| 6099 } | |
| 6100 } | 6265 } |
| 6101 | 6266 |
| 6102 | 6267 |
| 6103 void Parser::AddSyncGenClosureParameters(ParamList* params) { | 6268 void Parser::AddSyncGenClosureParameters(ParamList* params) { |
| 6104 // Create the parameter list for the body closure of a sync generator: | 6269 // Create the parameter list for the body closure of a sync generator: |
| 6105 // 1) Implicit closure parameter; | 6270 // 1) Implicit closure parameter; |
| 6106 // 2) Iterator | 6271 // 2) Iterator |
| 6107 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | 6272 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 6108 // Add implicit closure parameter if not already present. | 6273 // Add implicit closure parameter if not already present. |
| 6109 if (params->parameters->length() == 0) { | 6274 if (params->parameters->length() == 0) { |
| 6110 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); | 6275 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); |
| 6111 } | 6276 } |
| 6112 ParamDesc iterator_param; | 6277 ParamDesc iterator_param; |
| 6113 iterator_param.name = &Symbols::IteratorParameter(); | 6278 iterator_param.name = &Symbols::IteratorParameter(); |
| 6114 iterator_param.type = &dynamic_type; | 6279 iterator_param.type = &dynamic_type; |
| 6115 params->parameters->Add(iterator_param); | 6280 params->parameters->Add(iterator_param); |
| 6116 params->num_fixed_parameters++; | 6281 params->num_fixed_parameters++; |
| 6117 } | 6282 } |
| 6118 | 6283 |
| 6119 | 6284 |
| 6285 void Parser::AddAsyncGenClosureParameters(ParamList* params) { | |
| 6286 // Create the parameter list for the body closure of a sync generator: | |
|
Ivan Posva
2015/02/23 08:23:36
sync?
hausner
2015/02/23 17:12:01
Yes.
| |
| 6287 // The closure has no explicit parameters. | |
| 6288 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | |
| 6289 // Add implicit closure parameter if not already present. | |
| 6290 if (params->parameters->length() == 0) { | |
| 6291 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); | |
| 6292 } | |
| 6293 } | |
| 6294 | |
| 6295 | |
| 6120 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) { | 6296 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) { |
| 6121 Function& body = Function::Handle(Z); | 6297 Function& body = Function::Handle(Z); |
| 6122 String& body_closure_name = String::Handle(Z); | 6298 String& body_closure_name = String::Handle(Z); |
| 6123 bool is_new_closure = false; | 6299 bool is_new_closure = false; |
| 6124 | 6300 |
| 6125 AddContinuationVariables(); | 6301 AddContinuationVariables(); |
| 6126 | 6302 |
| 6127 // Check whether a function for the body of this generator | 6303 // Check whether a function for the body of this generator |
| 6128 // function has already been created by a previous | 6304 // function has already been created by a previous |
| 6129 // compilation. | 6305 // compilation. |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6349 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); | 6525 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); |
| 6350 async_op_var->set_is_captured(); | 6526 async_op_var->set_is_captured(); |
| 6351 LocalVariable* async_completer = new(Z) LocalVariable( | 6527 LocalVariable* async_completer = new(Z) LocalVariable( |
| 6352 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); | 6528 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); |
| 6353 current_block_->scope->AddVariable(async_completer); | 6529 current_block_->scope->AddVariable(async_completer); |
| 6354 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); | 6530 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); |
| 6355 async_completer->set_is_captured(); | 6531 async_completer->set_is_captured(); |
| 6356 } | 6532 } |
| 6357 | 6533 |
| 6358 | 6534 |
| 6535 void Parser::AddAsyncGeneratorVariables() { | |
| 6536 // Add to current block's scope: | |
| 6537 // var :controller; | |
| 6538 // This variables is used by the nested async generator closure to | |
| 6539 // store the StreamController object to which the yielded expressions | |
| 6540 // are added. | |
| 6541 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | |
| 6542 LocalVariable* controller_var = new(Z) LocalVariable( | |
| 6543 Scanner::kNoSourcePos, Symbols::Controller(), dynamic_type); | |
| 6544 current_block_->scope->AddVariable(controller_var); | |
| 6545 current_block_->scope->CaptureVariable(Symbols::Controller()); | |
| 6546 controller_var->set_is_captured(); | |
| 6547 } | |
| 6548 | |
| 6549 | |
| 6550 RawFunction* Parser::OpenAsyncGeneratorFunction(intptr_t async_func_pos) { | |
| 6551 TRACE_PARSER("OpenAsyncGeneratorFunction"); | |
| 6552 AddContinuationVariables(); | |
| 6553 AddAsyncGeneratorVariables(); | |
| 6554 | |
| 6555 Function& closure = Function::Handle(Z); | |
| 6556 bool is_new_closure = false; | |
| 6557 | |
| 6558 // Check whether a function for the asynchronous function body of | |
| 6559 // this async generator has already been created by a previous | |
| 6560 // compilation of this function. | |
| 6561 const Function& found_func = Function::Handle( | |
| 6562 Z, current_class().LookupClosureFunction(async_func_pos)); | |
| 6563 if (!found_func.IsNull() && | |
| 6564 (found_func.token_pos() == async_func_pos) && | |
| 6565 (found_func.script() == innermost_function().script()) && | |
| 6566 (found_func.parent_function() == innermost_function().raw())) { | |
| 6567 ASSERT(found_func.IsAsyncGenClosure()); | |
| 6568 closure = found_func.raw(); | |
| 6569 } else { | |
| 6570 // Create the closure containing the body of this async generator function. | |
| 6571 const String& async_generator_name = | |
| 6572 String::Handle(Z, innermost_function().name()); | |
| 6573 String& closure_name = String::Handle(Z, | |
| 6574 String::NewFormatted("<%s_async_body>", | |
| 6575 async_generator_name.ToCString())); | |
| 6576 closure = Function::NewClosureFunction( | |
| 6577 String::Handle(Z, Symbols::New(closure_name)), | |
| 6578 innermost_function(), | |
| 6579 async_func_pos); | |
| 6580 closure.set_is_generated_body(true); | |
| 6581 closure.set_result_type(AbstractType::Handle(Type::DynamicType())); | |
| 6582 is_new_closure = true; | |
| 6583 } | |
| 6584 | |
| 6585 ParamList closure_params; | |
| 6586 AddAsyncGenClosureParameters(&closure_params); | |
| 6587 | |
| 6588 if (is_new_closure) { | |
| 6589 // Add the parameters to the newly created closure. | |
| 6590 AddFormalParamsToFunction(&closure_params, closure); | |
| 6591 | |
| 6592 // Create and set the signature class of the closure. | |
| 6593 const String& sig = String::Handle(Z, closure.Signature()); | |
| 6594 Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig)); | |
| 6595 if (sig_cls.IsNull()) { | |
| 6596 sig_cls = | |
| 6597 Class::NewSignatureClass(sig, closure, script_, closure.token_pos()); | |
| 6598 library_.AddClass(sig_cls); | |
| 6599 } | |
| 6600 closure.set_signature_class(sig_cls); | |
| 6601 const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType()); | |
| 6602 if (!sig_type.IsFinalized()) { | |
| 6603 ClassFinalizer::FinalizeType( | |
| 6604 sig_cls, sig_type, ClassFinalizer::kCanonicalize); | |
| 6605 } | |
| 6606 ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved()); | |
| 6607 ASSERT(closure.NumParameters() == closure_params.parameters->length()); | |
| 6608 } | |
| 6609 | |
| 6610 OpenFunctionBlock(closure); | |
| 6611 AddFormalParamsToScope(&closure_params, current_block_->scope); | |
| 6612 OpenBlock(); | |
| 6613 async_temp_scope_ = current_block_->scope; | |
| 6614 return closure.raw(); | |
| 6615 } | |
| 6616 | |
| 6617 | |
| 6618 // Generate the Ast nodes for the implicit code of the async* function. | |
| 6619 // | |
| 6620 // f(...) async* { | |
| 6621 // var :controller; | |
| 6622 // var :await_jump_var = -1; | |
| 6623 // var :await_context_var; | |
| 6624 // f_async_body() { | |
| 6625 // ... source code of f ... | |
| 6626 // } | |
| 6627 // :controller = new _AsyncStarStreamController(f_async_body); | |
| 6628 // return :controller.stream; | |
| 6629 // } | |
| 6630 SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure, | |
| 6631 SequenceNode* closure_body) { | |
| 6632 TRACE_PARSER("CloseAsyncGeneratorFunction"); | |
| 6633 ASSERT(!closure.IsNull()); | |
| 6634 ASSERT(closure_body != NULL); | |
| 6635 | |
| 6636 // The block for the async closure body has already been closed. Close the | |
| 6637 // corresponding function block. | |
| 6638 CloseBlock(); | |
| 6639 | |
| 6640 // Make sure the implicit variables of the async generator function | |
| 6641 // are captured. | |
| 6642 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | |
| 6643 closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); | |
| 6644 closure_body->scope()->LookupVariable(Symbols::Controller(), false); | |
| 6645 | |
| 6646 const Class& controller_class = Class::Handle(Z, | |
| 6647 Library::LookupCoreClass(Symbols::_AsyncStarStreamController())); | |
| 6648 ASSERT(!controller_class.IsNull()); | |
| 6649 const Function& controller_constructor = Function::ZoneHandle(Z, | |
| 6650 controller_class.LookupConstructorAllowPrivate( | |
| 6651 Symbols::_AsyncStarStreamControllerConstructor())); | |
| 6652 | |
| 6653 // :await_jump_var = -1; | |
| 6654 LocalVariable* jump_var = | |
| 6655 current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false); | |
| 6656 LiteralNode* init_value = | |
| 6657 new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1))); | |
| 6658 current_block_->statements->Add( | |
| 6659 new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value)); | |
| 6660 | |
| 6661 // :controller = new _AsyncStarStreamController(body_closure); | |
| 6662 ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos); | |
| 6663 ClosureNode* closure_obj = new(Z) ClosureNode( | |
| 6664 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); | |
| 6665 arguments->Add(closure_obj); | |
| 6666 ConstructorCallNode* controller_constructor_call = | |
| 6667 new(Z) ConstructorCallNode(Scanner::kNoSourcePos, | |
| 6668 TypeArguments::ZoneHandle(Z), | |
| 6669 controller_constructor, | |
| 6670 arguments); | |
| 6671 LocalVariable* controller_var = | |
| 6672 current_block_->scope->LookupVariable(Symbols::Controller(), false); | |
| 6673 StoreLocalNode* store_controller = | |
| 6674 new(Z) StoreLocalNode(Scanner::kNoSourcePos, | |
| 6675 controller_var, | |
| 6676 controller_constructor_call); | |
| 6677 current_block_->statements->Add(store_controller); | |
| 6678 | |
| 6679 // return :controller.stream; | |
| 6680 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos, | |
| 6681 new(Z) InstanceGetterNode(Scanner::kNoSourcePos, | |
| 6682 new(Z) LoadLocalNode(Scanner::kNoSourcePos, | |
| 6683 controller_var), | |
| 6684 Symbols::ControllerStream())); | |
| 6685 current_block_->statements->Add(return_node); | |
| 6686 return CloseBlock(); | |
| 6687 } | |
| 6688 | |
| 6689 | |
| 6690 void Parser::OpenAsyncGeneratorClosure() { | |
| 6691 async_temp_scope_ = current_block_->scope; | |
| 6692 OpenAsyncTryBlock(); | |
| 6693 } | |
| 6694 | |
| 6695 | |
| 6696 SequenceNode* Parser::CloseAsyncGeneratorClosure(SequenceNode* body) { | |
| 6697 // TODO(hausner): Is the temporary expression necessary? | |
| 6698 // We need a temporary expression to store intermediate return values. | |
| 6699 parsed_function()->EnsureExpressionTemp(); | |
| 6700 | |
| 6701 SequenceNode* new_body = CloseAsyncGeneratorTryBlock(body); | |
| 6702 ASSERT(new_body != NULL); | |
| 6703 ASSERT(new_body->scope() != NULL); | |
| 6704 | |
| 6705 // Implicitly mark those variables below as captured. We currently mark all | |
| 6706 // variables of all scopes as captured, but as soon as we do something | |
| 6707 // smarter we rely on these internal variables to be available. | |
| 6708 new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | |
| 6709 new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); | |
| 6710 new_body->scope()->LookupVariable(Symbols::Controller(), false); | |
| 6711 new_body->scope()->RecursivelyCaptureAllVariables(); | |
| 6712 return new_body; | |
| 6713 } | |
| 6714 | |
| 6715 | |
| 6359 SequenceNode* Parser::CloseBlock() { | 6716 SequenceNode* Parser::CloseBlock() { |
| 6360 SequenceNode* statements = current_block_->statements; | 6717 SequenceNode* statements = current_block_->statements; |
| 6361 if (current_block_->scope != NULL) { | 6718 if (current_block_->scope != NULL) { |
| 6362 // Record the begin and end token index of the scope. | 6719 // Record the begin and end token index of the scope. |
| 6363 ASSERT(statements != NULL); | 6720 ASSERT(statements != NULL); |
| 6364 current_block_->scope->set_begin_token_pos(statements->token_pos()); | 6721 current_block_->scope->set_begin_token_pos(statements->token_pos()); |
| 6365 current_block_->scope->set_end_token_pos(TokenPos()); | 6722 current_block_->scope->set_end_token_pos(TokenPos()); |
| 6366 } | 6723 } |
| 6367 current_block_ = current_block_->parent; | 6724 current_block_ = current_block_->parent; |
| 6368 return statements; | 6725 return statements; |
| (...skipping 1395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7764 AstNode* Parser::ParseAwaitForStatement(String* label_name) { | 8121 AstNode* Parser::ParseAwaitForStatement(String* label_name) { |
| 7765 TRACE_PARSER("ParseAwaitForStatement"); | 8122 TRACE_PARSER("ParseAwaitForStatement"); |
| 7766 ASSERT(IsAwaitKeyword()); | 8123 ASSERT(IsAwaitKeyword()); |
| 7767 const intptr_t await_for_pos = TokenPos(); | 8124 const intptr_t await_for_pos = TokenPos(); |
| 7768 ConsumeToken(); // await. | 8125 ConsumeToken(); // await. |
| 7769 ASSERT(CurrentToken() == Token::kFOR); | 8126 ASSERT(CurrentToken() == Token::kFOR); |
| 7770 ConsumeToken(); // for. | 8127 ConsumeToken(); // for. |
| 7771 ExpectToken(Token::kLPAREN); | 8128 ExpectToken(Token::kLPAREN); |
| 7772 | 8129 |
| 7773 if (!innermost_function().IsAsyncFunction() && | 8130 if (!innermost_function().IsAsyncFunction() && |
| 7774 !innermost_function().IsAsyncClosure()) { | 8131 !innermost_function().IsAsyncClosure() && |
| 8132 !innermost_function().IsAsyncGenerator() && | |
| 8133 !innermost_function().IsAsyncGenClosure()) { | |
| 7775 ReportError(await_for_pos, | 8134 ReportError(await_for_pos, |
| 7776 "await for loop is only allowed in async function"); | 8135 "await for loop is only allowed in an asynchronous function"); |
| 7777 } | 8136 } |
| 7778 | 8137 |
| 7779 // Parse loop variable. | 8138 // Parse loop variable. |
| 7780 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); | 8139 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); |
| 7781 if (CurrentToken() == Token::kCONST) { | 8140 if (CurrentToken() == Token::kCONST) { |
| 7782 ReportError("Loop variable cannot be 'const'"); | 8141 ReportError("Loop variable cannot be 'const'"); |
| 7783 } | 8142 } |
| 7784 bool new_loop_var = false; | 8143 bool new_loop_var = false; |
| 7785 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); | 8144 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); |
| 7786 if (LookaheadToken(1) != Token::kIN) { | 8145 if (LookaheadToken(1) != Token::kIN) { |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8205 TRACE_PARSER("ParseFinallyBlock"); | 8564 TRACE_PARSER("ParseFinallyBlock"); |
| 8206 OpenBlock(); | 8565 OpenBlock(); |
| 8207 ExpectToken(Token::kLBRACE); | 8566 ExpectToken(Token::kLBRACE); |
| 8208 | 8567 |
| 8209 // In case of async closures we need to restore the saved try index of an | 8568 // In case of async closures we need to restore the saved try index of an |
| 8210 // outer try block (if it exists). The current try block has already been | 8569 // outer try block (if it exists). The current try block has already been |
| 8211 // removed from the stack of try blocks. | 8570 // removed from the stack of try blocks. |
| 8212 if ((innermost_function().IsAsyncClosure() || | 8571 if ((innermost_function().IsAsyncClosure() || |
| 8213 innermost_function().IsAsyncFunction() || | 8572 innermost_function().IsAsyncFunction() || |
| 8214 innermost_function().IsSyncGenClosure() || | 8573 innermost_function().IsSyncGenClosure() || |
| 8215 innermost_function().IsSyncGenerator()) && | 8574 innermost_function().IsSyncGenerator() || |
| 8575 innermost_function().IsAsyncGenerator() || | |
| 8576 innermost_function().IsAsyncGenClosure()) && | |
| 8216 (try_blocks_list_ != NULL)) { | 8577 (try_blocks_list_ != NULL)) { |
| 8217 // We need two unchain two scopes: finally clause, and the try block level. | 8578 // We need two unchain two scopes: finally clause, and the try block level. |
| 8218 RestoreSavedTryContext(current_block_->scope->parent()->parent(), | 8579 RestoreSavedTryContext(current_block_->scope->parent()->parent(), |
| 8219 try_blocks_list_->try_index(), | 8580 try_blocks_list_->try_index(), |
| 8220 current_block_->statements); | 8581 current_block_->statements); |
| 8221 } else { | 8582 } else { |
| 8222 parsed_function()->reset_saved_try_ctx_vars(); | 8583 parsed_function()->reset_saved_try_ctx_vars(); |
| 8223 } | 8584 } |
| 8224 | 8585 |
| 8225 ParseStatementSequence(); | 8586 ParseStatementSequence(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8314 } else { | 8675 } else { |
| 8315 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); | 8676 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 8316 } | 8677 } |
| 8317 if (CurrentToken() == Token::kCATCH) { | 8678 if (CurrentToken() == Token::kCATCH) { |
| 8318 ConsumeToken(); // Consume the 'catch'. | 8679 ConsumeToken(); // Consume the 'catch'. |
| 8319 ExpectToken(Token::kLPAREN); | 8680 ExpectToken(Token::kLPAREN); |
| 8320 exception_param.token_pos = TokenPos(); | 8681 exception_param.token_pos = TokenPos(); |
| 8321 exception_param.name = ExpectIdentifier("identifier expected"); | 8682 exception_param.name = ExpectIdentifier("identifier expected"); |
| 8322 if (CurrentToken() == Token::kCOMMA) { | 8683 if (CurrentToken() == Token::kCOMMA) { |
| 8323 ConsumeToken(); | 8684 ConsumeToken(); |
| 8324 // TODO(hausner): Make implicit type be StackTrace, not dynamic. | |
| 8325 stack_trace_param.type = | 8685 stack_trace_param.type = |
| 8326 &AbstractType::ZoneHandle(Z, Type::DynamicType()); | 8686 &AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 8327 stack_trace_param.token_pos = TokenPos(); | 8687 stack_trace_param.token_pos = TokenPos(); |
| 8328 stack_trace_param.name = ExpectIdentifier("identifier expected"); | 8688 stack_trace_param.name = ExpectIdentifier("identifier expected"); |
| 8329 } | 8689 } |
| 8330 ExpectToken(Token::kRPAREN); | 8690 ExpectToken(Token::kRPAREN); |
| 8331 } | 8691 } |
| 8332 | 8692 |
| 8333 // Create a block containing the catch clause parameters and the | 8693 // Create a block containing the catch clause parameters and the |
| 8334 // following code: | 8694 // following code: |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 8351 // A stack trace variable is specified in this block, so generate code | 8711 // A stack trace variable is specified in this block, so generate code |
| 8352 // to load the stack trace object (:stack_trace_var) into the stack | 8712 // to load the stack trace object (:stack_trace_var) into the stack |
| 8353 // trace variable specified in this block. | 8713 // trace variable specified in this block. |
| 8354 *needs_stack_trace = true; | 8714 *needs_stack_trace = true; |
| 8355 ASSERT(stack_trace_var != NULL); | 8715 ASSERT(stack_trace_var != NULL); |
| 8356 current_block_->statements->Add(new(Z) StoreLocalNode( | 8716 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 8357 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( | 8717 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( |
| 8358 catch_pos, stack_trace_var))); | 8718 catch_pos, stack_trace_var))); |
| 8359 } | 8719 } |
| 8360 | 8720 |
| 8361 // Add nested block with user-defined code. This blocks allows | 8721 // Add nested block with user-defined code. This block allows |
| 8362 // declarations in the body to shadow the catch parameters. | 8722 // declarations in the body to shadow the catch parameters. |
| 8363 CheckToken(Token::kLBRACE); | 8723 CheckToken(Token::kLBRACE); |
| 8364 | 8724 |
| 8365 // In case of async closures we need to restore the saved try index of an | 8725 // In case of async closures we need to restore the saved try index of an |
| 8366 // outer try block (if it exists). | 8726 // outer try block (if it exists). |
| 8367 ASSERT(try_blocks_list_ != NULL); | 8727 ASSERT(try_blocks_list_ != NULL); |
| 8368 if (innermost_function().IsAsyncClosure() || | 8728 if (innermost_function().IsAsyncClosure() || |
| 8369 innermost_function().IsAsyncFunction() || | 8729 innermost_function().IsAsyncFunction() || |
| 8370 innermost_function().IsSyncGenClosure() || | 8730 innermost_function().IsSyncGenClosure() || |
| 8371 innermost_function().IsSyncGenerator()) { | 8731 innermost_function().IsSyncGenerator() || |
| 8732 innermost_function().IsAsyncGenerator() || | |
| 8733 innermost_function().IsAsyncGenClosure()) { | |
| 8372 if ((try_blocks_list_->outer_try_block() != NULL) && | 8734 if ((try_blocks_list_->outer_try_block() != NULL) && |
| 8373 (try_blocks_list_->outer_try_block()->try_block() | 8735 (try_blocks_list_->outer_try_block()->try_block() |
| 8374 ->scope->function_level() == | 8736 ->scope->function_level() == |
| 8375 current_block_->scope->function_level())) { | 8737 current_block_->scope->function_level())) { |
| 8376 // We need to unchain three scope levels: catch clause, catch | 8738 // We need to unchain three scope levels: catch clause, catch |
| 8377 // parameters, and the general try block. | 8739 // parameters, and the general try block. |
| 8378 RestoreSavedTryContext( | 8740 RestoreSavedTryContext( |
| 8379 current_block_->scope->parent()->parent()->parent(), | 8741 current_block_->scope->parent()->parent()->parent(), |
| 8380 try_blocks_list_->outer_try_block()->try_index(), | 8742 try_blocks_list_->outer_try_block()->try_index(), |
| 8381 current_block_->statements); | 8743 current_block_->statements); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8471 while (!type_tests.is_empty()) { | 8833 while (!type_tests.is_empty()) { |
| 8472 AstNode* type_test = type_tests.RemoveLast(); | 8834 AstNode* type_test = type_tests.RemoveLast(); |
| 8473 SequenceNode* catch_block = catch_blocks.RemoveLast(); | 8835 SequenceNode* catch_block = catch_blocks.RemoveLast(); |
| 8474 | 8836 |
| 8475 // In case of async closures we need to restore the saved try index of an | 8837 // In case of async closures we need to restore the saved try index of an |
| 8476 // outer try block (if it exists). | 8838 // outer try block (if it exists). |
| 8477 ASSERT(try_blocks_list_ != NULL); | 8839 ASSERT(try_blocks_list_ != NULL); |
| 8478 if (innermost_function().IsAsyncClosure() || | 8840 if (innermost_function().IsAsyncClosure() || |
| 8479 innermost_function().IsAsyncFunction() || | 8841 innermost_function().IsAsyncFunction() || |
| 8480 innermost_function().IsSyncGenClosure() || | 8842 innermost_function().IsSyncGenClosure() || |
| 8481 innermost_function().IsSyncGenerator()) { | 8843 innermost_function().IsSyncGenerator() || |
| 8844 innermost_function().IsAsyncGenerator() || | |
| 8845 innermost_function().IsAsyncGenClosure()) { | |
| 8482 if ((try_blocks_list_->outer_try_block() != NULL) && | 8846 if ((try_blocks_list_->outer_try_block() != NULL) && |
| 8483 (try_blocks_list_->outer_try_block()->try_block() | 8847 (try_blocks_list_->outer_try_block()->try_block() |
| 8484 ->scope->function_level() == | 8848 ->scope->function_level() == |
| 8485 current_block_->scope->function_level())) { | 8849 current_block_->scope->function_level())) { |
| 8486 // We need to unchain three scope levels: catch clause, catch | 8850 // We need to unchain three scope levels: catch clause, catch |
| 8487 // parameters, and the general try block. | 8851 // parameters, and the general try block. |
| 8488 RestoreSavedTryContext( | 8852 RestoreSavedTryContext( |
| 8489 current_block_->scope->parent()->parent(), | 8853 current_block_->scope->parent()->parent(), |
| 8490 try_blocks_list_->outer_try_block()->try_index(), | 8854 try_blocks_list_->outer_try_block()->try_index(), |
| 8491 current_block_->statements); | 8855 current_block_->statements); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8610 } | 8974 } |
| 8611 | 8975 |
| 8612 // Now parse the 'try' block. | 8976 // Now parse the 'try' block. |
| 8613 OpenBlock(); | 8977 OpenBlock(); |
| 8614 PushTryBlock(current_block_); | 8978 PushTryBlock(current_block_); |
| 8615 ExpectToken(Token::kLBRACE); | 8979 ExpectToken(Token::kLBRACE); |
| 8616 | 8980 |
| 8617 if (innermost_function().IsAsyncClosure() || | 8981 if (innermost_function().IsAsyncClosure() || |
| 8618 innermost_function().IsAsyncFunction() || | 8982 innermost_function().IsAsyncFunction() || |
| 8619 innermost_function().IsSyncGenClosure() || | 8983 innermost_function().IsSyncGenClosure() || |
| 8620 innermost_function().IsSyncGenerator()) { | 8984 innermost_function().IsSyncGenerator() || |
| 8985 innermost_function().IsAsyncGenerator() || | |
| 8986 innermost_function().IsAsyncGenClosure()) { | |
| 8621 SetupSavedTryContext(context_var); | 8987 SetupSavedTryContext(context_var); |
| 8622 } | 8988 } |
| 8623 | 8989 |
| 8624 ParseStatementSequence(); | 8990 ParseStatementSequence(); |
| 8625 ExpectToken(Token::kRBRACE); | 8991 ExpectToken(Token::kRBRACE); |
| 8626 SequenceNode* try_block = CloseBlock(); | 8992 SequenceNode* try_block = CloseBlock(); |
| 8627 | 8993 |
| 8628 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 8994 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
| 8629 (CurrentToken() != Token::kFINALLY)) { | 8995 (CurrentToken() != Token::kFINALLY)) { |
| 8630 ReportError("catch or finally clause expected"); | 8996 ReportError("catch or finally clause expected"); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8754 ReportError(jump_pos, "'break' to case clause label is illegal"); | 9120 ReportError(jump_pos, "'break' to case clause label is illegal"); |
| 8755 } | 9121 } |
| 8756 if (target->FunctionLevel() != current_block_->scope->function_level()) { | 9122 if (target->FunctionLevel() != current_block_->scope->function_level()) { |
| 8757 ReportError(jump_pos, "'%s' target must be in same function context", | 9123 ReportError(jump_pos, "'%s' target must be in same function context", |
| 8758 Token::Str(jump_kind)); | 9124 Token::Str(jump_kind)); |
| 8759 } | 9125 } |
| 8760 return new(Z) JumpNode(jump_pos, jump_kind, target); | 9126 return new(Z) JumpNode(jump_pos, jump_kind, target); |
| 8761 } | 9127 } |
| 8762 | 9128 |
| 8763 | 9129 |
| 9130 AstNode* Parser::ParseYieldStatement() { | |
| 9131 bool is_yield_each = false; | |
| 9132 const intptr_t yield_pos = TokenPos(); | |
| 9133 ConsumeToken(); // yield reserved word. | |
| 9134 ASSERT(innermost_function().IsGenerator() || | |
| 9135 innermost_function().IsSyncGenClosure() || | |
| 9136 innermost_function().IsAsyncGenerator() || | |
| 9137 innermost_function().IsAsyncGenClosure()); | |
| 9138 if (CurrentToken() == Token::kMUL) { | |
| 9139 is_yield_each = true; | |
| 9140 ConsumeToken(); | |
| 9141 } | |
| 9142 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | |
| 9143 | |
| 9144 LetNode* yield = new(Z) LetNode(yield_pos); | |
| 9145 if (innermost_function().IsSyncGenerator() || | |
| 9146 innermost_function().IsSyncGenClosure()) { | |
| 9147 // Yield statement in sync* function. | |
| 9148 | |
| 9149 LocalVariable* iterator_param = | |
| 9150 LookupLocalScope(Symbols::IteratorParameter()); | |
| 9151 ASSERT(iterator_param != NULL); | |
| 9152 // Generate :iterator.current = expr; | |
| 9153 AstNode* iterator = | |
| 9154 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param); | |
| 9155 AstNode* store_current = | |
| 9156 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 9157 iterator, | |
| 9158 String::ZoneHandle(Symbols::Current().raw()), | |
| 9159 expr); | |
| 9160 yield->AddNode(store_current); | |
| 9161 if (is_yield_each) { | |
| 9162 // Generate :iterator.isYieldEach = true; | |
| 9163 AstNode* set_is_yield_each = | |
| 9164 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 9165 iterator, | |
| 9166 String::ZoneHandle(Symbols::IsYieldEach().raw()), | |
| 9167 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 9168 yield->AddNode(set_is_yield_each); | |
| 9169 } | |
| 9170 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); | |
| 9171 await_marker->set_scope(current_block_->scope); | |
| 9172 yield->AddNode(await_marker); | |
| 9173 // Return true to indicate that a value has been generated. | |
| 9174 ReturnNode* return_true = new(Z) ReturnNode(yield_pos, | |
| 9175 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 9176 return_true->set_return_type(ReturnNode::kContinuationTarget); | |
| 9177 yield->AddNode(return_true); | |
| 9178 | |
| 9179 // If this expression is part of a try block, also append the code for | |
| 9180 // restoring the saved try context that lives on the stack. | |
| 9181 const String& async_saved_try_ctx_name = | |
| 9182 String::Handle(Z, parsed_function()->async_saved_try_ctx_name()); | |
| 9183 if (!async_saved_try_ctx_name.IsNull()) { | |
| 9184 LocalVariable* async_saved_try_ctx = | |
| 9185 current_block_->scope->LookupVariable(async_saved_try_ctx_name, | |
| 9186 false); | |
| 9187 ASSERT(async_saved_try_ctx != NULL); | |
| 9188 yield->AddNode(new (Z) StoreLocalNode( | |
| 9189 Scanner::kNoSourcePos, | |
| 9190 parsed_function()->saved_try_ctx(), | |
| 9191 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx))); | |
| 9192 } | |
| 9193 } else { | |
| 9194 // yield statement in async* function. | |
| 9195 ASSERT(innermost_function().IsAsyncGenerator() || | |
| 9196 innermost_function().IsAsyncGenClosure()); | |
| 9197 | |
| 9198 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller()); | |
| 9199 ASSERT(controller_var != NULL); | |
| 9200 // :controller.add[Stream](expr); | |
| 9201 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos); | |
| 9202 add_args->Add(expr); | |
| 9203 AstNode* add_call = | |
| 9204 new(Z) InstanceCallNode(yield_pos, | |
| 9205 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var), | |
| 9206 is_yield_each ? Symbols::AddStream() : Symbols::add(), | |
| 9207 add_args); | |
| 9208 | |
| 9209 // if (:controller.isPaused) { | |
| 9210 // await_marker; | |
| 9211 // continuation_return; | |
| 9212 // } | |
| 9213 /* | |
| 9214 AstNode* is_paused = new(Z) InstanceGetterNode( | |
| 9215 Scanner::kNoSourcePos, | |
| 9216 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var), | |
| 9217 Symbols::isPaused());*/ | |
| 9218 | |
| 9219 SequenceNode* true_branch = | |
| 9220 new(Z) SequenceNode(Scanner::kNoSourcePos, current_block_->scope); | |
| 9221 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); | |
| 9222 await_marker->set_scope(current_block_->scope); | |
| 9223 true_branch->Add(await_marker); | |
| 9224 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos); | |
| 9225 continuation_return->set_return_type(ReturnNode::kContinuationTarget); | |
| 9226 true_branch->Add(continuation_return); | |
| 9227 | |
| 9228 AstNode* if_is_paused = | |
| 9229 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL); | |
| 9230 yield->AddNode(if_is_paused); | |
| 9231 } | |
| 9232 return yield; | |
| 9233 } | |
| 9234 | |
| 9235 | |
| 8764 AstNode* Parser::ParseStatement() { | 9236 AstNode* Parser::ParseStatement() { |
| 8765 TRACE_PARSER("ParseStatement"); | 9237 TRACE_PARSER("ParseStatement"); |
| 8766 AstNode* statement = NULL; | 9238 AstNode* statement = NULL; |
| 8767 intptr_t label_pos = 0; | 9239 intptr_t label_pos = 0; |
| 8768 String* label_name = NULL; | 9240 String* label_name = NULL; |
| 8769 if (IsIdentifier()) { | 9241 if (IsIdentifier()) { |
| 8770 if (LookaheadToken(1) == Token::kCOLON) { | 9242 if (LookaheadToken(1) == Token::kCOLON) { |
| 8771 // Statement starts with a label. | 9243 // Statement starts with a label. |
| 8772 label_name = CurrentLiteral(); | 9244 label_name = CurrentLiteral(); |
| 8773 label_pos = TokenPos(); | 9245 label_pos = TokenPos(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 8793 statement = ParseTryStatement(label_name); | 9265 statement = ParseTryStatement(label_name); |
| 8794 } else if (token == Token::kRETURN) { | 9266 } else if (token == Token::kRETURN) { |
| 8795 const intptr_t return_pos = TokenPos(); | 9267 const intptr_t return_pos = TokenPos(); |
| 8796 ConsumeToken(); | 9268 ConsumeToken(); |
| 8797 if (CurrentToken() != Token::kSEMICOLON) { | 9269 if (CurrentToken() != Token::kSEMICOLON) { |
| 8798 const intptr_t expr_pos = TokenPos(); | 9270 const intptr_t expr_pos = TokenPos(); |
| 8799 if (current_function().IsGenerativeConstructor() && | 9271 if (current_function().IsGenerativeConstructor() && |
| 8800 (current_block_->scope->function_level() == 0)) { | 9272 (current_block_->scope->function_level() == 0)) { |
| 8801 ReportError(expr_pos, | 9273 ReportError(expr_pos, |
| 8802 "return of a value is not allowed in constructors"); | 9274 "return of a value is not allowed in constructors"); |
| 8803 } else if (current_function().IsGenerator()) { | 9275 } else if (current_function().IsGeneratorClosure() && |
| 9276 (current_block_->scope->function_level() == 0)) { | |
| 8804 ReportError(expr_pos, "generator functions may not return a value"); | 9277 ReportError(expr_pos, "generator functions may not return a value"); |
| 8805 } | 9278 } |
| 8806 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 9279 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 8807 statement = new(Z) ReturnNode(statement_pos, expr); | 9280 statement = new(Z) ReturnNode(statement_pos, expr); |
| 8808 } else { | 9281 } else { |
| 8809 if (current_function().IsSyncGenClosure() && | 9282 if (current_function().IsSyncGenClosure() && |
| 8810 (current_block_->scope->function_level() == 0)) { | 9283 (current_block_->scope->function_level() == 0)) { |
| 8811 // In a synchronous generator, return without an expression | 9284 // In a synchronous generator, return without an expression |
| 8812 // returns false, signaling that the iterator terminates and | 9285 // returns false, signaling that the iterator terminates and |
| 8813 // did not yield a value. | 9286 // did not yield a value. |
| 8814 statement = new(Z) ReturnNode(statement_pos, | 9287 statement = new(Z) ReturnNode(statement_pos, |
| 8815 new(Z) LiteralNode(return_pos, Bool::False())); | 9288 new(Z) LiteralNode(return_pos, Bool::False())); |
| 8816 } else { | 9289 } else { |
| 8817 statement = new(Z) ReturnNode(statement_pos); | 9290 statement = new(Z) ReturnNode(statement_pos); |
| 8818 } | 9291 } |
| 8819 } | 9292 } |
| 8820 AddNodeForFinallyInlining(statement); | 9293 AddNodeForFinallyInlining(statement); |
| 8821 ExpectSemicolon(); | 9294 ExpectSemicolon(); |
| 8822 } else if (IsYieldKeyword()) { | 9295 } else if (IsYieldKeyword()) { |
| 8823 bool is_yield_each = false; | 9296 statement = ParseYieldStatement(); |
| 8824 ConsumeToken(); | |
| 8825 ASSERT(innermost_function().IsGenerator() || | |
| 8826 innermost_function().IsSyncGenClosure()); | |
| 8827 if (CurrentToken() == Token::kMUL) { | |
| 8828 is_yield_each = true; | |
| 8829 ConsumeToken(); | |
| 8830 } | |
| 8831 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | |
| 8832 LocalVariable* iterator_param = | |
| 8833 LookupLocalScope(Symbols::IteratorParameter()); | |
| 8834 ASSERT(iterator_param != NULL); | |
| 8835 // Generate :iterator.current = expr; | |
| 8836 AstNode* iterator = | |
| 8837 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param); | |
| 8838 AstNode* store_current = | |
| 8839 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 8840 iterator, | |
| 8841 String::ZoneHandle(Symbols::Current().raw()), | |
| 8842 expr); | |
| 8843 LetNode* yield = new(Z) LetNode(statement_pos); | |
| 8844 yield->AddNode(store_current); | |
| 8845 if (is_yield_each) { | |
| 8846 // Generate :iterator.isYieldEach = true; | |
| 8847 AstNode* set_is_yield_each = | |
| 8848 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 8849 iterator, | |
| 8850 String::ZoneHandle(Symbols::IsYieldEach().raw()), | |
| 8851 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 8852 yield->AddNode(set_is_yield_each); | |
| 8853 } | |
| 8854 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); | |
| 8855 await_marker->set_scope(current_block_->scope); | |
| 8856 yield->AddNode(await_marker); | |
| 8857 // Return true to indicate that a value has been generated. | |
| 8858 ReturnNode* return_true = new(Z) ReturnNode(statement_pos, | |
| 8859 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 8860 return_true->set_return_type(ReturnNode::kContinuationTarget); | |
| 8861 yield->AddNode(return_true); | |
| 8862 | |
| 8863 // If this expression is part of a try block, also append the code for | |
| 8864 // restoring the saved try context that lives on the stack. | |
| 8865 const String& async_saved_try_ctx_name = | |
| 8866 String::Handle(Z, parsed_function()->async_saved_try_ctx_name()); | |
| 8867 if (!async_saved_try_ctx_name.IsNull()) { | |
| 8868 LocalVariable* async_saved_try_ctx = | |
| 8869 current_block_->scope->LookupVariable(async_saved_try_ctx_name, | |
| 8870 false); | |
| 8871 ASSERT(async_saved_try_ctx != NULL); | |
| 8872 yield->AddNode(new (Z) StoreLocalNode( | |
| 8873 Scanner::kNoSourcePos, | |
| 8874 parsed_function()->saved_try_ctx(), | |
| 8875 new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx))); | |
| 8876 } | |
| 8877 | |
| 8878 statement = yield; | |
| 8879 ExpectSemicolon(); | 9297 ExpectSemicolon(); |
| 8880 } else if (token == Token::kIF) { | 9298 } else if (token == Token::kIF) { |
| 8881 statement = ParseIfStatement(label_name); | 9299 statement = ParseIfStatement(label_name); |
| 8882 } else if (token == Token::kASSERT) { | 9300 } else if (token == Token::kASSERT) { |
| 8883 statement = ParseAssertStatement(); | 9301 statement = ParseAssertStatement(); |
| 8884 ExpectSemicolon(); | 9302 ExpectSemicolon(); |
| 8885 } else if (IsVariableDeclaration()) { | 9303 } else if (IsVariableDeclaration()) { |
| 8886 statement = ParseVariableDeclarationList(); | 9304 statement = ParseVariableDeclarationList(); |
| 8887 ExpectSemicolon(); | 9305 ExpectSemicolon(); |
| 8888 } else if (IsFunctionDeclaration()) { | 9306 } else if (IsFunctionDeclaration()) { |
| (...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9719 } | 10137 } |
| 9720 | 10138 |
| 9721 | 10139 |
| 9722 AstNode* Parser::ParseUnaryExpr() { | 10140 AstNode* Parser::ParseUnaryExpr() { |
| 9723 TRACE_PARSER("ParseUnaryExpr"); | 10141 TRACE_PARSER("ParseUnaryExpr"); |
| 9724 AstNode* expr = NULL; | 10142 AstNode* expr = NULL; |
| 9725 const intptr_t op_pos = TokenPos(); | 10143 const intptr_t op_pos = TokenPos(); |
| 9726 if (IsAwaitKeyword()) { | 10144 if (IsAwaitKeyword()) { |
| 9727 TRACE_PARSER("ParseAwaitExpr"); | 10145 TRACE_PARSER("ParseAwaitExpr"); |
| 9728 if (!innermost_function().IsAsyncFunction() && | 10146 if (!innermost_function().IsAsyncFunction() && |
| 9729 !innermost_function().IsAsyncClosure()) { | 10147 !innermost_function().IsAsyncClosure() && |
| 9730 ReportError("await operator is only allowed in async function"); | 10148 !innermost_function().IsAsyncGenerator() && |
| 10149 !innermost_function().IsAsyncGenClosure()) { | |
| 10150 ReportError("await operator is only allowed in an asynchronous function"); | |
| 9731 } | 10151 } |
| 9732 ConsumeToken(); | 10152 ConsumeToken(); |
| 9733 parsed_function()->record_await(); | 10153 parsed_function()->record_await(); |
| 9734 expr = new (Z) AwaitNode(op_pos, ParseUnaryExpr()); | 10154 expr = new (Z) AwaitNode(op_pos, ParseUnaryExpr()); |
| 9735 } else if (IsPrefixOperator(CurrentToken())) { | 10155 } else if (IsPrefixOperator(CurrentToken())) { |
| 9736 Token::Kind unary_op = CurrentToken(); | 10156 Token::Kind unary_op = CurrentToken(); |
| 9737 if (unary_op == Token::kSUB) { | 10157 if (unary_op == Token::kSUB) { |
| 9738 unary_op = Token::kNEGATE; | 10158 unary_op = Token::kNEGATE; |
| 9739 } | 10159 } |
| 9740 ConsumeToken(); | 10160 ConsumeToken(); |
| (...skipping 2816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12557 void Parser::SkipQualIdent() { | 12977 void Parser::SkipQualIdent() { |
| 12558 ASSERT(IsIdentifier()); | 12978 ASSERT(IsIdentifier()); |
| 12559 ConsumeToken(); | 12979 ConsumeToken(); |
| 12560 if (CurrentToken() == Token::kPERIOD) { | 12980 if (CurrentToken() == Token::kPERIOD) { |
| 12561 ConsumeToken(); // Consume the kPERIOD token. | 12981 ConsumeToken(); // Consume the kPERIOD token. |
| 12562 ExpectIdentifier("identifier expected after '.'"); | 12982 ExpectIdentifier("identifier expected after '.'"); |
| 12563 } | 12983 } |
| 12564 } | 12984 } |
| 12565 | 12985 |
| 12566 } // namespace dart | 12986 } // namespace dart |
| OLD | NEW |