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 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 | 279 |
| 280 // For parsing a compilation unit. | 280 // For parsing a compilation unit. |
| 281 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos) | 281 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos) |
| 282 : isolate_(Isolate::Current()), | 282 : isolate_(Isolate::Current()), |
| 283 script_(Script::Handle(isolate_, script.raw())), | 283 script_(Script::Handle(isolate_, script.raw())), |
| 284 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), | 284 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), |
| 285 token_pos), | 285 token_pos), |
| 286 token_kind_(Token::kILLEGAL), | 286 token_kind_(Token::kILLEGAL), |
| 287 current_block_(NULL), | 287 current_block_(NULL), |
| 288 is_top_level_(false), | 288 is_top_level_(false), |
| 289 await_is_keyword_(false), | |
| 289 current_member_(NULL), | 290 current_member_(NULL), |
| 290 allow_function_literals_(true), | 291 allow_function_literals_(true), |
| 291 parsed_function_(NULL), | 292 parsed_function_(NULL), |
| 292 innermost_function_(Function::Handle(isolate_)), | 293 innermost_function_(Function::Handle(isolate_)), |
| 293 literal_token_(LiteralToken::Handle(isolate_)), | 294 literal_token_(LiteralToken::Handle(isolate_)), |
| 294 current_class_(Class::Handle(isolate_)), | 295 current_class_(Class::Handle(isolate_)), |
| 295 library_(Library::Handle(isolate_, library.raw())), | 296 library_(Library::Handle(isolate_, library.raw())), |
| 296 try_blocks_list_(NULL), | 297 try_blocks_list_(NULL), |
| 297 last_used_try_index_(0), | 298 last_used_try_index_(0), |
| 298 unregister_pending_function_(false) { | 299 unregister_pending_function_(false) { |
| 299 ASSERT(tokens_iterator_.IsValid()); | 300 ASSERT(tokens_iterator_.IsValid()); |
| 300 ASSERT(!library.IsNull()); | 301 ASSERT(!library.IsNull()); |
| 301 } | 302 } |
| 302 | 303 |
| 303 | 304 |
| 304 // For parsing a function. | 305 // For parsing a function. |
| 305 Parser::Parser(const Script& script, | 306 Parser::Parser(const Script& script, |
| 306 ParsedFunction* parsed_function, | 307 ParsedFunction* parsed_function, |
| 307 intptr_t token_position) | 308 intptr_t token_position) |
| 308 : isolate_(Isolate::Current()), | 309 : isolate_(Isolate::Current()), |
| 309 script_(Script::Handle(isolate_, script.raw())), | 310 script_(Script::Handle(isolate_, script.raw())), |
| 310 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), | 311 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), |
| 311 token_position), | 312 token_position), |
| 312 token_kind_(Token::kILLEGAL), | 313 token_kind_(Token::kILLEGAL), |
| 313 current_block_(NULL), | 314 current_block_(NULL), |
| 314 is_top_level_(false), | 315 is_top_level_(false), |
| 316 await_is_keyword_(false), | |
| 315 current_member_(NULL), | 317 current_member_(NULL), |
| 316 allow_function_literals_(true), | 318 allow_function_literals_(true), |
| 317 parsed_function_(parsed_function), | 319 parsed_function_(parsed_function), |
| 318 innermost_function_(Function::Handle(isolate_, | 320 innermost_function_(Function::Handle(isolate_, |
| 319 parsed_function->function().raw())), | 321 parsed_function->function().raw())), |
| 320 literal_token_(LiteralToken::Handle(isolate_)), | 322 literal_token_(LiteralToken::Handle(isolate_)), |
| 321 current_class_(Class::Handle(isolate_, | 323 current_class_(Class::Handle(isolate_, |
| 322 parsed_function->function().Owner())), | 324 parsed_function->function().Owner())), |
| 323 library_(Library::Handle(isolate_, Class::Handle( | 325 library_(Library::Handle(isolate_, Class::Handle( |
| 324 isolate_, | 326 isolate_, |
| (...skipping 2625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2950 | 2952 |
| 2951 OpenBlock(); // Open a nested scope for the outermost function block. | 2953 OpenBlock(); // Open a nested scope for the outermost function block. |
| 2952 | 2954 |
| 2953 Function& async_closure = Function::ZoneHandle(I); | 2955 Function& async_closure = Function::ZoneHandle(I); |
| 2954 if (func.IsAsyncFunction() && !func.is_async_closure()) { | 2956 if (func.IsAsyncFunction() && !func.is_async_closure()) { |
| 2955 async_closure = OpenAsyncFunction(formal_params_pos); | 2957 async_closure = OpenAsyncFunction(formal_params_pos); |
| 2956 } else if (func.is_async_closure()) { | 2958 } else if (func.is_async_closure()) { |
| 2957 OpenAsyncClosure(); | 2959 OpenAsyncClosure(); |
| 2958 } | 2960 } |
| 2959 | 2961 |
| 2962 // For async functions and their inner closures parse "await" as a keyword. | |
| 2963 if (func.IsAsyncFunction() || func.is_async_closure()) { | |
| 2964 await_is_keyword_ = true; | |
| 2965 } | |
| 2966 | |
| 2960 intptr_t end_token_pos = 0; | 2967 intptr_t end_token_pos = 0; |
| 2961 if (CurrentToken() == Token::kLBRACE) { | 2968 if (CurrentToken() == Token::kLBRACE) { |
| 2962 ConsumeToken(); | 2969 ConsumeToken(); |
| 2963 if (String::Handle(I, func.name()).Equals( | 2970 if (String::Handle(I, func.name()).Equals( |
| 2964 Symbols::EqualOperator())) { | 2971 Symbols::EqualOperator())) { |
| 2965 const Class& owner = Class::Handle(I, func.Owner()); | 2972 const Class& owner = Class::Handle(I, func.Owner()); |
| 2966 if (!owner.IsObjectClass()) { | 2973 if (!owner.IsObjectClass()) { |
| 2967 AddEqualityNullCheck(); | 2974 AddEqualityNullCheck(); |
| 2968 } | 2975 } |
| 2969 } | 2976 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3018 func.set_end_token_pos(end_token_pos); | 3025 func.set_end_token_pos(end_token_pos); |
| 3019 SequenceNode* body = CloseBlock(); | 3026 SequenceNode* body = CloseBlock(); |
| 3020 if (func.IsAsyncFunction() && !func.is_async_closure()) { | 3027 if (func.IsAsyncFunction() && !func.is_async_closure()) { |
| 3021 body = CloseAsyncFunction(async_closure, body); | 3028 body = CloseAsyncFunction(async_closure, body); |
| 3022 } else if (func.is_async_closure()) { | 3029 } else if (func.is_async_closure()) { |
| 3023 CloseAsyncClosure(body); | 3030 CloseAsyncClosure(body); |
| 3024 } | 3031 } |
| 3025 current_block_->statements->Add(body); | 3032 current_block_->statements->Add(body); |
| 3026 innermost_function_ = saved_innermost_function.raw(); | 3033 innermost_function_ = saved_innermost_function.raw(); |
| 3027 last_used_try_index_ = saved_try_index; | 3034 last_used_try_index_ = saved_try_index; |
| 3035 await_is_keyword_ = false; | |
|
hausner
2014/08/26 22:48:06
Interesting. Why are you setting this flag to fals
Michael Lippautz (Google)
2014/08/26 23:01:44
As discussed offline: Need for parsing nested func
| |
| 3028 return CloseBlock(); | 3036 return CloseBlock(); |
| 3029 } | 3037 } |
| 3030 | 3038 |
| 3031 | 3039 |
| 3032 void Parser::AddEqualityNullCheck() { | 3040 void Parser::AddEqualityNullCheck() { |
| 3033 AstNode* argument = | 3041 AstNode* argument = |
| 3034 new LoadLocalNode(Scanner::kNoSourcePos, | 3042 new LoadLocalNode(Scanner::kNoSourcePos, |
| 3035 current_block_->scope->parent()->VariableAt(1)); | 3043 current_block_->scope->parent()->VariableAt(1)); |
| 3036 LiteralNode* null_operand = | 3044 LiteralNode* null_operand = |
| 3037 new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(I)); | 3045 new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(I)); |
| (...skipping 3210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6248 *value = Bool::True().raw(); | 6256 *value = Bool::True().raw(); |
| 6249 return true; | 6257 return true; |
| 6250 } else if (CurrentToken() == Token::kFALSE) { | 6258 } else if (CurrentToken() == Token::kFALSE) { |
| 6251 *value = Bool::False().raw(); | 6259 *value = Bool::False().raw(); |
| 6252 return true; | 6260 return true; |
| 6253 } | 6261 } |
| 6254 return false; | 6262 return false; |
| 6255 } | 6263 } |
| 6256 | 6264 |
| 6257 | 6265 |
| 6258 // Returns true if the current token is kIDENT or a pseudo-keyword. | 6266 // Returns true if the current token is |
| 6267 // * kIDENT, | |
| 6268 // * or a pseudo-keyword, | |
| 6269 // * or is not the literal "await" in an async function. | |
| 6259 bool Parser::IsIdentifier() { | 6270 bool Parser::IsIdentifier() { |
| 6260 return Token::IsIdentifier(CurrentToken()); | 6271 return Token::IsIdentifier(CurrentToken()) && |
| 6272 (!await_is_keyword_ || | |
| 6273 (CurrentLiteral()->raw() != Symbols::Await().raw())); | |
| 6261 } | 6274 } |
| 6262 | 6275 |
| 6263 | 6276 |
| 6264 // Returns true if the next tokens can be parsed as a an optionally | 6277 // Returns true if the next tokens can be parsed as a an optionally |
| 6265 // qualified identifier: [ident '.'] ident. | 6278 // qualified identifier: [ident '.'] ident. |
| 6266 // Current token position is not restored. | 6279 // Current token position is not restored. |
| 6267 bool Parser::TryParseQualIdent() { | 6280 bool Parser::TryParseQualIdent() { |
| 6268 if (CurrentToken() != Token::kIDENT) { | 6281 if (CurrentToken() != Token::kIDENT) { |
| 6269 return false; | 6282 return false; |
| 6270 } | 6283 } |
| (...skipping 2176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8447 parsed_function()->reset_have_seen_await(); | 8460 parsed_function()->reset_have_seen_await(); |
| 8448 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); | 8461 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); |
| 8449 if (parsed_function()->have_seen_await()) { | 8462 if (parsed_function()->have_seen_await()) { |
| 8450 if (!current_block_->scope->LookupVariable( | 8463 if (!current_block_->scope->LookupVariable( |
| 8451 Symbols::AsyncOperation(), true)) { | 8464 Symbols::AsyncOperation(), true)) { |
| 8452 // Async operations are always encapsulated into a local function. We only | 8465 // Async operations are always encapsulated into a local function. We only |
| 8453 // need to transform the expression when generating code for this inner | 8466 // need to transform the expression when generating code for this inner |
| 8454 // function. | 8467 // function. |
| 8455 return expr; | 8468 return expr; |
| 8456 } | 8469 } |
| 8457 SequenceNode* intermediates_block = new(I) SequenceNode( | 8470 OpenBlock(); |
| 8458 Scanner::kNoSourcePos, current_block_->scope); | 8471 AwaitTransformer at(current_block_->statements, |
| 8459 AwaitTransformer at(intermediates_block, library_, parsed_function()); | 8472 library_, |
| 8473 parsed_function()); | |
| 8460 AstNode* result = at.Transform(expr); | 8474 AstNode* result = at.Transform(expr); |
| 8461 current_block_->statements->Add(intermediates_block); | 8475 current_block_->statements->Add(CloseBlock()); |
| 8462 parsed_function()->reset_have_seen_await(); | 8476 parsed_function()->reset_have_seen_await(); |
| 8463 return result; | 8477 return result; |
| 8464 } | 8478 } |
| 8465 return expr; | 8479 return expr; |
| 8466 } | 8480 } |
| 8467 | 8481 |
| 8468 | 8482 |
| 8469 AstNode* Parser::ParseExpr(bool require_compiletime_const, | 8483 AstNode* Parser::ParseExpr(bool require_compiletime_const, |
| 8470 bool consume_cascades) { | 8484 bool consume_cascades) { |
| 8471 TRACE_PARSER("ParseExpr"); | 8485 TRACE_PARSER("ParseExpr"); |
| (...skipping 2364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10836 TRACE_PARSER("ParsePrimary"); | 10850 TRACE_PARSER("ParsePrimary"); |
| 10837 ASSERT(!is_top_level_); | 10851 ASSERT(!is_top_level_); |
| 10838 AstNode* primary = NULL; | 10852 AstNode* primary = NULL; |
| 10839 const Token::Kind token = CurrentToken(); | 10853 const Token::Kind token = CurrentToken(); |
| 10840 if (IsFunctionLiteral()) { | 10854 if (IsFunctionLiteral()) { |
| 10841 // The name of a literal function is visible from inside the function, but | 10855 // The name of a literal function is visible from inside the function, but |
| 10842 // must not collide with names in the scope declaring the literal. | 10856 // must not collide with names in the scope declaring the literal. |
| 10843 OpenBlock(); | 10857 OpenBlock(); |
| 10844 primary = ParseFunctionStatement(true); | 10858 primary = ParseFunctionStatement(true); |
| 10845 CloseBlock(); | 10859 CloseBlock(); |
| 10846 } else if (IsLiteral("await") && | 10860 } else if ((CurrentLiteral()->raw() == Symbols::Await().raw()) && |
| 10847 (parsed_function()->function().IsAsyncFunction() || | 10861 (parsed_function()->function().IsAsyncFunction() || |
| 10848 parsed_function()->function().is_async_closure())) { | 10862 parsed_function()->function().is_async_closure())) { |
| 10849 // The body of an async function is parsed multiple times. The first time | 10863 // The body of an async function is parsed multiple times. The first time |
| 10850 // when setting up an AsyncFunction() for generating relevant scope | 10864 // when setting up an AsyncFunction() for generating relevant scope |
| 10851 // information. The second time the body is parsed for actually generating | 10865 // information. The second time the body is parsed for actually generating |
| 10852 // code. | 10866 // code. |
| 10853 TRACE_PARSER("ParseAwaitExpr"); | 10867 TRACE_PARSER("ParseAwaitExpr"); |
| 10854 ConsumeToken(); | 10868 ConsumeToken(); |
| 10855 parsed_function()->record_await(); | 10869 parsed_function()->record_await(); |
| 10856 primary = new(I) AwaitNode( | 10870 primary = new(I) AwaitNode( |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11387 void Parser::SkipQualIdent() { | 11401 void Parser::SkipQualIdent() { |
| 11388 ASSERT(IsIdentifier()); | 11402 ASSERT(IsIdentifier()); |
| 11389 ConsumeToken(); | 11403 ConsumeToken(); |
| 11390 if (CurrentToken() == Token::kPERIOD) { | 11404 if (CurrentToken() == Token::kPERIOD) { |
| 11391 ConsumeToken(); // Consume the kPERIOD token. | 11405 ConsumeToken(); // Consume the kPERIOD token. |
| 11392 ExpectIdentifier("identifier expected after '.'"); | 11406 ExpectIdentifier("identifier expected after '.'"); |
| 11393 } | 11407 } |
| 11394 } | 11408 } |
| 11395 | 11409 |
| 11396 } // namespace dart | 11410 } // namespace dart |
| OLD | NEW |