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 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()); |
| 6235 // Add implicit closure parameter if not yet present. | 6421 // Add implicit closure parameter if not yet present. |
| 6236 if (params->parameters->length() == 0) { | 6422 if (params->parameters->length() == 0) { |
|
Ivan Posva
2015/03/03 01:05:52
We should assert that params->parameters->length()
hausner
2015/03/03 17:51:28
Done.
| |
| 6237 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); | 6423 params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type); |
| 6238 } | 6424 } |
| 6239 ParamDesc result_param; | 6425 ParamDesc result_param; |
| 6240 result_param.name = &Symbols::AsyncOperationParam(); | 6426 result_param.name = &Symbols::AsyncOperationParam(); |
| 6241 result_param.default_value = &Object::null_instance(); | 6427 result_param.default_value = &Object::null_instance(); |
| 6242 result_param.type = &dynamic_type; | 6428 result_param.type = &dynamic_type; |
| 6243 params->parameters->Add(result_param); | 6429 params->parameters->Add(result_param); |
| 6244 ParamDesc error_param; | 6430 ParamDesc error_param; |
| 6245 error_param.name = &Symbols::AsyncOperationErrorParam(); | 6431 error_param.name = &Symbols::AsyncOperationErrorParam(); |
| 6246 error_param.default_value = &Object::null_instance(); | 6432 error_param.default_value = &Object::null_instance(); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6349 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); | 6535 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); |
| 6350 async_op_var->set_is_captured(); | 6536 async_op_var->set_is_captured(); |
| 6351 LocalVariable* async_completer = new(Z) LocalVariable( | 6537 LocalVariable* async_completer = new(Z) LocalVariable( |
| 6352 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); | 6538 Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type); |
| 6353 current_block_->scope->AddVariable(async_completer); | 6539 current_block_->scope->AddVariable(async_completer); |
| 6354 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); | 6540 current_block_->scope->CaptureVariable(Symbols::AsyncCompleter()); |
| 6355 async_completer->set_is_captured(); | 6541 async_completer->set_is_captured(); |
| 6356 } | 6542 } |
| 6357 | 6543 |
| 6358 | 6544 |
| 6545 void Parser::AddAsyncGeneratorVariables() { | |
| 6546 // Add to current block's scope: | |
| 6547 // var :controller; | |
|
Ivan Posva
2015/03/03 01:05:52
// var :async_op;?
hausner
2015/03/03 17:51:28
Done.
| |
| 6548 // This variable is used by the nested async generator closure to | |
| 6549 // store the StreamController object to which the yielded expressions | |
| 6550 // are added. | |
| 6551 const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType()); | |
| 6552 LocalVariable* controller_var = new(Z) LocalVariable( | |
| 6553 Scanner::kNoSourcePos, Symbols::Controller(), dynamic_type); | |
| 6554 current_block_->scope->AddVariable(controller_var); | |
| 6555 current_block_->scope->CaptureVariable(Symbols::Controller()); | |
| 6556 controller_var->set_is_captured(); | |
| 6557 | |
| 6558 LocalVariable* async_op_var = new(Z) LocalVariable( | |
| 6559 Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type); | |
| 6560 current_block_->scope->AddVariable(async_op_var); | |
| 6561 current_block_->scope->CaptureVariable(Symbols::AsyncOperation()); | |
| 6562 async_op_var->set_is_captured(); | |
| 6563 } | |
| 6564 | |
| 6565 | |
| 6566 RawFunction* Parser::OpenAsyncGeneratorFunction(intptr_t async_func_pos) { | |
| 6567 TRACE_PARSER("OpenAsyncGeneratorFunction"); | |
| 6568 AddContinuationVariables(); | |
| 6569 AddAsyncGeneratorVariables(); | |
| 6570 | |
| 6571 Function& closure = Function::Handle(Z); | |
| 6572 bool is_new_closure = false; | |
| 6573 | |
| 6574 // Check whether a function for the asynchronous function body of | |
| 6575 // this async generator has already been created by a previous | |
| 6576 // compilation of this function. | |
| 6577 const Function& found_func = Function::Handle( | |
| 6578 Z, current_class().LookupClosureFunction(async_func_pos)); | |
| 6579 if (!found_func.IsNull() && | |
| 6580 (found_func.token_pos() == async_func_pos) && | |
| 6581 (found_func.script() == innermost_function().script()) && | |
| 6582 (found_func.parent_function() == innermost_function().raw())) { | |
| 6583 ASSERT(found_func.IsAsyncGenClosure()); | |
| 6584 closure = found_func.raw(); | |
| 6585 } else { | |
| 6586 // Create the closure containing the body of this async generator function. | |
| 6587 const String& async_generator_name = | |
| 6588 String::Handle(Z, innermost_function().name()); | |
| 6589 String& closure_name = String::Handle(Z, | |
| 6590 String::NewFormatted("<%s_async_gen_body>", | |
| 6591 async_generator_name.ToCString())); | |
| 6592 closure = Function::NewClosureFunction( | |
| 6593 String::Handle(Z, Symbols::New(closure_name)), | |
| 6594 innermost_function(), | |
| 6595 async_func_pos); | |
| 6596 closure.set_is_generated_body(true); | |
| 6597 closure.set_result_type(AbstractType::Handle(Type::DynamicType())); | |
| 6598 is_new_closure = true; | |
| 6599 } | |
| 6600 | |
| 6601 ParamList closure_params; | |
| 6602 AddAsyncGenClosureParameters(&closure_params); | |
| 6603 | |
| 6604 if (is_new_closure) { | |
| 6605 // Add the parameters to the newly created closure. | |
| 6606 AddFormalParamsToFunction(&closure_params, closure); | |
| 6607 | |
| 6608 // Create and set the signature class of the closure. | |
| 6609 const String& sig = String::Handle(Z, closure.Signature()); | |
| 6610 Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig)); | |
| 6611 if (sig_cls.IsNull()) { | |
| 6612 sig_cls = | |
| 6613 Class::NewSignatureClass(sig, closure, script_, closure.token_pos()); | |
| 6614 library_.AddClass(sig_cls); | |
| 6615 } | |
| 6616 closure.set_signature_class(sig_cls); | |
| 6617 const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType()); | |
| 6618 if (!sig_type.IsFinalized()) { | |
| 6619 ClassFinalizer::FinalizeType( | |
| 6620 sig_cls, sig_type, ClassFinalizer::kCanonicalize); | |
| 6621 } | |
| 6622 ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved()); | |
| 6623 ASSERT(closure.NumParameters() == closure_params.parameters->length()); | |
| 6624 } | |
| 6625 | |
| 6626 OpenFunctionBlock(closure); | |
| 6627 AddFormalParamsToScope(&closure_params, current_block_->scope); | |
| 6628 OpenBlock(); | |
| 6629 async_temp_scope_ = current_block_->scope; | |
| 6630 return closure.raw(); | |
| 6631 } | |
| 6632 | |
| 6633 | |
| 6634 // Generate the Ast nodes for the implicit code of the async* function. | |
| 6635 // | |
| 6636 // f(...) async* { | |
| 6637 // var :controller; | |
| 6638 // var :await_jump_var = -1; | |
| 6639 // var :await_context_var; | |
|
Ivan Posva
2015/03/03 01:05:52
// var :async_op;
hausner
2015/03/03 17:51:28
Done.
| |
| 6640 // f_async_body() { | |
| 6641 // ... source code of f ... | |
| 6642 // } | |
| 6643 // :controller = new _AsyncStarStreamController(f_async_body); | |
| 6644 // return :controller.stream; | |
| 6645 // } | |
| 6646 SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure, | |
| 6647 SequenceNode* closure_body) { | |
| 6648 TRACE_PARSER("CloseAsyncGeneratorFunction"); | |
| 6649 ASSERT(!closure.IsNull()); | |
| 6650 ASSERT(closure_body != NULL); | |
| 6651 | |
| 6652 // The block for the async closure body has already been closed. Close the | |
| 6653 // corresponding function block. | |
| 6654 CloseBlock(); | |
| 6655 | |
| 6656 // Make sure the implicit variables of the async generator function | |
| 6657 // are captured. | |
| 6658 closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | |
| 6659 closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); | |
| 6660 closure_body->scope()->LookupVariable(Symbols::Controller(), false); | |
|
Ivan Posva
2015/03/03 01:05:52
Force capture :async_op?
hausner
2015/03/03 17:51:28
Done.
| |
| 6661 | |
| 6662 const Class& controller_class = Class::Handle(Z, | |
| 6663 Library::LookupCoreClass(Symbols::_AsyncStarStreamController())); | |
| 6664 ASSERT(!controller_class.IsNull()); | |
| 6665 const Function& controller_constructor = Function::ZoneHandle(Z, | |
| 6666 controller_class.LookupConstructorAllowPrivate( | |
| 6667 Symbols::_AsyncStarStreamControllerConstructor())); | |
| 6668 | |
| 6669 // :await_jump_var = -1; | |
| 6670 LocalVariable* jump_var = | |
| 6671 current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false); | |
| 6672 LiteralNode* init_value = | |
| 6673 new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1))); | |
| 6674 current_block_->statements->Add( | |
| 6675 new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value)); | |
| 6676 | |
| 6677 // Add to AST: | |
| 6678 // :async_op = <closure>; (containing the original body) | |
| 6679 LocalVariable* async_op_var = | |
| 6680 current_block_->scope->LookupVariable(Symbols::AsyncOperation(), false); | |
| 6681 ClosureNode* cn = new(Z) ClosureNode( | |
| 6682 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); | |
| 6683 StoreLocalNode* store_async_op = new (Z) StoreLocalNode( | |
| 6684 Scanner::kNoSourcePos, | |
| 6685 async_op_var, | |
| 6686 cn); | |
| 6687 current_block_->statements->Add(store_async_op); | |
| 6688 | |
| 6689 // :controller = new _AsyncStarStreamController(body_closure); | |
| 6690 ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos); | |
| 6691 ClosureNode* closure_obj = new(Z) ClosureNode( | |
| 6692 Scanner::kNoSourcePos, closure, NULL, closure_body->scope()); | |
| 6693 arguments->Add(closure_obj); | |
| 6694 ConstructorCallNode* controller_constructor_call = | |
| 6695 new(Z) ConstructorCallNode(Scanner::kNoSourcePos, | |
| 6696 TypeArguments::ZoneHandle(Z), | |
| 6697 controller_constructor, | |
| 6698 arguments); | |
| 6699 LocalVariable* controller_var = | |
| 6700 current_block_->scope->LookupVariable(Symbols::Controller(), false); | |
| 6701 StoreLocalNode* store_controller = | |
| 6702 new(Z) StoreLocalNode(Scanner::kNoSourcePos, | |
| 6703 controller_var, | |
| 6704 controller_constructor_call); | |
| 6705 current_block_->statements->Add(store_controller); | |
| 6706 | |
| 6707 // return :controller.stream; | |
| 6708 ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos, | |
| 6709 new(Z) InstanceGetterNode(Scanner::kNoSourcePos, | |
| 6710 new(Z) LoadLocalNode(Scanner::kNoSourcePos, | |
| 6711 controller_var), | |
| 6712 Symbols::Stream())); | |
| 6713 current_block_->statements->Add(return_node); | |
| 6714 return CloseBlock(); | |
| 6715 } | |
| 6716 | |
| 6717 | |
| 6718 void Parser::OpenAsyncGeneratorClosure() { | |
| 6719 async_temp_scope_ = current_block_->scope; | |
| 6720 OpenAsyncTryBlock(); | |
| 6721 } | |
| 6722 | |
| 6723 | |
| 6724 SequenceNode* Parser::CloseAsyncGeneratorClosure(SequenceNode* body) { | |
| 6725 // TODO(hausner): Is the temporary expression necessary? | |
|
Ivan Posva
2015/03/03 01:05:52
Remove TODO
hausner
2015/03/03 17:51:28
Done.
| |
| 6726 // We need a temporary expression to store intermediate return values. | |
| 6727 parsed_function()->EnsureExpressionTemp(); | |
| 6728 | |
| 6729 SequenceNode* new_body = CloseAsyncGeneratorTryBlock(body); | |
| 6730 ASSERT(new_body != NULL); | |
| 6731 ASSERT(new_body->scope() != NULL); | |
| 6732 | |
| 6733 // Implicitly mark those variables below as captured. We currently mark all | |
| 6734 // variables of all scopes as captured, but as soon as we do something | |
| 6735 // smarter we rely on these internal variables to be available. | |
| 6736 new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false); | |
| 6737 new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false); | |
| 6738 new_body->scope()->LookupVariable(Symbols::Controller(), false); | |
| 6739 new_body->scope()->LookupVariable(Symbols::AsyncOperationParam(), false); | |
| 6740 new_body->scope()->LookupVariable(Symbols::AsyncOperationErrorParam(), false); | |
| 6741 new_body->scope()->LookupVariable( | |
| 6742 Symbols::AsyncOperationStackTraceParam(), false); | |
| 6743 new_body->scope()->RecursivelyCaptureAllVariables(); | |
| 6744 return new_body; | |
| 6745 } | |
| 6746 | |
| 6747 | |
| 6359 SequenceNode* Parser::CloseBlock() { | 6748 SequenceNode* Parser::CloseBlock() { |
| 6360 SequenceNode* statements = current_block_->statements; | 6749 SequenceNode* statements = current_block_->statements; |
| 6361 if (current_block_->scope != NULL) { | 6750 if (current_block_->scope != NULL) { |
| 6362 // Record the begin and end token index of the scope. | 6751 // Record the begin and end token index of the scope. |
| 6363 ASSERT(statements != NULL); | 6752 ASSERT(statements != NULL); |
| 6364 current_block_->scope->set_begin_token_pos(statements->token_pos()); | 6753 current_block_->scope->set_begin_token_pos(statements->token_pos()); |
| 6365 current_block_->scope->set_end_token_pos(TokenPos()); | 6754 current_block_->scope->set_end_token_pos(TokenPos()); |
| 6366 } | 6755 } |
| 6367 current_block_ = current_block_->parent; | 6756 current_block_ = current_block_->parent; |
| 6368 return statements; | 6757 return statements; |
| (...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7794 *outer_try_index = try_blocks_list_->outer_try_block()->try_index(); | 8183 *outer_try_index = try_blocks_list_->outer_try_block()->try_index(); |
| 7795 } | 8184 } |
| 7796 } | 8185 } |
| 7797 } | 8186 } |
| 7798 } | 8187 } |
| 7799 // An async or async* has an implicitly created try-catch around the | 8188 // 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 | 8189 // function body, so the await or yield inside the async closure should always |
| 7801 // be created with a try scope. | 8190 // be created with a try scope. |
| 7802 ASSERT((*try_scope != NULL) || | 8191 ASSERT((*try_scope != NULL) || |
| 7803 innermost_function().IsAsyncFunction() || | 8192 innermost_function().IsAsyncFunction() || |
| 8193 innermost_function().IsAsyncGenerator() || | |
| 7804 innermost_function().IsSyncGenClosure() || | 8194 innermost_function().IsSyncGenClosure() || |
| 7805 innermost_function().IsSyncGenerator()); | 8195 innermost_function().IsSyncGenerator()); |
| 7806 } | 8196 } |
| 7807 | 8197 |
| 7808 | 8198 |
| 7809 AstNode* Parser::ParseAwaitForStatement(String* label_name) { | 8199 AstNode* Parser::ParseAwaitForStatement(String* label_name) { |
| 7810 TRACE_PARSER("ParseAwaitForStatement"); | 8200 TRACE_PARSER("ParseAwaitForStatement"); |
| 7811 ASSERT(IsAwaitKeyword()); | 8201 ASSERT(IsAwaitKeyword()); |
| 7812 const intptr_t await_for_pos = TokenPos(); | 8202 const intptr_t await_for_pos = TokenPos(); |
| 7813 ConsumeToken(); // await. | 8203 ConsumeToken(); // await. |
| 7814 ASSERT(CurrentToken() == Token::kFOR); | 8204 ASSERT(CurrentToken() == Token::kFOR); |
| 7815 ConsumeToken(); // for. | 8205 ConsumeToken(); // for. |
| 7816 ExpectToken(Token::kLPAREN); | 8206 ExpectToken(Token::kLPAREN); |
| 7817 | 8207 |
| 7818 if (!innermost_function().IsAsyncFunction() && | 8208 if (!innermost_function().IsAsyncFunction() && |
| 7819 !innermost_function().IsAsyncClosure()) { | 8209 !innermost_function().IsAsyncClosure() && |
| 8210 !innermost_function().IsAsyncGenerator() && | |
| 8211 !innermost_function().IsAsyncGenClosure()) { | |
| 7820 ReportError(await_for_pos, | 8212 ReportError(await_for_pos, |
| 7821 "await for loop is only allowed in async function"); | 8213 "await for loop is only allowed in an asynchronous function"); |
| 7822 } | 8214 } |
| 7823 | 8215 |
| 7824 // Parse loop variable. | 8216 // Parse loop variable. |
| 7825 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); | 8217 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); |
| 7826 if (CurrentToken() == Token::kCONST) { | 8218 if (CurrentToken() == Token::kCONST) { |
| 7827 ReportError("Loop variable cannot be 'const'"); | 8219 ReportError("Loop variable cannot be 'const'"); |
| 7828 } | 8220 } |
| 7829 bool new_loop_var = false; | 8221 bool new_loop_var = false; |
| 7830 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); | 8222 AbstractType& loop_var_type = AbstractType::ZoneHandle(Z); |
| 7831 if (LookaheadToken(1) != Token::kIN) { | 8223 if (LookaheadToken(1) != Token::kIN) { |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8256 } | 8648 } |
| 8257 } | 8649 } |
| 8258 | 8650 |
| 8259 | 8651 |
| 8260 // Populate current scope of the try block with the saved exception and saved | 8652 // Populate current scope of the try block with the saved exception and saved |
| 8261 // stack trace. | 8653 // stack trace. |
| 8262 void Parser::SetupSavedExceptionAndStacktrace() { | 8654 void Parser::SetupSavedExceptionAndStacktrace() { |
| 8263 ASSERT(innermost_function().IsAsyncClosure() || | 8655 ASSERT(innermost_function().IsAsyncClosure() || |
| 8264 innermost_function().IsAsyncFunction() || | 8656 innermost_function().IsAsyncFunction() || |
| 8265 innermost_function().IsSyncGenClosure() || | 8657 innermost_function().IsSyncGenClosure() || |
| 8266 innermost_function().IsSyncGenerator()); | 8658 innermost_function().IsSyncGenerator() || |
| 8659 innermost_function().IsAsyncGenerator() || | |
| 8660 innermost_function().IsAsyncGenClosure()); | |
| 8267 // Add :saved_exception_var and :saved_stack_trace_var to current scope. | 8661 // Add :saved_exception_var and :saved_stack_trace_var to current scope. |
| 8268 // They will automatically get captured. | 8662 // They will automatically get captured. |
| 8269 // Parallel try statements share the same set of variables. | 8663 // Parallel try statements share the same set of variables. |
| 8270 LocalVariable* saved_exception_var = | 8664 LocalVariable* saved_exception_var = |
| 8271 current_block_->scope->LocalLookupVariable(Symbols::SavedExceptionVar()); | 8665 current_block_->scope->LocalLookupVariable(Symbols::SavedExceptionVar()); |
| 8272 if (saved_exception_var == NULL) { | 8666 if (saved_exception_var == NULL) { |
| 8273 saved_exception_var = new (Z) LocalVariable( | 8667 saved_exception_var = new (Z) LocalVariable( |
| 8274 Scanner::kNoSourcePos, | 8668 Scanner::kNoSourcePos, |
| 8275 Symbols::SavedExceptionVar(), | 8669 Symbols::SavedExceptionVar(), |
| 8276 Type::ZoneHandle(Z, Type::DynamicType())); | 8670 Type::ZoneHandle(Z, Type::DynamicType())); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 8290 } | 8684 } |
| 8291 | 8685 |
| 8292 | 8686 |
| 8293 // Generate code to load the exception object (:exception_var) into | 8687 // Generate code to load the exception object (:exception_var) into |
| 8294 // the saved exception variable (:saved_exception_var) used to rethrow. | 8688 // the saved exception variable (:saved_exception_var) used to rethrow. |
| 8295 void Parser::SaveExceptionAndStacktrace(LocalVariable* exception_var, | 8689 void Parser::SaveExceptionAndStacktrace(LocalVariable* exception_var, |
| 8296 LocalVariable* stack_trace_var) { | 8690 LocalVariable* stack_trace_var) { |
| 8297 ASSERT(innermost_function().IsAsyncClosure() || | 8691 ASSERT(innermost_function().IsAsyncClosure() || |
| 8298 innermost_function().IsAsyncFunction() || | 8692 innermost_function().IsAsyncFunction() || |
| 8299 innermost_function().IsSyncGenClosure() || | 8693 innermost_function().IsSyncGenClosure() || |
| 8300 innermost_function().IsSyncGenerator()); | 8694 innermost_function().IsSyncGenerator() || |
| 8695 innermost_function().IsAsyncGenClosure() || | |
| 8696 innermost_function().IsAsyncGenerator()); | |
| 8301 LocalVariable* saved_exception_var = current_block_->scope->LookupVariable( | 8697 LocalVariable* saved_exception_var = current_block_->scope->LookupVariable( |
| 8302 Symbols::SavedExceptionVar(), false); | 8698 Symbols::SavedExceptionVar(), false); |
| 8303 ASSERT(saved_exception_var != NULL); | 8699 ASSERT(saved_exception_var != NULL); |
| 8304 ASSERT(exception_var != NULL); | 8700 ASSERT(exception_var != NULL); |
| 8305 current_block_->statements->Add(new(Z) StoreLocalNode( | 8701 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 8306 Scanner::kNoSourcePos, | 8702 Scanner::kNoSourcePos, |
| 8307 saved_exception_var, | 8703 saved_exception_var, |
| 8308 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); | 8704 new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var))); |
| 8309 | 8705 |
| 8310 // Generate code to load the stack trace object (:stack_trace_var) into | 8706 // Generate code to load the stack trace object (:stack_trace_var) into |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 8324 TRACE_PARSER("ParseFinallyBlock"); | 8720 TRACE_PARSER("ParseFinallyBlock"); |
| 8325 OpenBlock(); | 8721 OpenBlock(); |
| 8326 ExpectToken(Token::kLBRACE); | 8722 ExpectToken(Token::kLBRACE); |
| 8327 | 8723 |
| 8328 // In case of async closures we need to restore the saved try index of an | 8724 // 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 | 8725 // outer try block (if it exists). The current try block has already been |
| 8330 // removed from the stack of try blocks. | 8726 // removed from the stack of try blocks. |
| 8331 if ((innermost_function().IsAsyncClosure() || | 8727 if ((innermost_function().IsAsyncClosure() || |
| 8332 innermost_function().IsAsyncFunction() || | 8728 innermost_function().IsAsyncFunction() || |
| 8333 innermost_function().IsSyncGenClosure() || | 8729 innermost_function().IsSyncGenClosure() || |
| 8334 innermost_function().IsSyncGenerator()) && | 8730 innermost_function().IsSyncGenerator() || |
| 8731 innermost_function().IsAsyncGenerator() || | |
| 8732 innermost_function().IsAsyncGenClosure()) && | |
| 8335 (try_blocks_list_ != NULL)) { | 8733 (try_blocks_list_ != NULL)) { |
| 8336 LocalScope* scope = try_blocks_list_->try_block()->scope; | 8734 LocalScope* scope = try_blocks_list_->try_block()->scope; |
| 8337 if (scope->function_level() == current_block_->scope->function_level()) { | 8735 if (scope->function_level() == current_block_->scope->function_level()) { |
| 8338 current_block_->statements->Add( | 8736 current_block_->statements->Add( |
| 8339 AwaitTransformer::RestoreSavedTryContext( | 8737 AwaitTransformer::RestoreSavedTryContext( |
| 8340 Z, scope->parent(), try_blocks_list_->try_index())); | 8738 Z, scope->parent(), try_blocks_list_->try_index())); |
| 8341 } | 8739 } |
| 8342 } | 8740 } |
| 8343 | 8741 |
| 8344 ParseStatementSequence(); | 8742 ParseStatementSequence(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8433 } else { | 8831 } else { |
| 8434 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); | 8832 exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 8435 } | 8833 } |
| 8436 if (CurrentToken() == Token::kCATCH) { | 8834 if (CurrentToken() == Token::kCATCH) { |
| 8437 ConsumeToken(); // Consume the 'catch'. | 8835 ConsumeToken(); // Consume the 'catch'. |
| 8438 ExpectToken(Token::kLPAREN); | 8836 ExpectToken(Token::kLPAREN); |
| 8439 exception_param.token_pos = TokenPos(); | 8837 exception_param.token_pos = TokenPos(); |
| 8440 exception_param.name = ExpectIdentifier("identifier expected"); | 8838 exception_param.name = ExpectIdentifier("identifier expected"); |
| 8441 if (CurrentToken() == Token::kCOMMA) { | 8839 if (CurrentToken() == Token::kCOMMA) { |
| 8442 ConsumeToken(); | 8840 ConsumeToken(); |
| 8443 // TODO(hausner): Make implicit type be StackTrace, not dynamic. | |
| 8444 stack_trace_param.type = | 8841 stack_trace_param.type = |
| 8445 &AbstractType::ZoneHandle(Z, Type::DynamicType()); | 8842 &AbstractType::ZoneHandle(Z, Type::DynamicType()); |
| 8446 stack_trace_param.token_pos = TokenPos(); | 8843 stack_trace_param.token_pos = TokenPos(); |
| 8447 stack_trace_param.name = ExpectIdentifier("identifier expected"); | 8844 stack_trace_param.name = ExpectIdentifier("identifier expected"); |
| 8448 } | 8845 } |
| 8449 ExpectToken(Token::kRPAREN); | 8846 ExpectToken(Token::kRPAREN); |
| 8450 } | 8847 } |
| 8451 | 8848 |
| 8452 // Create a block containing the catch clause parameters and the | 8849 // Create a block containing the catch clause parameters and the |
| 8453 // following code: | 8850 // following code: |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 8472 // A stack trace variable is specified in this block, so generate code | 8869 // 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 | 8870 // to load the stack trace object (:stack_trace_var) into the stack |
| 8474 // trace variable specified in this block. | 8871 // trace variable specified in this block. |
| 8475 *needs_stack_trace = true; | 8872 *needs_stack_trace = true; |
| 8476 ASSERT(stack_trace_var != NULL); | 8873 ASSERT(stack_trace_var != NULL); |
| 8477 current_block_->statements->Add(new(Z) StoreLocalNode( | 8874 current_block_->statements->Add(new(Z) StoreLocalNode( |
| 8478 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( | 8875 catch_pos, stack_trace_param.var, new(Z) LoadLocalNode( |
| 8479 catch_pos, stack_trace_var))); | 8876 catch_pos, stack_trace_var))); |
| 8480 } | 8877 } |
| 8481 | 8878 |
| 8482 // Add nested block with user-defined code. This blocks allows | 8879 // Add nested block with user-defined code. This block allows |
| 8483 // declarations in the body to shadow the catch parameters. | 8880 // declarations in the body to shadow the catch parameters. |
| 8484 CheckToken(Token::kLBRACE); | 8881 CheckToken(Token::kLBRACE); |
| 8485 | 8882 |
| 8486 // In case of async closures we need to restore the saved try index of an | 8883 // In case of async closures we need to restore the saved try index of an |
| 8487 // outer try block (if it exists). | 8884 // outer try block (if it exists). |
| 8488 ASSERT(try_blocks_list_ != NULL); | 8885 ASSERT(try_blocks_list_ != NULL); |
| 8489 if (innermost_function().IsAsyncClosure() || | 8886 if (innermost_function().IsAsyncClosure() || |
| 8490 innermost_function().IsAsyncFunction() || | 8887 innermost_function().IsAsyncFunction() || |
| 8491 innermost_function().IsSyncGenClosure() || | 8888 innermost_function().IsSyncGenClosure() || |
| 8492 innermost_function().IsSyncGenerator()) { | 8889 innermost_function().IsSyncGenerator() || |
| 8890 innermost_function().IsAsyncGenerator() || | |
| 8891 innermost_function().IsAsyncGenClosure()) { | |
| 8493 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); | 8892 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); |
| 8494 if (try_block != NULL) { | 8893 if (try_block != NULL) { |
| 8495 LocalScope* scope = try_block->try_block()->scope; | 8894 LocalScope* scope = try_block->try_block()->scope; |
| 8496 if (scope->function_level() == | 8895 if (scope->function_level() == |
| 8497 current_block_->scope->function_level()) { | 8896 current_block_->scope->function_level()) { |
| 8498 current_block_->statements->Add( | 8897 current_block_->statements->Add( |
| 8499 AwaitTransformer::RestoreSavedTryContext( | 8898 AwaitTransformer::RestoreSavedTryContext( |
| 8500 Z, scope->parent(), try_block->try_index())); | 8899 Z, scope->parent(), try_block->try_index())); |
| 8501 } | 8900 } |
| 8502 } | 8901 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8595 current_block_->statements->Add(new(Z) IfNode( | 8994 current_block_->statements->Add(new(Z) IfNode( |
| 8596 type_test->token_pos(), type_test, catch_block, current)); | 8995 type_test->token_pos(), type_test, catch_block, current)); |
| 8597 current = CloseBlock(); | 8996 current = CloseBlock(); |
| 8598 } | 8997 } |
| 8599 // Restore :saved_try_context_var before executing the catch clauses. | 8998 // Restore :saved_try_context_var before executing the catch clauses. |
| 8600 if (current != NULL) { | 8999 if (current != NULL) { |
| 8601 ASSERT(try_blocks_list_ != NULL); | 9000 ASSERT(try_blocks_list_ != NULL); |
| 8602 if (innermost_function().IsAsyncClosure() || | 9001 if (innermost_function().IsAsyncClosure() || |
| 8603 innermost_function().IsAsyncFunction() || | 9002 innermost_function().IsAsyncFunction() || |
| 8604 innermost_function().IsSyncGenClosure() || | 9003 innermost_function().IsSyncGenClosure() || |
| 8605 innermost_function().IsSyncGenerator()) { | 9004 innermost_function().IsSyncGenerator() || |
| 9005 innermost_function().IsAsyncGenerator() || | |
| 9006 innermost_function().IsAsyncGenClosure()) { | |
| 8606 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); | 9007 const TryBlocks* try_block = try_blocks_list_->outer_try_block(); |
| 8607 if (try_block != NULL) { | 9008 if (try_block != NULL) { |
| 8608 LocalScope* scope = try_block->try_block()->scope; | 9009 LocalScope* scope = try_block->try_block()->scope; |
| 8609 if (scope->function_level() == | 9010 if (scope->function_level() == |
| 8610 current_block_->scope->function_level()) { | 9011 current_block_->scope->function_level()) { |
| 8611 SequenceNode* restore_code = new(Z) SequenceNode(handler_pos, NULL); | 9012 SequenceNode* restore_code = new(Z) SequenceNode(handler_pos, NULL); |
| 8612 restore_code->Add( | 9013 restore_code->Add( |
| 8613 AwaitTransformer::RestoreSavedTryContext( | 9014 AwaitTransformer::RestoreSavedTryContext( |
| 8614 Z, scope->parent(), try_block->try_index())); | 9015 Z, scope->parent(), try_block->try_index())); |
| 8615 restore_code->Add(current); | 9016 restore_code->Add(current); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8687 stack_trace_var = new(Z) LocalVariable( | 9088 stack_trace_var = new(Z) LocalVariable( |
| 8688 TokenPos(), | 9089 TokenPos(), |
| 8689 Symbols::StackTraceVar(), | 9090 Symbols::StackTraceVar(), |
| 8690 Type::ZoneHandle(Z, Type::DynamicType())); | 9091 Type::ZoneHandle(Z, Type::DynamicType())); |
| 8691 current_block_->scope->AddVariable(stack_trace_var); | 9092 current_block_->scope->AddVariable(stack_trace_var); |
| 8692 } | 9093 } |
| 8693 | 9094 |
| 8694 if (innermost_function().IsAsyncClosure() || | 9095 if (innermost_function().IsAsyncClosure() || |
| 8695 innermost_function().IsAsyncFunction() || | 9096 innermost_function().IsAsyncFunction() || |
| 8696 innermost_function().IsSyncGenClosure() || | 9097 innermost_function().IsSyncGenClosure() || |
| 8697 innermost_function().IsSyncGenerator()) { | 9098 innermost_function().IsSyncGenerator() || |
| 9099 innermost_function().IsAsyncGenClosure() || | |
| 9100 innermost_function().IsAsyncGenerator()) { | |
| 8698 SetupSavedExceptionAndStacktrace(); | 9101 SetupSavedExceptionAndStacktrace(); |
| 8699 } | 9102 } |
| 8700 | 9103 |
| 8701 const intptr_t try_pos = TokenPos(); | 9104 const intptr_t try_pos = TokenPos(); |
| 8702 ConsumeToken(); // Consume the 'try'. | 9105 ConsumeToken(); // Consume the 'try'. |
| 8703 | 9106 |
| 8704 SourceLabel* try_label = NULL; | 9107 SourceLabel* try_label = NULL; |
| 8705 if (label_name != NULL) { | 9108 if (label_name != NULL) { |
| 8706 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); | 9109 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); |
| 8707 OpenBlock(); | 9110 OpenBlock(); |
| 8708 current_block_->scope->AddLabel(try_label); | 9111 current_block_->scope->AddLabel(try_label); |
| 8709 } | 9112 } |
| 8710 | 9113 |
| 8711 // Now parse the 'try' block. | 9114 // Now parse the 'try' block. |
| 8712 OpenBlock(); | 9115 OpenBlock(); |
| 8713 PushTryBlock(current_block_); | 9116 PushTryBlock(current_block_); |
| 8714 ExpectToken(Token::kLBRACE); | 9117 ExpectToken(Token::kLBRACE); |
| 8715 | 9118 |
| 8716 if (innermost_function().IsAsyncClosure() || | 9119 if (innermost_function().IsAsyncClosure() || |
| 8717 innermost_function().IsAsyncFunction() || | 9120 innermost_function().IsAsyncFunction() || |
| 8718 innermost_function().IsSyncGenClosure() || | 9121 innermost_function().IsSyncGenClosure() || |
| 8719 innermost_function().IsSyncGenerator()) { | 9122 innermost_function().IsSyncGenerator() || |
| 9123 innermost_function().IsAsyncGenerator() || | |
| 9124 innermost_function().IsAsyncGenClosure()) { | |
| 8720 SetupSavedTryContext(context_var); | 9125 SetupSavedTryContext(context_var); |
| 8721 } | 9126 } |
| 8722 | 9127 |
| 8723 ParseStatementSequence(); | 9128 ParseStatementSequence(); |
| 8724 ExpectToken(Token::kRBRACE); | 9129 ExpectToken(Token::kRBRACE); |
| 8725 SequenceNode* try_block = CloseBlock(); | 9130 SequenceNode* try_block = CloseBlock(); |
| 8726 | 9131 |
| 8727 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 9132 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
| 8728 (CurrentToken() != Token::kFINALLY)) { | 9133 (CurrentToken() != Token::kFINALLY)) { |
| 8729 ReportError("catch or finally clause expected"); | 9134 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"); | 9258 ReportError(jump_pos, "'break' to case clause label is illegal"); |
| 8854 } | 9259 } |
| 8855 if (target->FunctionLevel() != current_block_->scope->function_level()) { | 9260 if (target->FunctionLevel() != current_block_->scope->function_level()) { |
| 8856 ReportError(jump_pos, "'%s' target must be in same function context", | 9261 ReportError(jump_pos, "'%s' target must be in same function context", |
| 8857 Token::Str(jump_kind)); | 9262 Token::Str(jump_kind)); |
| 8858 } | 9263 } |
| 8859 return new(Z) JumpNode(jump_pos, jump_kind, target); | 9264 return new(Z) JumpNode(jump_pos, jump_kind, target); |
| 8860 } | 9265 } |
| 8861 | 9266 |
| 8862 | 9267 |
| 9268 AstNode* Parser::ParseYieldStatement() { | |
| 9269 bool is_yield_each = false; | |
| 9270 const intptr_t yield_pos = TokenPos(); | |
| 9271 ConsumeToken(); // yield reserved word. | |
| 9272 ASSERT(innermost_function().IsGenerator() || | |
| 9273 innermost_function().IsSyncGenClosure() || | |
| 9274 innermost_function().IsAsyncGenerator() || | |
| 9275 innermost_function().IsAsyncGenClosure()); | |
| 9276 if (CurrentToken() == Token::kMUL) { | |
| 9277 is_yield_each = true; | |
| 9278 ConsumeToken(); | |
| 9279 } | |
| 9280 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | |
| 9281 | |
| 9282 LetNode* yield = new(Z) LetNode(yield_pos); | |
| 9283 if (innermost_function().IsSyncGenerator() || | |
| 9284 innermost_function().IsSyncGenClosure()) { | |
| 9285 // Yield statement in sync* function. | |
| 9286 | |
| 9287 LocalVariable* iterator_param = | |
| 9288 LookupLocalScope(Symbols::IteratorParameter()); | |
| 9289 ASSERT(iterator_param != NULL); | |
| 9290 // Generate :iterator.current = expr; | |
| 9291 AstNode* iterator = | |
| 9292 new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param); | |
| 9293 AstNode* store_current = | |
| 9294 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 9295 iterator, | |
| 9296 String::ZoneHandle(Symbols::Current().raw()), | |
| 9297 expr); | |
| 9298 yield->AddNode(store_current); | |
| 9299 if (is_yield_each) { | |
| 9300 // Generate :iterator.isYieldEach = true; | |
| 9301 AstNode* set_is_yield_each = | |
| 9302 new(Z) InstanceSetterNode(Scanner::kNoSourcePos, | |
| 9303 iterator, | |
| 9304 String::ZoneHandle(Symbols::IsYieldEach().raw()), | |
| 9305 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 9306 yield->AddNode(set_is_yield_each); | |
| 9307 } | |
| 9308 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); | |
| 9309 await_marker->set_scope(current_block_->scope); | |
| 9310 yield->AddNode(await_marker); | |
| 9311 // Return true to indicate that a value has been generated. | |
| 9312 ReturnNode* return_true = new(Z) ReturnNode(yield_pos, | |
| 9313 new(Z) LiteralNode(TokenPos(), Bool::True())); | |
| 9314 return_true->set_return_type(ReturnNode::kContinuationTarget); | |
| 9315 yield->AddNode(return_true); | |
| 9316 | |
| 9317 // If this expression is part of a try block, also append the code for | |
| 9318 // restoring the saved try context that lives on the stack and possibly the | |
| 9319 // saved try context of the outer try block. | |
| 9320 LocalScope* try_scope; | |
| 9321 int16_t try_index; | |
| 9322 LocalScope* outer_try_scope; | |
| 9323 int16_t outer_try_index; | |
| 9324 CheckAsyncOpInTryBlock(&try_scope, &try_index, | |
| 9325 &outer_try_scope, &outer_try_index); | |
| 9326 if (try_scope != NULL) { | |
| 9327 yield->AddNode( | |
| 9328 AwaitTransformer::RestoreSavedTryContext(Z, | |
| 9329 try_scope, | |
| 9330 try_index)); | |
| 9331 if (outer_try_scope != NULL) { | |
| 9332 yield->AddNode( | |
| 9333 AwaitTransformer::RestoreSavedTryContext(Z, | |
| 9334 outer_try_scope, | |
| 9335 outer_try_index)); | |
| 9336 } | |
| 9337 } else { | |
| 9338 ASSERT(outer_try_scope == NULL); | |
| 9339 } | |
| 9340 } else { | |
| 9341 // yield statement in async* function. | |
| 9342 ASSERT(innermost_function().IsAsyncGenerator() || | |
| 9343 innermost_function().IsAsyncGenClosure()); | |
| 9344 | |
| 9345 LocalVariable* controller_var = LookupLocalScope(Symbols::Controller()); | |
| 9346 ASSERT(controller_var != NULL); | |
| 9347 // :controller.add[Stream](expr); | |
| 9348 ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos); | |
| 9349 add_args->Add(expr); | |
| 9350 AstNode* add_call = | |
| 9351 new(Z) InstanceCallNode(yield_pos, | |
| 9352 new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var), | |
| 9353 is_yield_each ? Symbols::AddStream() : Symbols::add(), | |
| 9354 add_args); | |
| 9355 | |
| 9356 | |
| 9357 // if (:controller.add[Stream](expr)) { | |
| 9358 // return; | |
| 9359 // } | |
| 9360 // await_marker; | |
| 9361 // continuation_return; | |
| 9362 // restore saved_try_context | |
| 9363 | |
| 9364 SequenceNode* true_branch = | |
| 9365 new(Z) SequenceNode(Scanner::kNoSourcePos, current_block_->scope); | |
| 9366 AstNode* return_from_generator = new(Z) ReturnNode(yield_pos); | |
| 9367 true_branch->Add(return_from_generator); | |
| 9368 AddNodeForFinallyInlining(return_from_generator); | |
| 9369 AstNode* if_is_cancelled = | |
| 9370 new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL); | |
| 9371 yield->AddNode(if_is_cancelled); | |
| 9372 | |
| 9373 AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode(); | |
| 9374 await_marker->set_scope(current_block_->scope); | |
| 9375 yield->AddNode(await_marker); | |
| 9376 ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos); | |
| 9377 continuation_return->set_return_type(ReturnNode::kContinuationTarget); | |
| 9378 yield->AddNode(continuation_return); | |
| 9379 | |
| 9380 // If this expression is part of a try block, also append the code for | |
| 9381 // restoring the saved try context that lives on the stack and possibly the | |
| 9382 // saved try context of the outer try block. | |
| 9383 LocalScope* try_scope; | |
| 9384 int16_t try_index; | |
| 9385 LocalScope* outer_try_scope; | |
| 9386 int16_t outer_try_index; | |
| 9387 CheckAsyncOpInTryBlock(&try_scope, &try_index, | |
| 9388 &outer_try_scope, &outer_try_index); | |
| 9389 if (try_scope != NULL) { | |
| 9390 yield->AddNode( | |
| 9391 AwaitTransformer::RestoreSavedTryContext(Z, | |
| 9392 try_scope, | |
| 9393 try_index)); | |
| 9394 if (outer_try_scope != NULL) { | |
| 9395 yield->AddNode( | |
| 9396 AwaitTransformer::RestoreSavedTryContext(Z, | |
| 9397 outer_try_scope, | |
| 9398 outer_try_index)); | |
| 9399 } | |
| 9400 } else { | |
| 9401 ASSERT(outer_try_scope == NULL); | |
| 9402 } | |
| 9403 } | |
| 9404 return yield; | |
| 9405 } | |
| 9406 | |
| 9407 | |
| 8863 AstNode* Parser::ParseStatement() { | 9408 AstNode* Parser::ParseStatement() { |
| 8864 TRACE_PARSER("ParseStatement"); | 9409 TRACE_PARSER("ParseStatement"); |
| 8865 AstNode* statement = NULL; | 9410 AstNode* statement = NULL; |
| 8866 intptr_t label_pos = 0; | 9411 intptr_t label_pos = 0; |
| 8867 String* label_name = NULL; | 9412 String* label_name = NULL; |
| 8868 if (IsIdentifier()) { | 9413 if (IsIdentifier()) { |
| 8869 if (LookaheadToken(1) == Token::kCOLON) { | 9414 if (LookaheadToken(1) == Token::kCOLON) { |
| 8870 // Statement starts with a label. | 9415 // Statement starts with a label. |
| 8871 label_name = CurrentLiteral(); | 9416 label_name = CurrentLiteral(); |
| 8872 label_pos = TokenPos(); | 9417 label_pos = TokenPos(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 8892 statement = ParseTryStatement(label_name); | 9437 statement = ParseTryStatement(label_name); |
| 8893 } else if (token == Token::kRETURN) { | 9438 } else if (token == Token::kRETURN) { |
| 8894 const intptr_t return_pos = TokenPos(); | 9439 const intptr_t return_pos = TokenPos(); |
| 8895 ConsumeToken(); | 9440 ConsumeToken(); |
| 8896 if (CurrentToken() != Token::kSEMICOLON) { | 9441 if (CurrentToken() != Token::kSEMICOLON) { |
| 8897 const intptr_t expr_pos = TokenPos(); | 9442 const intptr_t expr_pos = TokenPos(); |
| 8898 if (current_function().IsGenerativeConstructor() && | 9443 if (current_function().IsGenerativeConstructor() && |
| 8899 (current_block_->scope->function_level() == 0)) { | 9444 (current_block_->scope->function_level() == 0)) { |
| 8900 ReportError(expr_pos, | 9445 ReportError(expr_pos, |
| 8901 "return of a value is not allowed in constructors"); | 9446 "return of a value is not allowed in constructors"); |
| 8902 } else if (current_function().IsGenerator()) { | 9447 } else if (current_function().IsGeneratorClosure() && |
| 9448 (current_block_->scope->function_level() == 0)) { | |
| 8903 ReportError(expr_pos, "generator functions may not return a value"); | 9449 ReportError(expr_pos, "generator functions may not return a value"); |
| 8904 } | 9450 } |
| 8905 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); | 9451 AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL); |
| 8906 statement = new(Z) ReturnNode(statement_pos, expr); | 9452 statement = new(Z) ReturnNode(statement_pos, expr); |
| 8907 } else { | 9453 } else { |
| 8908 if (current_function().IsSyncGenClosure() && | 9454 if (current_function().IsSyncGenClosure() && |
| 8909 (current_block_->scope->function_level() == 0)) { | 9455 (current_block_->scope->function_level() == 0)) { |
| 8910 // In a synchronous generator, return without an expression | 9456 // In a synchronous generator, return without an expression |
| 8911 // returns false, signaling that the iterator terminates and | 9457 // returns false, signaling that the iterator terminates and |
| 8912 // did not yield a value. | 9458 // did not yield a value. |
| 8913 statement = new(Z) ReturnNode(statement_pos, | 9459 statement = new(Z) ReturnNode(statement_pos, |
| 8914 new(Z) LiteralNode(return_pos, Bool::False())); | 9460 new(Z) LiteralNode(return_pos, Bool::False())); |
| 8915 } else { | 9461 } else { |
| 8916 statement = new(Z) ReturnNode(statement_pos); | 9462 statement = new(Z) ReturnNode(statement_pos); |
| 8917 } | 9463 } |
| 8918 } | 9464 } |
| 8919 AddNodeForFinallyInlining(statement); | 9465 AddNodeForFinallyInlining(statement); |
| 8920 ExpectSemicolon(); | 9466 ExpectSemicolon(); |
| 8921 } else if (IsYieldKeyword()) { | 9467 } else if (IsYieldKeyword()) { |
| 8922 bool is_yield_each = false; | 9468 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(); | 9469 ExpectSemicolon(); |
| 8988 } else if (token == Token::kIF) { | 9470 } else if (token == Token::kIF) { |
| 8989 statement = ParseIfStatement(label_name); | 9471 statement = ParseIfStatement(label_name); |
| 8990 } else if (token == Token::kASSERT) { | 9472 } else if (token == Token::kASSERT) { |
| 8991 statement = ParseAssertStatement(); | 9473 statement = ParseAssertStatement(); |
| 8992 ExpectSemicolon(); | 9474 ExpectSemicolon(); |
| 8993 } else if (IsVariableDeclaration()) { | 9475 } else if (IsVariableDeclaration()) { |
| 8994 statement = ParseVariableDeclarationList(); | 9476 statement = ParseVariableDeclarationList(); |
| 8995 ExpectSemicolon(); | 9477 ExpectSemicolon(); |
| 8996 } else if (IsFunctionDeclaration()) { | 9478 } else if (IsFunctionDeclaration()) { |
| (...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9837 } | 10319 } |
| 9838 | 10320 |
| 9839 | 10321 |
| 9840 AstNode* Parser::ParseUnaryExpr() { | 10322 AstNode* Parser::ParseUnaryExpr() { |
| 9841 TRACE_PARSER("ParseUnaryExpr"); | 10323 TRACE_PARSER("ParseUnaryExpr"); |
| 9842 AstNode* expr = NULL; | 10324 AstNode* expr = NULL; |
| 9843 const intptr_t op_pos = TokenPos(); | 10325 const intptr_t op_pos = TokenPos(); |
| 9844 if (IsAwaitKeyword()) { | 10326 if (IsAwaitKeyword()) { |
| 9845 TRACE_PARSER("ParseAwaitExpr"); | 10327 TRACE_PARSER("ParseAwaitExpr"); |
| 9846 if (!innermost_function().IsAsyncFunction() && | 10328 if (!innermost_function().IsAsyncFunction() && |
| 9847 !innermost_function().IsAsyncClosure()) { | 10329 !innermost_function().IsAsyncClosure() && |
| 9848 ReportError("await operator is only allowed in async function"); | 10330 !innermost_function().IsAsyncGenerator() && |
| 10331 !innermost_function().IsAsyncGenClosure()) { | |
| 10332 ReportError("await operator is only allowed in an asynchronous function"); | |
| 9849 } | 10333 } |
| 9850 ConsumeToken(); | 10334 ConsumeToken(); |
| 9851 parsed_function()->record_await(); | 10335 parsed_function()->record_await(); |
| 9852 | 10336 |
| 9853 LocalScope* try_scope; | 10337 LocalScope* try_scope; |
| 9854 int16_t try_index; | 10338 int16_t try_index; |
| 9855 LocalScope* outer_try_scope; | 10339 LocalScope* outer_try_scope; |
| 9856 int16_t outer_try_index; | 10340 int16_t outer_try_index; |
| 9857 CheckAsyncOpInTryBlock(&try_scope, &try_index, | 10341 CheckAsyncOpInTryBlock(&try_scope, &try_index, |
| 9858 &outer_try_scope, &outer_try_index); | 10342 &outer_try_scope, &outer_try_index); |
| (...skipping 1810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11669 // them here. | 12153 // them here. |
| 11670 // Map and List interfaces do not declare bounds on their type parameters, so | 12154 // Map and List interfaces do not declare bounds on their type parameters, so |
| 11671 // we will not see malbounded type arguments here. | 12155 // we will not see malbounded type arguments here. |
| 11672 AstNode* primary = NULL; | 12156 AstNode* primary = NULL; |
| 11673 if ((CurrentToken() == Token::kLBRACK) || | 12157 if ((CurrentToken() == Token::kLBRACK) || |
| 11674 (CurrentToken() == Token::kINDEX)) { | 12158 (CurrentToken() == Token::kINDEX)) { |
| 11675 primary = ParseListLiteral(type_pos, is_const, type_arguments); | 12159 primary = ParseListLiteral(type_pos, is_const, type_arguments); |
| 11676 } else if (CurrentToken() == Token::kLBRACE) { | 12160 } else if (CurrentToken() == Token::kLBRACE) { |
| 11677 primary = ParseMapLiteral(type_pos, is_const, type_arguments); | 12161 primary = ParseMapLiteral(type_pos, is_const, type_arguments); |
| 11678 } else { | 12162 } else { |
| 11679 ReportError("unexpected token %s", Token::Str(CurrentToken())); | 12163 UnexpectedToken(); |
| 11680 } | 12164 } |
| 11681 return primary; | 12165 return primary; |
| 11682 } | 12166 } |
| 11683 | 12167 |
| 11684 | 12168 |
| 11685 AstNode* Parser::ParseSymbolLiteral() { | 12169 AstNode* Parser::ParseSymbolLiteral() { |
| 11686 ASSERT(CurrentToken() == Token::kHASH); | 12170 ASSERT(CurrentToken() == Token::kHASH); |
| 11687 ConsumeToken(); | 12171 ConsumeToken(); |
| 11688 intptr_t symbol_pos = TokenPos(); | 12172 intptr_t symbol_pos = TokenPos(); |
| 11689 String& symbol = String::Handle(Z); | 12173 String& symbol = String::Handle(Z); |
| (...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12688 void Parser::SkipQualIdent() { | 13172 void Parser::SkipQualIdent() { |
| 12689 ASSERT(IsIdentifier()); | 13173 ASSERT(IsIdentifier()); |
| 12690 ConsumeToken(); | 13174 ConsumeToken(); |
| 12691 if (CurrentToken() == Token::kPERIOD) { | 13175 if (CurrentToken() == Token::kPERIOD) { |
| 12692 ConsumeToken(); // Consume the kPERIOD token. | 13176 ConsumeToken(); // Consume the kPERIOD token. |
| 12693 ExpectIdentifier("identifier expected after '.'"); | 13177 ExpectIdentifier("identifier expected after '.'"); |
| 12694 } | 13178 } |
| 12695 } | 13179 } |
| 12696 | 13180 |
| 12697 } // namespace dart | 13181 } // namespace dart |
| OLD | NEW |