| 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 | 6003 |
| 5962 AddCatchParamsToScope( | 6004 AddCatchParamsToScope( |
| 5963 &exception_param, &stack_trace_param, current_block_->scope); | 6005 &exception_param, &stack_trace_param, current_block_->scope); |
| 5964 | 6006 |
| 6007 // Generate code to save the exception object and stack trace |
| 6008 // in local variables. |
| 5965 LocalVariable* context_var = current_block_->scope->LookupVariable( | 6009 LocalVariable* context_var = current_block_->scope->LookupVariable( |
| 5966 Symbols::SavedTryContextVar(), false); | 6010 Symbols::SavedTryContextVar(), false); |
| 5967 ASSERT(context_var != NULL); | 6011 ASSERT(context_var != NULL); |
| 5968 | 6012 |
| 5969 LocalVariable* exception_var = current_block_->scope->LookupVariable( | 6013 LocalVariable* exception_var = current_block_->scope->LookupVariable( |
| 5970 Symbols::ExceptionVar(), false); | 6014 Symbols::ExceptionVar(), false); |
| 5971 ASSERT(exception_var != NULL); | 6015 ASSERT(exception_var != NULL); |
| 5972 if (exception_param.var != NULL) { | 6016 if (exception_param.var != NULL) { |
| 5973 // Generate code to load the exception object (:exception_var) into | 6017 // Generate code to load the exception object (:exception_var) into |
| 5974 // the exception variable specified in this block. | 6018 // 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 | 6030 // to load the stack trace object (:stack_trace_var) into the stack |
| 5987 // trace variable specified in this block. | 6031 // trace variable specified in this block. |
| 5988 current_block_->statements->Add(new(Z) StoreLocalNode( | 6032 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 5989 Scanner::kNoSourcePos, | 6033 Scanner::kNoSourcePos, |
| 5990 stack_trace_param.var, | 6034 stack_trace_param.var, |
| 5991 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); | 6035 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); |
| 5992 } | 6036 } |
| 5993 | 6037 |
| 5994 SaveExceptionAndStacktrace(exception_var, stack_trace_var); | 6038 SaveExceptionAndStacktrace(exception_var, stack_trace_var); |
| 5995 | 6039 |
| 6040 // Catch block: add the error to the stream. |
| 6041 // :controller.AddError(:exception, :stack_trace); |
| 6042 // return; // The finally block will close the stream. |
| 6043 LocalVariable* controller = |
| 6044 current_block_->scope->LookupVariable(Symbols::Controller(), false); |
| 6045 ASSERT(controller != NULL); |
| 6046 ArgumentListNode* args = |
| 6047 new(Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6048 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); |
| 6049 args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); |
| 6050 current_block_->statements->Add( |
| 6051 new(Z) InstanceCallNode(try_end_pos, |
| 6052 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), |
| 6053 Symbols::AddError(), |
| 6054 args)); |
| 6055 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); |
| 6056 AddNodeForFinallyInlining(return_node); |
| 6057 current_block_->statements->Add(return_node); |
| 6058 AstNode* catch_block = CloseBlock(); |
| 6059 current_block_->statements->Add(catch_block); |
| 6060 SequenceNode* catch_handler_list = CloseBlock(); |
| 6061 |
| 6062 TryBlocks* try_block = PopTryBlock(); |
| 6063 ASSERT(try_blocks_list_ == NULL); // We popped the outermost try block. |
| 6064 |
| 6065 // Finally block: closing the stream and returning. (Note: the return |
| 6066 // is necessary otherwise the back-end will append a rethrow of the |
| 6067 // current exception.) |
| 6068 // :controller.close(); |
| 6069 // return; |
| 6070 // We need to inline this code in all recorded exit points. |
| 6071 intptr_t node_index = 0; |
| 6072 SequenceNode* finally_clause = NULL; |
| 6073 do { |
| 6074 OpenBlock(); |
| 6075 ArgumentListNode* no_args = |
| 6076 new(Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6077 current_block_->statements->Add( |
| 6078 new(Z) InstanceCallNode(try_end_pos, |
| 6079 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller), |
| 6080 Symbols::Close(), |
| 6081 no_args)); |
| 6082 |
| 6083 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos); |
| 6084 current_block_->statements->Add(return_node); |
| 6085 |
| 6086 finally_clause = CloseBlock(); |
| 6087 AstNode* node_to_inline = try_block->GetNodeToInlineFinally(node_index); |
| 6088 if (node_to_inline != NULL) { |
| 6089 InlinedFinallyNode* node = |
| 6090 new(Z) InlinedFinallyNode(try_end_pos, |
| 6091 finally_clause, |
| 6092 context_var, |
| 6093 // No outer try statement |
| 6094 CatchClauseNode::kInvalidTryIndex); |
| 6095 finally_clause = NULL; |
| 6096 AddFinallyBlockToNode(node_to_inline, node); |
| 6097 node_index++; |
| 6098 } |
| 6099 } while (finally_clause == NULL); |
| 6100 |
| 6101 const GrowableObjectArray& handler_types = |
| 6102 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
| 6103 handler_types.Add(dynamic_type); // Catch block handles all exceptions. |
| 6104 |
| 6105 CatchClauseNode* catch_clause = new(Z) CatchClauseNode( |
| 6106 Scanner::kNoSourcePos, |
| 6107 catch_handler_list, |
| 6108 Array::ZoneHandle(Z, Array::MakeArray(handler_types)), |
| 6109 context_var, |
| 6110 exception_var, |
| 6111 stack_trace_var, |
| 6112 AllocateTryIndex(), |
| 6113 true); |
| 6114 |
| 6115 const intptr_t try_index = try_block->try_index(); |
| 6116 |
| 6117 AstNode* try_catch_node = |
| 6118 new(Z) TryCatchNode(Scanner::kNoSourcePos, |
| 6119 body, |
| 6120 context_var, |
| 6121 catch_clause, |
| 6122 finally_clause, |
| 6123 try_index); |
| 6124 current_block_->statements->Add(try_catch_node); |
| 6125 return CloseBlock(); |
| 6126 } |
| 6127 |
| 6128 |
| 6129 SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { |
| 6130 // This is the outermost try-catch of the function. |
| 5996 ASSERT(try_blocks_list_ != NULL); | 6131 ASSERT(try_blocks_list_ != NULL); |
| 5997 ASSERT(innermost_function().IsAsyncClosure() || | 6132 ASSERT(try_blocks_list_->outer_try_block() == NULL); |
| 5998 innermost_function().IsAsyncFunction()); | 6133 ASSERT(innermost_function().IsAsyncClosure()); |
| 5999 const TryBlocks* outer_try_block = try_blocks_list_->outer_try_block(); | 6134 |
| 6000 if (outer_try_block != NULL) { | 6135 try_blocks_list_->enter_catch(); |
| 6001 LocalScope* scope = outer_try_block->try_block()->scope; | 6136 |
| 6002 if (scope->function_level() == current_block_->scope->function_level()) { | 6137 OpenBlock(); // Catch handler list. |
| 6003 current_block_->statements->Add( | 6138 OpenBlock(); // Catch block. |
| 6004 AwaitTransformer::RestoreSavedTryContext( | 6139 const AbstractType& dynamic_type = |
| 6005 Z, scope->parent(), outer_try_block->try_index())); | 6140 AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 6006 } | 6141 CatchParamDesc exception_param; |
| 6142 CatchParamDesc stack_trace_param; |
| 6143 exception_param.token_pos = Scanner::kNoSourcePos; |
| 6144 exception_param.type = &dynamic_type; |
| 6145 exception_param.name = &Symbols::ExceptionParameter(); |
| 6146 stack_trace_param.token_pos = Scanner::kNoSourcePos; |
| 6147 stack_trace_param.type = &dynamic_type; |
| 6148 stack_trace_param.name = &Symbols::StackTraceParameter(); |
| 6149 |
| 6150 AddCatchParamsToScope( |
| 6151 &exception_param, &stack_trace_param, current_block_->scope); |
| 6152 |
| 6153 LocalVariable* context_var = current_block_->scope->LookupVariable( |
| 6154 Symbols::SavedTryContextVar(), false); |
| 6155 ASSERT(context_var != NULL); |
| 6156 |
| 6157 LocalVariable* exception_var = current_block_->scope->LookupVariable( |
| 6158 Symbols::ExceptionVar(), false); |
| 6159 if (exception_param.var != NULL) { |
| 6160 // Generate code to load the exception object (:exception_var) into |
| 6161 // the exception variable specified in this block. |
| 6162 ASSERT(exception_var != NULL); |
| 6163 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 6164 Scanner::kNoSourcePos, |
| 6165 exception_param.var, |
| 6166 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); |
| 6007 } | 6167 } |
| 6008 | 6168 |
| 6009 // Complete the async future with an error. | 6169 LocalVariable* stack_trace_var = |
| 6010 // Since we control the catch block there is no need to generate a nested | 6170 current_block_->scope->LookupVariable(Symbols::StackTraceVar(), false); |
| 6011 // if/then/else. | 6171 if (stack_trace_param.var != NULL) { |
| 6172 // A stack trace variable is specified in this block, so generate code |
| 6173 // to load the stack trace object (:stack_trace_var) into the stack |
| 6174 // trace variable specified in this block. |
| 6175 ASSERT(stack_trace_var != NULL); |
| 6176 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 6177 Scanner::kNoSourcePos, |
| 6178 stack_trace_param.var, |
| 6179 new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var))); |
| 6180 } |
| 6181 |
| 6182 SaveExceptionAndStacktrace(exception_var, stack_trace_var); |
| 6183 |
| 6184 // Complete the async future with an error. This catch block executes |
| 6185 // unconditionally, there is no need to generate a type check for. |
| 6012 LocalVariable* async_completer = current_block_->scope->LookupVariable( | 6186 LocalVariable* async_completer = current_block_->scope->LookupVariable( |
| 6013 Symbols::AsyncCompleter(), false); | 6187 Symbols::AsyncCompleter(), false); |
| 6014 ASSERT(async_completer != NULL); | 6188 ASSERT(async_completer != NULL); |
| 6015 ArgumentListNode* completer_args = | 6189 ArgumentListNode* completer_args = |
| 6016 new (Z) ArgumentListNode(Scanner::kNoSourcePos); | 6190 new (Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6017 completer_args->Add( | 6191 completer_args->Add( |
| 6018 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); | 6192 new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var)); |
| 6019 completer_args->Add( | 6193 completer_args->Add( |
| 6020 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); | 6194 new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var)); |
| 6021 current_block_->statements->Add(new (Z) InstanceCallNode( | 6195 current_block_->statements->Add(new (Z) InstanceCallNode( |
| (...skipping 24 matching lines...) Expand all Loading... |
| 6046 context_var, | 6220 context_var, |
| 6047 exception_var, | 6221 exception_var, |
| 6048 stack_trace_var, | 6222 stack_trace_var, |
| 6049 CatchClauseNode::kInvalidTryIndex, | 6223 CatchClauseNode::kInvalidTryIndex, |
| 6050 true); | 6224 true); |
| 6051 AstNode* try_catch_node = new (Z) TryCatchNode( | 6225 AstNode* try_catch_node = new (Z) TryCatchNode( |
| 6052 Scanner::kNoSourcePos, | 6226 Scanner::kNoSourcePos, |
| 6053 try_block, | 6227 try_block, |
| 6054 context_var, | 6228 context_var, |
| 6055 catch_clause, | 6229 catch_clause, |
| 6056 NULL, | 6230 NULL, // No finally clause. |
| 6057 try_index); | 6231 try_index); |
| 6058 current_block_->statements->Add(try_catch_node); | 6232 current_block_->statements->Add(try_catch_node); |
| 6059 return CloseBlock(); | 6233 return CloseBlock(); |
| 6060 } | 6234 } |
| 6061 | 6235 |
| 6062 | 6236 |
| 6237 // Wrap the body of the async or arync* closure in a try/catch block. |
| 6063 void Parser::OpenAsyncTryBlock() { | 6238 void Parser::OpenAsyncTryBlock() { |
| 6064 // Manually wrapping the actual body into a try/catch block. | 6239 ASSERT(innermost_function().IsAsyncClosure() || |
| 6240 innermost_function().IsAsyncGenClosure()); |
| 6241 |
| 6065 LocalVariable* context_var = | 6242 LocalVariable* context_var = |
| 6066 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); | 6243 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); |
| 6067 if (context_var == NULL) { | 6244 if (context_var == NULL) { |
| 6068 context_var = new(Z) LocalVariable( | 6245 context_var = new(Z) LocalVariable( |
| 6069 TokenPos(), | 6246 TokenPos(), |
| 6070 Symbols::SavedTryContextVar(), | 6247 Symbols::SavedTryContextVar(), |
| 6071 Type::ZoneHandle(Z, Type::DynamicType())); | 6248 Type::ZoneHandle(Z, Type::DynamicType())); |
| 6072 current_block_->scope->AddVariable(context_var); | 6249 current_block_->scope->AddVariable(context_var); |
| 6073 } | 6250 } |
| 6074 LocalVariable* exception_var = | 6251 LocalVariable* exception_var = |
| (...skipping 12 matching lines...) Expand all Loading... |
| 6087 TokenPos(), | 6264 TokenPos(), |
| 6088 Symbols::StackTraceVar(), | 6265 Symbols::StackTraceVar(), |
| 6089 Type::ZoneHandle(Z, Type::DynamicType())); | 6266 Type::ZoneHandle(Z, Type::DynamicType())); |
| 6090 current_block_->scope->AddVariable(stack_trace_var); | 6267 current_block_->scope->AddVariable(stack_trace_var); |
| 6091 } | 6268 } |
| 6092 | 6269 |
| 6093 SetupSavedExceptionAndStacktrace(); | 6270 SetupSavedExceptionAndStacktrace(); |
| 6094 | 6271 |
| 6095 // Open the try block. | 6272 // Open the try block. |
| 6096 OpenBlock(); | 6273 OpenBlock(); |
| 6274 // This is the outermost try-catch in the function. |
| 6275 ASSERT(try_blocks_list_ == NULL); |
| 6097 PushTryBlock(current_block_); | 6276 PushTryBlock(current_block_); |
| 6098 | 6277 |
| 6099 SetupSavedTryContext(context_var); | 6278 SetupSavedTryContext(context_var); |
| 6100 } | 6279 } |
| 6101 | 6280 |
| 6102 | 6281 |
| 6103 void Parser::AddSyncGenClosureParameters(ParamList* params) { | 6282 void Parser::AddSyncGenClosureParameters(ParamList* params) { |
| 6104 // Create the parameter list for the body closure of a sync generator: | 6283 // Create the parameter list for the body closure of a sync generator: |
| 6105 // 1) Implicit closure parameter; | 6284 // 1) Implicit closure parameter; |
| 6106 // 2) Iterator | 6285 // 2) Iterator |
| 6107 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | 6286 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 6108 // Add implicit closure parameter if not already present. | 6287 // Add implicit closure parameter if not already present. |
| 6109 if (params->parameters->length() == 0) { | 6288 if (params->parameters->length() == 0) { |
| 6110 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); | 6289 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); |
| 6111 } | 6290 } |
| 6112 ParamDesc iterator_param; | 6291 ParamDesc iterator_param; |
| 6113 iterator_param.name = &Symbols::IteratorParameter(); | 6292 iterator_param.name = &Symbols::IteratorParameter(); |
| 6114 iterator_param.type = &dynamic_type; | 6293 iterator_param.type = &dynamic_type; |
| 6115 params->parameters->Add(iterator_param); | 6294 params->parameters->Add(iterator_param); |
| 6116 params->num_fixed_parameters++; | 6295 params->num_fixed_parameters++; |
| 6117 } | 6296 } |
| 6118 | 6297 |
| 6119 | 6298 |
| 6299 void Parser::AddAsyncGenClosureParameters(ParamList* params) { |
| 6300 // Create the parameter list for the body closure of an async generator. |
| 6301 // The closure has the same parameters as an asynchronous non-generator. |
| 6302 AddAsyncClosureParameters(params); |
| 6303 } |
| 6304 |
| 6305 |
| 6120 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) { | 6306 RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) { |
| 6121 Function& body = Function::Handle(Z); | 6307 Function& body = Function::Handle(Z); |
| 6122 String& body_closure_name = String::Handle(Z); | 6308 String& body_closure_name = String::Handle(Z); |
| 6123 bool is_new_closure = false; | 6309 bool is_new_closure = false; |
| 6124 | 6310 |
| 6125 AddContinuationVariables(); | 6311 AddContinuationVariables(); |
| 6126 | 6312 |
| 6127 // Check whether a function for the body of this generator | 6313 // Check whether a function for the body of this generator |
| 6128 // function has already been created by a previous | 6314 // function has already been created by a previous |
| 6129 // compilation. | 6315 // compilation. |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6220 iterable_constructor, | 6406 iterable_constructor, |
| 6221 arguments); | 6407 arguments); |
| 6222 ReturnNode* return_node = | 6408 ReturnNode* return_node = |
| 6223 new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable); | 6409 new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable); |
| 6224 current_block_->statements->Add(return_node); | 6410 current_block_->statements->Add(return_node); |
| 6225 return CloseBlock(); | 6411 return CloseBlock(); |
| 6226 } | 6412 } |
| 6227 | 6413 |
| 6228 | 6414 |
| 6229 void Parser::AddAsyncClosureParameters(ParamList* params) { | 6415 void Parser::AddAsyncClosureParameters(ParamList* params) { |
| 6230 // Async closures have two optional parameters: | 6416 // Async closures have three optional parameters: |
| 6231 // * A continuation result. | 6417 // * A continuation result. |
| 6232 // * A continuation error. | 6418 // * A continuation error. |
| 6233 // * A continuation stack trace. | 6419 // * A continuation stack trace. |
| 6234 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | 6420 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 6421 ASSERT(params->parameters->length() <= 1); |
| 6235 // Add implicit closure parameter if not yet present. | 6422 // Add implicit closure parameter if not yet present. |
| 6236 if (params->parameters->length() == 0) { | 6423 if (params->parameters->length() == 0) { |
| 6237 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); | 6424 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); |
| 6238 } | 6425 } |
| 6239 ParamDesc result_param; | 6426 ParamDesc result_param; |
| 6240 result_param.name = &Symbols::AsyncOperationParam(); | 6427 result_param.name = &Symbols::AsyncOperationParam(); |
| 6241 result_param.default_value = &Object::null_instance(); | 6428 result_param.default_value = &Object::null_instance(); |
| 6242 result_param.type = &dynamic_type; | 6429 result_param.type = &dynamic_type; |
| 6243 params->parameters->Add(result_param); | 6430 params->parameters->Add(result_param); |
| 6244 ParamDesc error_param; | 6431 ParamDesc error_param; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6349 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); | 6536 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); |
| 6350 async_op_var->set_is_captured(); | 6537 async_op_var->set_is_captured(); |
| 6351 LocalVariable* async_completer = new(Z) LocalVariable( | 6538 LocalVariable* async_completer = new(Z) LocalVariable( |
| 6352 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); | 6539 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); |
| 6353 current_block_->scope->AddVariable(async_completer); | 6540 current_block_->scope->AddVariable(async_completer); |
| 6354 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); | 6541 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); |
| 6355 async_completer->set_is_captured(); | 6542 async_completer->set_is_captured(); |
| 6356 } | 6543 } |
| 6357 | 6544 |
| 6358 | 6545 |
| 6546 void Parser::AddAsyncGeneratorVariables() { |
| 6547 // Add to current block's scope: |
| 6548 // var :controller; |
| 6549 // The :controller variable is used by the async generator closure to |
| 6550 // store the StreamController object to which the yielded expressions |
| 6551 // are added. |
| 6552 // var :async_op; |
| 6553 // This variable is used to store the async generator closure containing |
| 6554 // the body of the async* function. It is used by the await operator. |
| 6555 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); |
| 6556 LocalVariable* controller_var = new(Z) LocalVariable( |
| 6557 Scanner::kNoSourcePos, Symbols::Controller(), dynamic_type); |
| 6558 current_block_->scope->AddVariable(controller_var); |
| 6559 current_block_->scope->CaptureVariable(Symbols::Controller()); |
| 6560 controller_var->set_is_captured(); |
| 6561 |
| 6562 LocalVariable* async_op_var = new(Z) LocalVariable( |
| 6563 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type); |
| 6564 current_block_->scope->AddVariable(async_op_var); |
| 6565 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); |
| 6566 async_op_var->set_is_captured(); |
| 6567 } |
| 6568 |
| 6569 |
| 6570 RawFunction* Parser::OpenAsyncGeneratorFunction(intptr_t async_func_pos) { |
| 6571 TRACE_PARSER("OpenAsyncGeneratorFunction"); |
| 6572 AddContinuationVariables(); |
| 6573 AddAsyncGeneratorVariables(); |
| 6574 |
| 6575 Function& closure = Function::Handle(Z); |
| 6576 bool is_new_closure = false; |
| 6577 |
| 6578 // Check whether a function for the asynchronous function body of |
| 6579 // this async generator has already been created by a previous |
| 6580 // compilation of this function. |
| 6581 const Function& found_func = Function::Handle( |
| 6582 Z, current_class().LookupClosureFunction(async_func_pos)); |
| 6583 if (!found_func.IsNull() && |
| 6584 (found_func.token_pos() == async_func_pos) && |
| 6585 (found_func.script() == innermost_function().script()) && |
| 6586 (found_func.parent_function() == innermost_function().raw())) { |
| 6587 ASSERT(found_func.IsAsyncGenClosure()); |
| 6588 closure = found_func.raw(); |
| 6589 } else { |
| 6590 // Create the closure containing the body of this async generator function. |
| 6591 const String& async_generator_name = |
| 6592 String::Handle(Z, innermost_function().name()); |
| 6593 String& closure_name = String::Handle(Z, |
| 6594 String::NewFormatted("<%s_async_gen_body>", |
| 6595 async_generator_name.ToCString())); |
| 6596 closure = Function::NewClosureFunction( |
| 6597 String::Handle(Z, Symbols::New(closure_name)), |
| 6598 innermost_function(), |
| 6599 async_func_pos); |
| 6600 closure.set_is_generated_body(true); |
| 6601 closure.set_result_type(AbstractType::Handle(Type::DynamicType())); |
| 6602 is_new_closure = true; |
| 6603 } |
| 6604 |
| 6605 ParamList closure_params; |
| 6606 AddAsyncGenClosureParameters(&closure_params); |
| 6607 |
| 6608 if (is_new_closure) { |
| 6609 // Add the parameters to the newly created closure. |
| 6610 AddFormalParamsToFunction(&closure_params, closure); |
| 6611 |
| 6612 // Create and set the signature class of the closure. |
| 6613 const String& sig = String::Handle(Z, closure.Signature()); |
| 6614 Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig)); |
| 6615 if (sig_cls.IsNull()) { |
| 6616 sig_cls = |
| 6617 Class::NewSignatureClass(sig, closure, script_, closure.token_pos()); |
| 6618 library_.AddClass(sig_cls); |
| 6619 } |
| 6620 closure.set_signature_class(sig_cls); |
| 6621 const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType()); |
| 6622 if (!sig_type.IsFinalized()) { |
| 6623 ClassFinalizer::FinalizeType( |
| 6624 sig_cls, sig_type, ClassFinalizer::kCanonicalize); |
| 6625 } |
| 6626 ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved()); |
| 6627 ASSERT(closure.NumParameters() == closure_params.parameters->length()); |
| 6628 } |
| 6629 |
| 6630 OpenFunctionBlock(closure); |
| 6631 AddFormalParamsToScope(&closure_params, current_block_->scope); |
| 6632 OpenBlock(); |
| 6633 async_temp_scope_ = current_block_->scope; |
| 6634 return closure.raw(); |
| 6635 } |
| 6636 |
| 6637 |
| 6638 // Generate the Ast nodes for the implicit code of the async* function. |
| 6639 // |
| 6640 // f(...) async* { |
| 6641 // var :controller; |
| 6642 // var :await_jump_var = -1; |
| 6643 // var :await_context_var; |
| 6644 // f_async_body() { |
| 6645 // ... source code of f ... |
| 6646 // } |
| 6647 // var :async_op = f_async_body; |
| 6648 // :controller = new _AsyncStarStreamController(f_async_body); |
| 6649 // return :controller.stream; |
| 6650 // } |
| 6651 SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure, |
| 6652 SequenceNode* closure_body) { |
| 6653 TRACE_PARSER("CloseAsyncGeneratorFunction"); |
| 6654 ASSERT(!closure.IsNull()); |
| 6655 ASSERT(closure_body != NULL); |
| 6656 |
| 6657 // The block for the async closure body has already been closed. Close the |
| 6658 // corresponding function block. |
| 6659 CloseBlock(); |
| 6660 |
| 6661 // Make sure the implicit variables of the async generator function |
| 6662 // are captured. |
| 6663 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 6664 closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
| 6665 closure_body->scope()->LookupVariable(Symbols::Controller(), false); |
| 6666 closure_body->scope()->LookupVariable(Symbols::AsyncOperation(), false); |
| 6667 |
| 6668 const Class& controller_class = Class::Handle(Z, |
| 6669 Library::LookupCoreClass(Symbols::_AsyncStarStreamController())); |
| 6670 ASSERT(!controller_class.IsNull()); |
| 6671 const Function& controller_constructor = Function::ZoneHandle(Z, |
| 6672 controller_class.LookupConstructorAllowPrivate( |
| 6673 Symbols::_AsyncStarStreamControllerConstructor())); |
| 6674 |
| 6675 // :await_jump_var = -1; |
| 6676 LocalVariable* jump_var = |
| 6677 current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 6678 LiteralNode* init_value = |
| 6679 new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1))); |
| 6680 current_block_->statements->Add( |
| 6681 new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value)); |
| 6682 |
| 6683 // Add to AST: |
| 6684 // :async_op = <closure>; (containing the original body) |
| 6685 LocalVariable* async_op_var = |
| 6686 current_block_->scope->LookupVariable(Symbols::AsyncOperation(), false); |
| 6687 ClosureNode* cn = new(Z) ClosureNode( |
| 6688 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); |
| 6689 StoreLocalNode* store_async_op = new (Z) StoreLocalNode( |
| 6690 Scanner::kNoSourcePos, |
| 6691 async_op_var, |
| 6692 cn); |
| 6693 current_block_->statements->Add(store_async_op); |
| 6694 |
| 6695 // :controller = new _AsyncStarStreamController(body_closure); |
| 6696 ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos); |
| 6697 ClosureNode* closure_obj = new(Z) ClosureNode( |
| 6698 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); |
| 6699 arguments->Add(closure_obj); |
| 6700 ConstructorCallNode* controller_constructor_call = |
| 6701 new(Z) ConstructorCallNode(Scanner::kNoSourcePos, |
| 6702 TypeArguments::ZoneHandle(Z), |
| 6703 controller_constructor, |
| 6704 arguments); |
| 6705 LocalVariable* controller_var = |
| 6706 current_block_->scope->LookupVariable(Symbols::Controller(), false); |
| 6707 StoreLocalNode* store_controller = |
| 6708 new(Z) StoreLocalNode(Scanner::kNoSourcePos, |
| 6709 controller_var, |
| 6710 controller_constructor_call); |
| 6711 current_block_->statements->Add(store_controller); |
| 6712 |
| 6713 // return :controller.stream; |
| 6714 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos, |
| 6715 new(Z) InstanceGetterNode(Scanner::kNoSourcePos, |
| 6716 new(Z) LoadLocalNode(Scanner::kNoSourcePos, |
| 6717 controller_var), |
| 6718 Symbols::Stream())); |
| 6719 current_block_->statements->Add(return_node); |
| 6720 return CloseBlock(); |
| 6721 } |
| 6722 |
| 6723 |
| 6724 void Parser::OpenAsyncGeneratorClosure() { |
| 6725 async_temp_scope_ = current_block_->scope; |
| 6726 OpenAsyncTryBlock(); |
| 6727 } |
| 6728 |
| 6729 |
| 6730 SequenceNode* Parser::CloseAsyncGeneratorClosure(SequenceNode* body) { |
| 6731 // We need a temporary expression to store intermediate return values. |
| 6732 parsed_function()->EnsureExpressionTemp(); |
| 6733 |
| 6734 SequenceNode* new_body = CloseAsyncGeneratorTryBlock(body); |
| 6735 ASSERT(new_body != NULL); |
| 6736 ASSERT(new_body->scope() != NULL); |
| 6737 |
| 6738 // Implicitly mark those variables below as captured. We currently mark all |
| 6739 // variables of all scopes as captured, but as soon as we do something |
| 6740 // smarter we rely on these internal variables to be available. |
| 6741 new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 6742 new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
| 6743 new_body->scope()->LookupVariable(Symbols::Controller(), false); |
| 6744 new_body->scope()->LookupVariable(Symbols::AsyncOperationParam(), false); |
| 6745 new_body->scope()->LookupVariable(Symbols::AsyncOperationErrorParam(), false); |
| 6746 new_body->scope()->LookupVariable( |
| 6747 Symbols::AsyncOperationStackTraceParam(), false); |
| 6748 new_body->scope()->RecursivelyCaptureAllVariables(); |
| 6749 return new_body; |
| 6750 } |
| 6751 |
| 6752 |
| 6359 SequenceNode* Parser::CloseBlock() { | 6753 SequenceNode* Parser::CloseBlock() { |
| 6360 SequenceNode* statements = current_block_->statements; | 6754 SequenceNode* statements = current_block_->statements; |
| 6361 if (current_block_->scope != NULL) { | 6755 if (current_block_->scope != NULL) { |
| 6362 // Record the begin and end token index of the scope. | 6756 // Record the begin and end token index of the scope. |
| 6363 ASSERT(statements != NULL); | 6757 ASSERT(statements != NULL); |
| 6364 current_block_->scope->set_begin_token_pos(statements->token_pos()); | 6758 current_block_->scope->set_begin_token_pos(statements->token_pos()); |
| 6365 current_block_->scope->set_end_token_pos(TokenPos()); | 6759 current_block_->scope->set_end_token_pos(TokenPos()); |
| 6366 } | 6760 } |
| 6367 current_block_ = current_block_->parent; | 6761 current_block_ = current_block_->parent; |
| 6368 return statements; | 6762 return statements; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6458 new (Z) LoadLocalNode( | 6852 new (Z) LoadLocalNode( |
| 6459 Scanner::kNoSourcePos, | 6853 Scanner::kNoSourcePos, |
| 6460 async_completer), | 6854 async_completer), |
| 6461 Symbols::CompleterFuture())); | 6855 Symbols::CompleterFuture())); |
| 6462 current_block_->statements->Add(return_node); | 6856 current_block_->statements->Add(return_node); |
| 6463 return CloseBlock(); | 6857 return CloseBlock(); |
| 6464 } | 6858 } |
| 6465 | 6859 |
| 6466 | 6860 |
| 6467 SequenceNode* Parser::CloseAsyncClosure(SequenceNode* body) { | 6861 SequenceNode* Parser::CloseAsyncClosure(SequenceNode* body) { |
| 6468 TRACE_PARSER("CloseAsyncClosure"); | |
| 6469 | |
| 6470 // We need a temporary expression to store intermediate return values. | 6862 // We need a temporary expression to store intermediate return values. |
| 6471 parsed_function()->EnsureExpressionTemp(); | 6863 parsed_function()->EnsureExpressionTemp(); |
| 6472 // Implicitly mark those variables below as captured. We currently mark all | 6864 // Implicitly mark those variables below as captured. We currently mark all |
| 6473 // variables of all scopes as captured (below), but as soon as we do something | 6865 // variables of all scopes as captured (below), but as soon as we do something |
| 6474 // smarter we rely on these internal variables to be available. | 6866 // smarter we rely on these internal variables to be available. |
| 6475 SequenceNode* new_body = CloseAsyncTryBlock(body); | 6867 SequenceNode* new_body = CloseAsyncTryBlock(body); |
| 6476 ASSERT(new_body != NULL); | 6868 ASSERT(new_body != NULL); |
| 6477 ASSERT(new_body->scope() != NULL); | 6869 ASSERT(new_body->scope() != NULL); |
| 6478 new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | 6870 new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
| 6479 new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); | 6871 new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
| (...skipping 1314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7794 *outer_try_index = try_blocks_list_->outer_try_block()->try_index(); | 8186 *outer_try_index = try_blocks_list_->outer_try_block()->try_index(); |
| 7795 } | 8187 } |
| 7796 } | 8188 } |
| 7797 } | 8189 } |
| 7798 } | 8190 } |
| 7799 // An async or async* has an implicitly created try-catch around the | 8191 // An async or async* has an implicitly created try-catch around the |
| 7800 // function body, so the await or yield inside the async closure should always | 8192 // function body, so the await or yield inside the async closure should always |
| 7801 // be created with a try scope. | 8193 // be created with a try scope. |
| 7802 ASSERT((*try_scope != NULL) || | 8194 ASSERT((*try_scope != NULL) || |
| 7803 innermost_function().IsAsyncFunction() || | 8195 innermost_function().IsAsyncFunction() || |
| 8196 innermost_function().IsAsyncGenerator() || |
| 7804 innermost_function().IsSyncGenClosure() || | 8197 innermost_function().IsSyncGenClosure() || |
| 7805 innermost_function().IsSyncGenerator()); | 8198 innermost_function().IsSyncGenerator()); |
| 7806 } | 8199 } |
| 7807 | 8200 |
| 7808 | 8201 |
| 7809 AstNode* Parser::ParseAwaitForStatement(String* label_name) { | 8202 AstNode* Parser::ParseAwaitForStatement(String* label_name) { |
| 7810 TRACE_PARSER("ParseAwaitForStatement"); | 8203 TRACE_PARSER("ParseAwaitForStatement"); |
| 7811 ASSERT(IsAwaitKeyword()); | 8204 ASSERT(IsAwaitKeyword()); |
| 7812 const intptr_t await_for_pos = TokenPos(); | 8205 const intptr_t await_for_pos = TokenPos(); |
| 7813 ConsumeToken(); // await. | 8206 ConsumeToken(); // await. |
| 7814 ASSERT(CurrentToken() == Token::kFOR); | 8207 ASSERT(CurrentToken() == Token::kFOR); |
| 7815 ConsumeToken(); // for. | 8208 ConsumeToken(); // for. |
| 7816 ExpectToken(Token::kLPAREN); | 8209 ExpectToken(Token::kLPAREN); |
| 7817 | 8210 |
| 7818 if (!innermost_function().IsAsyncFunction() && | 8211 if (!innermost_function().IsAsyncFunction() && |
| 7819 !innermost_function().IsAsyncClosure()) { | 8212 !innermost_function().IsAsyncClosure() && |
| 8213 !innermost_function().IsAsyncGenerator() && |
| 8214 !innermost_function().IsAsyncGenClosure()) { |
| 7820 ReportError(await_for_pos, | 8215 ReportError(await_for_pos, |
| 7821 "await for loop is only allowed in async function"); | 8216 "await for loop is only allowed in an asynchronous function"); |
| 7822 } | 8217 } |
| 7823 | 8218 |
| 7824 // Parse loop variable. | 8219 // Parse loop variable. |
| 7825 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); | 8220 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); |
| 7826 if (CurrentToken() == Token::kCONST) { | 8221 if (CurrentToken() == Token::kCONST) { |
| 7827 ReportError("Loop variable cannot be 'const'"); | 8222 ReportError("Loop variable cannot be 'const'"); |
| 7828 } | 8223 } |
| 7829 bool new_loop_var = false; | 8224 bool new_loop_var = false; |
| 7830 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); | 8225 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); |
| 7831 if (LookaheadToken(1) != Token::kIN) { | 8226 if (LookaheadToken(1) != Token::kIN) { |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8256 } | 8651 } |
| 8257 } | 8652 } |
| 8258 | 8653 |
| 8259 | 8654 |
| 8260 // Populate current scope of the try block with the saved exception and saved | 8655 // Populate current scope of the try block with the saved exception and saved |
| 8261 // stack trace. | 8656 // stack trace. |
| 8262 void Parser::SetupSavedExceptionAndStacktrace() { | 8657 void Parser::SetupSavedExceptionAndStacktrace() { |
| 8263 ASSERT(innermost_function().IsAsyncClosure() || | 8658 ASSERT(innermost_function().IsAsyncClosure() || |
| 8264 innermost_function().IsAsyncFunction() || | 8659 innermost_function().IsAsyncFunction() || |
| 8265 innermost_function().IsSyncGenClosure() || | 8660 innermost_function().IsSyncGenClosure() || |
| 8266 innermost_function().IsSyncGenerator()); | 8661 innermost_function().IsSyncGenerator() || |
| 8662 innermost_function().IsAsyncGenerator() || |
| 8663 innermost_function().IsAsyncGenClosure()); |
| 8267 // Add :saved_exception_var and :saved_stack_trace_var to current scope. | 8664 // Add :saved_exception_var and :saved_stack_trace_var to current scope. |
| 8268 // They will automatically get captured. | 8665 // They will automatically get captured. |
| 8269 // Parallel try statements share the same set of variables. | 8666 // Parallel try statements share the same set of variables. |
| 8270 LocalVariable* saved_exception_var = | 8667 LocalVariable* saved_exception_var = |
| 8271 current_block_->scope->LocalLookupVariable(Symbols::SavedExceptionVar()); | 8668 current_block_->scope->LocalLookupVariable(Symbols::SavedExceptionVar()); |
| 8272 if (saved_exception_var == NULL) { | 8669 if (saved_exception_var == NULL) { |
| 8273 saved_exception_var = new (Z) LocalVariable( | 8670 saved_exception_var = new (Z) LocalVariable( |
| 8274 Scanner::kNoSourcePos, | 8671 Scanner::kNoSourcePos, |
| 8275 Symbols::SavedExceptionVar(), | 8672 Symbols::SavedExceptionVar(), |
| 8276 Type::ZoneHandle(Z, Type::DynamicType())); | 8673 Type::ZoneHandle(Z, Type::DynamicType())); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 8290 } | 8687 } |
| 8291 | 8688 |
| 8292 | 8689 |
| 8293 // Generate code to load the exception object (:exception_var) into | 8690 // Generate code to load the exception object (:exception_var) into |
| 8294 // the saved exception variable (:saved_exception_var) used to rethrow. | 8691 // the saved exception variable (:saved_exception_var) used to rethrow. |
| 8295 void Parser::SaveExceptionAndStacktrace(LocalVariable* exception_var, | 8692 void Parser::SaveExceptionAndStacktrace(LocalVariable* exception_var, |
| 8296 LocalVariable* stack_trace_var) { | 8693 LocalVariable* stack_trace_var) { |
| 8297 ASSERT(innermost_function().IsAsyncClosure() || | 8694 ASSERT(innermost_function().IsAsyncClosure() || |
| 8298 innermost_function().IsAsyncFunction() || | 8695 innermost_function().IsAsyncFunction() || |
| 8299 innermost_function().IsSyncGenClosure() || | 8696 innermost_function().IsSyncGenClosure() || |
| 8300 innermost_function().IsSyncGenerator()); | 8697 innermost_function().IsSyncGenerator() || |
| 8698 innermost_function().IsAsyncGenClosure() || |
| 8699 innermost_function().IsAsyncGenerator()); |
| 8301 LocalVariable* saved_exception_var = current_block_->scope->LookupVariable( | 8700 LocalVariable* saved_exception_var = current_block_->scope->LookupVariable( |
| 8302 Symbols::SavedExceptionVar(), false); | 8701 Symbols::SavedExceptionVar(), false); |
| 8303 ASSERT(saved_exception_var != NULL); | 8702 ASSERT(saved_exception_var != NULL); |
| 8304 ASSERT(exception_var != NULL); | 8703 ASSERT(exception_var != NULL); |
| 8305 current_block_->statements->Add(new(Z) StoreLocalNode( | 8704 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 8306 Scanner::kNoSourcePos, | 8705 Scanner::kNoSourcePos, |
| 8307 saved_exception_var, | 8706 saved_exception_var, |
| 8308 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); | 8707 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); |
| 8309 | 8708 |
| 8310 // Generate code to load the stack trace object (:stack_trace_var) into | 8709 // Generate code to load the stack trace object (:stack_trace_var) into |
| (...skipping 13 matching lines...) Expand all Loading... |
| 8324 TRACE_PARSER("ParseFinallyBlock"); | 8723 TRACE_PARSER("ParseFinallyBlock"); |
| 8325 OpenBlock(); | 8724 OpenBlock(); |
| 8326 ExpectToken(Token::kLBRACE); | 8725 ExpectToken(Token::kLBRACE); |
| 8327 | 8726 |
| 8328 // In case of async closures we need to restore the saved try index of an | 8727 // In case of async closures we need to restore the saved try index of an |
| 8329 // outer try block (if it exists). The current try block has already been | 8728 // outer try block (if it exists). The current try block has already been |
| 8330 // removed from the stack of try blocks. | 8729 // removed from the stack of try blocks. |
| 8331 if ((innermost_function().IsAsyncClosure() || | 8730 if ((innermost_function().IsAsyncClosure() || |
| 8332 innermost_function().IsAsyncFunction() || | 8731 innermost_function().IsAsyncFunction() || |
| 8333 innermost_function().IsSyncGenClosure() || | 8732 innermost_function().IsSyncGenClosure() || |
| 8334 innermost_function().IsSyncGenerator()) && | 8733 innermost_function().IsSyncGenerator() || |
| 8734 innermost_function().IsAsyncGenerator() || |
| 8735 innermost_function().IsAsyncGenClosure()) && |
| 8335 (try_blocks_list_ != NULL)) { | 8736 (try_blocks_list_ != NULL)) { |
| 8336 LocalScope* scope = try_blocks_list_->try_block()->scope; | 8737 LocalScope* scope = try_blocks_list_->try_block()->scope; |
| 8337 if (scope->function_level() == current_block_->scope->function_level()) { | 8738 if (scope->function_level() == current_block_->scope->function_level()) { |
| 8338 current_block_->statements->Add( | 8739 current_block_->statements->Add( |
| 8339 AwaitTransformer::RestoreSavedTryContext( | 8740 AwaitTransformer::RestoreSavedTryContext( |
| 8340 Z, scope->parent(), try_blocks_list_->try_index())); | 8741 Z, scope->parent(), try_blocks_list_->try_index())); |
| 8341 } | 8742 } |
| 8342 } | 8743 } |
| 8343 | 8744 |
| 8344 ParseStatementSequence(); | 8745 ParseStatementSequence(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8433 } else { | 8834 } else { |
| 8434 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); | 8835 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 8435 } | 8836 } |
| 8436 if (CurrentToken() == Token::kCATCH) { | 8837 if (CurrentToken() == Token::kCATCH) { |
| 8437 ConsumeToken(); // Consume the 'catch'. | 8838 ConsumeToken(); // Consume the 'catch'. |
| 8438 ExpectToken(Token::kLPAREN); | 8839 ExpectToken(Token::kLPAREN); |
| 8439 exception_param.token_pos = TokenPos(); | 8840 exception_param.token_pos = TokenPos(); |
| 8440 exception_param.name = ExpectIdentifier("identifier expected"); | 8841 exception_param.name = ExpectIdentifier("identifier expected"); |
| 8441 if (CurrentToken() == Token::kCOMMA) { | 8842 if (CurrentToken() == Token::kCOMMA) { |
| 8442 ConsumeToken(); | 8843 ConsumeToken(); |
| 8443 // TODO(hausner): Make implicit type be StackTrace, not dynamic. | |
| 8444 stack_trace_param.type = | 8844 stack_trace_param.type = |
| 8445 &AbstractType::ZoneHandle(Z, Type::DynamicType()); | 8845 &AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 8446 stack_trace_param.token_pos = TokenPos(); | 8846 stack_trace_param.token_pos = TokenPos(); |
| 8447 stack_trace_param.name = ExpectIdentifier("identifier expected"); | 8847 stack_trace_param.name = ExpectIdentifier("identifier expected"); |
| 8448 } | 8848 } |
| 8449 ExpectToken(Token::kRPAREN); | 8849 ExpectToken(Token::kRPAREN); |
| 8450 } | 8850 } |
| 8451 | 8851 |
| 8452 // Create a block containing the catch clause parameters and the | 8852 // Create a block containing the catch clause parameters and the |
| 8453 // following code: | 8853 // following code: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 8472 // A stack trace variable is specified in this block, so generate code | 8872 // A stack trace variable is specified in this block, so generate code |
| 8473 // to load the stack trace object (:stack_trace_var) into the stack | 8873 // to load the stack trace object (:stack_trace_var) into the stack |
| 8474 // trace variable specified in this block. | 8874 // trace variable specified in this block. |
| 8475 *needs_stack_trace = true; | 8875 *needs_stack_trace = true; |
| 8476 ASSERT(stack_trace_var != NULL); | 8876 ASSERT(stack_trace_var != NULL); |
| 8477 current_block_->statements->Add(new(Z) StoreLocalNode( | 8877 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 8478 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( | 8878 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( |
| 8479 catch_pos, stack_trace_var))); | 8879 catch_pos, stack_trace_var))); |
| 8480 } | 8880 } |
| 8481 | 8881 |
| 8482 // Add nested block with user-defined code. This blocks allows | 8882 // Add nested block with user-defined code. This block allows |
| 8483 // declarations in the body to shadow the catch parameters. | 8883 // declarations in the body to shadow the catch parameters. |
| 8484 CheckToken(Token::kLBRACE); | 8884 CheckToken(Token::kLBRACE); |
| 8485 | 8885 |
| 8486 // In case of async closures we need to restore the saved try index of an | 8886 // In case of async closures we need to restore the saved try index of an |
| 8487 // outer try block (if it exists). | 8887 // outer try block (if it exists). |
| 8488 ASSERT(try_blocks_list_ != NULL); | 8888 ASSERT(try_blocks_list_ != NULL); |
| 8489 if (innermost_function().IsAsyncClosure() || | 8889 if (innermost_function().IsAsyncClosure() || |
| 8490 innermost_function().IsAsyncFunction() || | 8890 innermost_function().IsAsyncFunction() || |
| 8491 innermost_function().IsSyncGenClosure() || | 8891 innermost_function().IsSyncGenClosure() || |
| 8492 innermost_function().IsSyncGenerator()) { | 8892 innermost_function().IsSyncGenerator() || |
| 8893 innermost_function().IsAsyncGenerator() || |
| 8894 innermost_function().IsAsyncGenClosure()) { |
| 8493 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); | 8895 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); |
| 8494 if (try_block != NULL) { | 8896 if (try_block != NULL) { |
| 8495 LocalScope* scope = try_block->try_block()->scope; | 8897 LocalScope* scope = try_block->try_block()->scope; |
| 8496 if (scope->function_level() == | 8898 if (scope->function_level() == |
| 8497 current_block_->scope->function_level()) { | 8899 current_block_->scope->function_level()) { |
| 8498 current_block_->statements->Add( | 8900 current_block_->statements->Add( |
| 8499 AwaitTransformer::RestoreSavedTryContext( | 8901 AwaitTransformer::RestoreSavedTryContext( |
| 8500 Z, scope->parent(), try_block->try_index())); | 8902 Z, scope->parent(), try_block->try_index())); |
| 8501 } | 8903 } |
| 8502 } | 8904 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8595 current_block_->statements->Add(new(Z) IfNode( | 8997 current_block_->statements->Add(new(Z) IfNode( |
| 8596 type_test->token_pos(), type_test, catch_block, current)); | 8998 type_test->token_pos(), type_test, catch_block, current)); |
| 8597 current = CloseBlock(); | 8999 current = CloseBlock(); |
| 8598 } | 9000 } |
| 8599 // Restore :saved_try_context_var before executing the catch clauses. | 9001 // Restore :saved_try_context_var before executing the catch clauses. |
| 8600 if (current != NULL) { | 9002 if (current != NULL) { |
| 8601 ASSERT(try_blocks_list_ != NULL); | 9003 ASSERT(try_blocks_list_ != NULL); |
| 8602 if (innermost_function().IsAsyncClosure() || | 9004 if (innermost_function().IsAsyncClosure() || |
| 8603 innermost_function().IsAsyncFunction() || | 9005 innermost_function().IsAsyncFunction() || |
| 8604 innermost_function().IsSyncGenClosure() || | 9006 innermost_function().IsSyncGenClosure() || |
| 8605 innermost_function().IsSyncGenerator()) { | 9007 innermost_function().IsSyncGenerator() || |
| 9008 innermost_function().IsAsyncGenerator() || |
| 9009 innermost_function().IsAsyncGenClosure()) { |
| 8606 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); | 9010 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); |
| 8607 if (try_block != NULL) { | 9011 if (try_block != NULL) { |
| 8608 LocalScope* scope = try_block->try_block()->scope; | 9012 LocalScope* scope = try_block->try_block()->scope; |
| 8609 if (scope->function_level() == | 9013 if (scope->function_level() == |
| 8610 current_block_->scope->function_level()) { | 9014 current_block_->scope->function_level()) { |
| 8611 SequenceNode* restore_code = new(Z) SequenceNode(handler_pos, NULL); | 9015 SequenceNode* restore_code = new(Z) SequenceNode(handler_pos, NULL); |
| 8612 restore_code->Add( | 9016 restore_code->Add( |
| 8613 AwaitTransformer::RestoreSavedTryContext( | 9017 AwaitTransformer::RestoreSavedTryContext( |
| 8614 Z, scope->parent(), try_block->try_index())); | 9018 Z, scope->parent(), try_block->try_index())); |
| 8615 restore_code->Add(current); | 9019 restore_code->Add(current); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8687 stack_trace_var = new(Z) LocalVariable( | 9091 stack_trace_var = new(Z) LocalVariable( |
| 8688 TokenPos(), | 9092 TokenPos(), |
| 8689 Symbols::StackTraceVar(), | 9093 Symbols::StackTraceVar(), |
| 8690 Type::ZoneHandle(Z, Type::DynamicType())); | 9094 Type::ZoneHandle(Z, Type::DynamicType())); |
| 8691 current_block_->scope->AddVariable(stack_trace_var); | 9095 current_block_->scope->AddVariable(stack_trace_var); |
| 8692 } | 9096 } |
| 8693 | 9097 |
| 8694 if (innermost_function().IsAsyncClosure() || | 9098 if (innermost_function().IsAsyncClosure() || |
| 8695 innermost_function().IsAsyncFunction() || | 9099 innermost_function().IsAsyncFunction() || |
| 8696 innermost_function().IsSyncGenClosure() || | 9100 innermost_function().IsSyncGenClosure() || |
| 8697 innermost_function().IsSyncGenerator()) { | 9101 innermost_function().IsSyncGenerator() || |
| 9102 innermost_function().IsAsyncGenClosure() || |
| 9103 innermost_function().IsAsyncGenerator()) { |
| 8698 SetupSavedExceptionAndStacktrace(); | 9104 SetupSavedExceptionAndStacktrace(); |
| 8699 } | 9105 } |
| 8700 | 9106 |
| 8701 const intptr_t try_pos = TokenPos(); | 9107 const intptr_t try_pos = TokenPos(); |
| 8702 ConsumeToken(); // Consume the 'try'. | 9108 ConsumeToken(); // Consume the 'try'. |
| 8703 | 9109 |
| 8704 SourceLabel* try_label = NULL; | 9110 SourceLabel* try_label = NULL; |
| 8705 if (label_name != NULL) { | 9111 if (label_name != NULL) { |
| 8706 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); | 9112 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); |
| 8707 OpenBlock(); | 9113 OpenBlock(); |
| 8708 current_block_->scope->AddLabel(try_label); | 9114 current_block_->scope->AddLabel(try_label); |
| 8709 } | 9115 } |
| 8710 | 9116 |
| 8711 // Now parse the 'try' block. | 9117 // Now parse the 'try' block. |
| 8712 OpenBlock(); | 9118 OpenBlock(); |
| 8713 PushTryBlock(current_block_); | 9119 PushTryBlock(current_block_); |
| 8714 ExpectToken(Token::kLBRACE); | 9120 ExpectToken(Token::kLBRACE); |
| 8715 | 9121 |
| 8716 if (innermost_function().IsAsyncClosure() || | 9122 if (innermost_function().IsAsyncClosure() || |
| 8717 innermost_function().IsAsyncFunction() || | 9123 innermost_function().IsAsyncFunction() || |
| 8718 innermost_function().IsSyncGenClosure() || | 9124 innermost_function().IsSyncGenClosure() || |
| 8719 innermost_function().IsSyncGenerator()) { | 9125 innermost_function().IsSyncGenerator() || |
| 9126 innermost_function().IsAsyncGenerator() || |
| 9127 innermost_function().IsAsyncGenClosure()) { |
| 8720 SetupSavedTryContext(context_var); | 9128 SetupSavedTryContext(context_var); |
| 8721 } | 9129 } |
| 8722 | 9130 |
| 8723 ParseStatementSequence(); | 9131 ParseStatementSequence(); |
| 8724 ExpectToken(Token::kRBRACE); | 9132 ExpectToken(Token::kRBRACE); |
| 8725 SequenceNode* try_block = CloseBlock(); | 9133 SequenceNode* try_block = CloseBlock(); |
| 8726 | 9134 |
| 8727 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 9135 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
| 8728 (CurrentToken() != Token::kFINALLY)) { | 9136 (CurrentToken() != Token::kFINALLY)) { |
| 8729 ReportError("catch or finally clause expected"); | 9137 ReportError("catch or finally clause expected"); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8853 ReportError(jump_pos, "'break' to case clause label is illegal"); | 9261 ReportError(jump_pos, "'break' to case clause label is illegal"); |
| 8854 } | 9262 } |
| 8855 if (target->FunctionLevel() != current_block_->scope->function_level()) { | 9263 if (target->FunctionLevel() != current_block_->scope->function_level()) { |
| 8856 ReportError(jump_pos, "'%s' target must be in same function context", | 9264 ReportError(jump_pos, "'%s' target must be in same function context", |
| 8857 Token::Str(jump_kind)); | 9265 Token::Str(jump_kind)); |
| 8858 } | 9266 } |
| 8859 return new(Z) JumpNode(jump_pos, jump_kind, target); | 9267 return new(Z) JumpNode(jump_pos, jump_kind, target); |
| 8860 } | 9268 } |
| 8861 | 9269 |
| 8862 | 9270 |
| 9271 AstNode* Parser::ParseYieldStatement() { |
| 9272 bool is_yield_each = false; |
| 9273 const intptr_t yield_pos = TokenPos(); |
| 9274 ConsumeToken(); // yield reserved word. |
| 9275 ASSERT(innermost_function().IsGenerator() || |
| 9276 innermost_function().IsSyncGenClosure() || |
| 9277 innermost_function().IsAsyncGenerator() || |
| 9278 innermost_function().IsAsyncGenClosure()); |
| 9279 if (CurrentToken() == Token::kMUL) { |
| 9280 is_yield_each = true; |
| 9281 ConsumeToken(); |
| 9282 } |
| 9283 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 9284 |
| 9285 LetNode* yield = new(Z) LetNode(yield_pos); |
| 9286 if (innermost_function().IsSyncGenerator() || |
| 9287 innermost_function().IsSyncGenClosure()) { |
| 9288 // Yield statement in sync* function. |
| 9289 |
| 9290 LocalVariable* iterator_param = |
| 9291 LookupLocalScope(Symbols::IteratorParameter()); |
| 9292 ASSERT(iterator_param != NULL); |
| 9293 // Generate :iterator.current = expr; |
| 9294 AstNode* iterator = |
| 9295 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param); |
| 9296 AstNode* store_current = |
| 9297 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, |
| 9298 iterator, |
| 9299 String::ZoneHandle(Symbols::Current().raw()), |
| 9300 expr); |
| 9301 yield->AddNode(store_current); |
| 9302 if (is_yield_each) { |
| 9303 // Generate :iterator.isYieldEach = true; |
| 9304 AstNode* set_is_yield_each = |
| 9305 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, |
| 9306 iterator, |
| 9307 String::ZoneHandle(Symbols::IsYieldEach().raw()), |
| 9308 new(Z) LiteralNode(TokenPos(), Bool::True())); |
| 9309 yield->AddNode(set_is_yield_each); |
| 9310 } |
| 9311 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); |
| 9312 await_marker->set_scope(current_block_->scope); |
| 9313 yield->AddNode(await_marker); |
| 9314 // Return true to indicate that a value has been generated. |
| 9315 ReturnNode* return_true = new(Z) ReturnNode(yield_pos, |
| 9316 new(Z) LiteralNode(TokenPos(), Bool::True())); |
| 9317 return_true->set_return_type(ReturnNode::kContinuationTarget); |
| 9318 yield->AddNode(return_true); |
| 9319 |
| 9320 // If this expression is part of a try block, also append the code for |
| 9321 // restoring the saved try context that lives on the stack and possibly the |
| 9322 // saved try context of the outer try block. |
| 9323 LocalScope* try_scope; |
| 9324 int16_t try_index; |
| 9325 LocalScope* outer_try_scope; |
| 9326 int16_t outer_try_index; |
| 9327 CheckAsyncOpInTryBlock(&try_scope, &try_index, |
| 9328 &outer_try_scope, &outer_try_index); |
| 9329 if (try_scope != NULL) { |
| 9330 yield->AddNode( |
| 9331 AwaitTransformer::RestoreSavedTryContext(Z, |
| 9332 try_scope, |
| 9333 try_index)); |
| 9334 if (outer_try_scope != NULL) { |
| 9335 yield->AddNode( |
| 9336 AwaitTransformer::RestoreSavedTryContext(Z, |
| 9337 outer_try_scope, |
| 9338 outer_try_index)); |
| 9339 } |
| 9340 } else { |
| 9341 ASSERT(outer_try_scope == NULL); |
| 9342 } |
| 9343 } else { |
| 9344 // yield statement in async* function. |
| 9345 ASSERT(innermost_function().IsAsyncGenerator() || |
| 9346 innermost_function().IsAsyncGenClosure()); |
| 9347 |
| 9348 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller()); |
| 9349 ASSERT(controller_var != NULL); |
| 9350 // :controller.add[Stream](expr); |
| 9351 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos); |
| 9352 add_args->Add(expr); |
| 9353 AstNode* add_call = |
| 9354 new(Z) InstanceCallNode(yield_pos, |
| 9355 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var), |
| 9356 is_yield_each ? Symbols::AddStream() : Symbols::add(), |
| 9357 add_args); |
| 9358 |
| 9359 |
| 9360 // if (:controller.add[Stream](expr)) { |
| 9361 // return; |
| 9362 // } |
| 9363 // await_marker; |
| 9364 // continuation_return; |
| 9365 // restore saved_try_context |
| 9366 |
| 9367 SequenceNode* true_branch = |
| 9368 new(Z) SequenceNode(Scanner::kNoSourcePos, current_block_->scope); |
| 9369 AstNode* return_from_generator = new(Z) ReturnNode(yield_pos); |
| 9370 true_branch->Add(return_from_generator); |
| 9371 AddNodeForFinallyInlining(return_from_generator); |
| 9372 AstNode* if_is_cancelled = |
| 9373 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL); |
| 9374 yield->AddNode(if_is_cancelled); |
| 9375 |
| 9376 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); |
| 9377 await_marker->set_scope(current_block_->scope); |
| 9378 yield->AddNode(await_marker); |
| 9379 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos); |
| 9380 continuation_return->set_return_type(ReturnNode::kContinuationTarget); |
| 9381 yield->AddNode(continuation_return); |
| 9382 |
| 9383 // If this expression is part of a try block, also append the code for |
| 9384 // restoring the saved try context that lives on the stack and possibly the |
| 9385 // saved try context of the outer try block. |
| 9386 LocalScope* try_scope; |
| 9387 int16_t try_index; |
| 9388 LocalScope* outer_try_scope; |
| 9389 int16_t outer_try_index; |
| 9390 CheckAsyncOpInTryBlock(&try_scope, &try_index, |
| 9391 &outer_try_scope, &outer_try_index); |
| 9392 if (try_scope != NULL) { |
| 9393 yield->AddNode( |
| 9394 AwaitTransformer::RestoreSavedTryContext(Z, |
| 9395 try_scope, |
| 9396 try_index)); |
| 9397 if (outer_try_scope != NULL) { |
| 9398 yield->AddNode( |
| 9399 AwaitTransformer::RestoreSavedTryContext(Z, |
| 9400 outer_try_scope, |
| 9401 outer_try_index)); |
| 9402 } |
| 9403 } else { |
| 9404 ASSERT(outer_try_scope == NULL); |
| 9405 } |
| 9406 } |
| 9407 return yield; |
| 9408 } |
| 9409 |
| 9410 |
| 8863 AstNode* Parser::ParseStatement() { | 9411 AstNode* Parser::ParseStatement() { |
| 8864 TRACE_PARSER("ParseStatement"); | 9412 TRACE_PARSER("ParseStatement"); |
| 8865 AstNode* statement = NULL; | 9413 AstNode* statement = NULL; |
| 8866 intptr_t label_pos = 0; | 9414 intptr_t label_pos = 0; |
| 8867 String* label_name = NULL; | 9415 String* label_name = NULL; |
| 8868 if (IsIdentifier()) { | 9416 if (IsIdentifier()) { |
| 8869 if (LookaheadToken(1) == Token::kCOLON) { | 9417 if (LookaheadToken(1) == Token::kCOLON) { |
| 8870 // Statement starts with a label. | 9418 // Statement starts with a label. |
| 8871 label_name = CurrentLiteral(); | 9419 label_name = CurrentLiteral(); |
| 8872 label_pos = TokenPos(); | 9420 label_pos = TokenPos(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 8892 statement = ParseTryStatement(label_name); | 9440 statement = ParseTryStatement(label_name); |
| 8893 } else if (token == Token::kRETURN) { | 9441 } else if (token == Token::kRETURN) { |
| 8894 const intptr_t return_pos = TokenPos(); | 9442 const intptr_t return_pos = TokenPos(); |
| 8895 ConsumeToken(); | 9443 ConsumeToken(); |
| 8896 if (CurrentToken() != Token::kSEMICOLON) { | 9444 if (CurrentToken() != Token::kSEMICOLON) { |
| 8897 const intptr_t expr_pos = TokenPos(); | 9445 const intptr_t expr_pos = TokenPos(); |
| 8898 if (current_function().IsGenerativeConstructor() && | 9446 if (current_function().IsGenerativeConstructor() && |
| 8899 (current_block_->scope->function_level() == 0)) { | 9447 (current_block_->scope->function_level() == 0)) { |
| 8900 ReportError(expr_pos, | 9448 ReportError(expr_pos, |
| 8901 "return of a value is not allowed in constructors"); | 9449 "return of a value is not allowed in constructors"); |
| 8902 } else if (current_function().IsGenerator()) { | 9450 } else if (current_function().IsGeneratorClosure() && |
| 9451 (current_block_->scope->function_level() == 0)) { |
| 8903 ReportError(expr_pos, "generator functions may not return a value"); | 9452 ReportError(expr_pos, "generator functions may not return a value"); |
| 8904 } | 9453 } |
| 8905 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 9454 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 8906 statement = new(Z) ReturnNode(statement_pos, expr); | 9455 statement = new(Z) ReturnNode(statement_pos, expr); |
| 8907 } else { | 9456 } else { |
| 8908 if (current_function().IsSyncGenClosure() && | 9457 if (current_function().IsSyncGenClosure() && |
| 8909 (current_block_->scope->function_level() == 0)) { | 9458 (current_block_->scope->function_level() == 0)) { |
| 8910 // In a synchronous generator, return without an expression | 9459 // In a synchronous generator, return without an expression |
| 8911 // returns false, signaling that the iterator terminates and | 9460 // returns false, signaling that the iterator terminates and |
| 8912 // did not yield a value. | 9461 // did not yield a value. |
| 8913 statement = new(Z) ReturnNode(statement_pos, | 9462 statement = new(Z) ReturnNode(statement_pos, |
| 8914 new(Z) LiteralNode(return_pos, Bool::False())); | 9463 new(Z) LiteralNode(return_pos, Bool::False())); |
| 8915 } else { | 9464 } else { |
| 8916 statement = new(Z) ReturnNode(statement_pos); | 9465 statement = new(Z) ReturnNode(statement_pos); |
| 8917 } | 9466 } |
| 8918 } | 9467 } |
| 8919 AddNodeForFinallyInlining(statement); | 9468 AddNodeForFinallyInlining(statement); |
| 8920 ExpectSemicolon(); | 9469 ExpectSemicolon(); |
| 8921 } else if (IsYieldKeyword()) { | 9470 } else if (IsYieldKeyword()) { |
| 8922 bool is_yield_each = false; | 9471 statement = ParseYieldStatement(); |
| 8923 ConsumeToken(); | |
| 8924 ASSERT(innermost_function().IsGenerator() || | |
| 8925 innermost_function().IsSyncGenClosure()); | |
| 8926 if (CurrentToken() == Token::kMUL) { | |
| 8927 is_yield_each = true; | |
| 8928 ConsumeToken(); | |
| 8929 } | |
| 8930 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | |
| 8931 LocalVariable* iterator_param = | |
| 8932 LookupLocalScope(Symbols::IteratorParameter()); | |
| 8933 ASSERT(iterator_param != NULL); | |
| 8934 // Generate :iterator.current = expr; | |
| 8935 AstNode* iterator = | |
| 8936 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param); | |
| 8937 AstNode* store_current = | |
| 8938 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 8939 iterator, | |
| 8940 String::ZoneHandle(Symbols::Current().raw()), | |
| 8941 expr); | |
| 8942 LetNode* yield = new(Z) LetNode(statement_pos); | |
| 8943 yield->AddNode(store_current); | |
| 8944 if (is_yield_each) { | |
| 8945 // Generate :iterator.isYieldEach = true; | |
| 8946 AstNode* set_is_yield_each = | |
| 8947 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 8948 iterator, | |
| 8949 String::ZoneHandle(Symbols::IsYieldEach().raw()), | |
| 8950 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 8951 yield->AddNode(set_is_yield_each); | |
| 8952 } | |
| 8953 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); | |
| 8954 await_marker->set_scope(current_block_->scope); | |
| 8955 yield->AddNode(await_marker); | |
| 8956 // Return true to indicate that a value has been generated. | |
| 8957 ReturnNode* return_true = new(Z) ReturnNode(statement_pos, | |
| 8958 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 8959 return_true->set_return_type(ReturnNode::kContinuationTarget); | |
| 8960 yield->AddNode(return_true); | |
| 8961 | |
| 8962 // If this expression is part of a try block, also append the code for | |
| 8963 // restoring the saved try context that lives on the stack and possibly the | |
| 8964 // saved try context of the outer try block. | |
| 8965 LocalScope* try_scope; | |
| 8966 int16_t try_index; | |
| 8967 LocalScope* outer_try_scope; | |
| 8968 int16_t outer_try_index; | |
| 8969 CheckAsyncOpInTryBlock(&try_scope, &try_index, | |
| 8970 &outer_try_scope, &outer_try_index); | |
| 8971 if (try_scope != NULL) { | |
| 8972 yield->AddNode( | |
| 8973 AwaitTransformer::RestoreSavedTryContext(Z, | |
| 8974 try_scope, | |
| 8975 try_index)); | |
| 8976 if (outer_try_scope != NULL) { | |
| 8977 yield->AddNode( | |
| 8978 AwaitTransformer::RestoreSavedTryContext(Z, | |
| 8979 outer_try_scope, | |
| 8980 outer_try_index)); | |
| 8981 } | |
| 8982 } else { | |
| 8983 ASSERT(outer_try_scope == NULL); | |
| 8984 } | |
| 8985 | |
| 8986 statement = yield; | |
| 8987 ExpectSemicolon(); | 9472 ExpectSemicolon(); |
| 8988 } else if (token == Token::kIF) { | 9473 } else if (token == Token::kIF) { |
| 8989 statement = ParseIfStatement(label_name); | 9474 statement = ParseIfStatement(label_name); |
| 8990 } else if (token == Token::kASSERT) { | 9475 } else if (token == Token::kASSERT) { |
| 8991 statement = ParseAssertStatement(); | 9476 statement = ParseAssertStatement(); |
| 8992 ExpectSemicolon(); | 9477 ExpectSemicolon(); |
| 8993 } else if (IsVariableDeclaration()) { | 9478 } else if (IsVariableDeclaration()) { |
| 8994 statement = ParseVariableDeclarationList(); | 9479 statement = ParseVariableDeclarationList(); |
| 8995 ExpectSemicolon(); | 9480 ExpectSemicolon(); |
| 8996 } else if (IsFunctionDeclaration()) { | 9481 } else if (IsFunctionDeclaration()) { |
| (...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9837 } | 10322 } |
| 9838 | 10323 |
| 9839 | 10324 |
| 9840 AstNode* Parser::ParseUnaryExpr() { | 10325 AstNode* Parser::ParseUnaryExpr() { |
| 9841 TRACE_PARSER("ParseUnaryExpr"); | 10326 TRACE_PARSER("ParseUnaryExpr"); |
| 9842 AstNode* expr = NULL; | 10327 AstNode* expr = NULL; |
| 9843 const intptr_t op_pos = TokenPos(); | 10328 const intptr_t op_pos = TokenPos(); |
| 9844 if (IsAwaitKeyword()) { | 10329 if (IsAwaitKeyword()) { |
| 9845 TRACE_PARSER("ParseAwaitExpr"); | 10330 TRACE_PARSER("ParseAwaitExpr"); |
| 9846 if (!innermost_function().IsAsyncFunction() && | 10331 if (!innermost_function().IsAsyncFunction() && |
| 9847 !innermost_function().IsAsyncClosure()) { | 10332 !innermost_function().IsAsyncClosure() && |
| 9848 ReportError("await operator is only allowed in async function"); | 10333 !innermost_function().IsAsyncGenerator() && |
| 10334 !innermost_function().IsAsyncGenClosure()) { |
| 10335 ReportError("await operator is only allowed in an asynchronous function"); |
| 9849 } | 10336 } |
| 9850 ConsumeToken(); | 10337 ConsumeToken(); |
| 9851 parsed_function()->record_await(); | 10338 parsed_function()->record_await(); |
| 9852 | 10339 |
| 9853 LocalScope* try_scope; | 10340 LocalScope* try_scope; |
| 9854 int16_t try_index; | 10341 int16_t try_index; |
| 9855 LocalScope* outer_try_scope; | 10342 LocalScope* outer_try_scope; |
| 9856 int16_t outer_try_index; | 10343 int16_t outer_try_index; |
| 9857 CheckAsyncOpInTryBlock(&try_scope, &try_index, | 10344 CheckAsyncOpInTryBlock(&try_scope, &try_index, |
| 9858 &outer_try_scope, &outer_try_index); | 10345 &outer_try_scope, &outer_try_index); |
| (...skipping 1810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11669 // them here. | 12156 // them here. |
| 11670 // Map and List interfaces do not declare bounds on their type parameters, so | 12157 // Map and List interfaces do not declare bounds on their type parameters, so |
| 11671 // we will not see malbounded type arguments here. | 12158 // we will not see malbounded type arguments here. |
| 11672 AstNode* primary = NULL; | 12159 AstNode* primary = NULL; |
| 11673 if ((CurrentToken() == Token::kLBRACK) || | 12160 if ((CurrentToken() == Token::kLBRACK) || |
| 11674 (CurrentToken() == Token::kINDEX)) { | 12161 (CurrentToken() == Token::kINDEX)) { |
| 11675 primary = ParseListLiteral(type_pos, is_const, type_arguments); | 12162 primary = ParseListLiteral(type_pos, is_const, type_arguments); |
| 11676 } else if (CurrentToken() == Token::kLBRACE) { | 12163 } else if (CurrentToken() == Token::kLBRACE) { |
| 11677 primary = ParseMapLiteral(type_pos, is_const, type_arguments); | 12164 primary = ParseMapLiteral(type_pos, is_const, type_arguments); |
| 11678 } else { | 12165 } else { |
| 11679 ReportError("unexpected token %s", Token::Str(CurrentToken())); | 12166 UnexpectedToken(); |
| 11680 } | 12167 } |
| 11681 return primary; | 12168 return primary; |
| 11682 } | 12169 } |
| 11683 | 12170 |
| 11684 | 12171 |
| 11685 AstNode* Parser::ParseSymbolLiteral() { | 12172 AstNode* Parser::ParseSymbolLiteral() { |
| 11686 ASSERT(CurrentToken() == Token::kHASH); | 12173 ASSERT(CurrentToken() == Token::kHASH); |
| 11687 ConsumeToken(); | 12174 ConsumeToken(); |
| 11688 intptr_t symbol_pos = TokenPos(); | 12175 intptr_t symbol_pos = TokenPos(); |
| 11689 String& symbol = String::Handle(Z); | 12176 String& symbol = String::Handle(Z); |
| (...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12688 void Parser::SkipQualIdent() { | 13175 void Parser::SkipQualIdent() { |
| 12689 ASSERT(IsIdentifier()); | 13176 ASSERT(IsIdentifier()); |
| 12690 ConsumeToken(); | 13177 ConsumeToken(); |
| 12691 if (CurrentToken() == Token::kPERIOD) { | 13178 if (CurrentToken() == Token::kPERIOD) { |
| 12692 ConsumeToken(); // Consume the kPERIOD token. | 13179 ConsumeToken(); // Consume the kPERIOD token. |
| 12693 ExpectIdentifier("identifier expected after '.'"); | 13180 ExpectIdentifier("identifier expected after '.'"); |
| 12694 } | 13181 } |
| 12695 } | 13182 } |
| 12696 | 13183 |
| 12697 } // namespace dart | 13184 } // namespace dart |
| OLD | NEW |