| 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), | |
| 290 current_member_(NULL), | 289 current_member_(NULL), |
| 291 allow_function_literals_(true), | 290 allow_function_literals_(true), |
| 292 parsed_function_(NULL), | 291 parsed_function_(NULL), |
| 293 innermost_function_(Function::Handle(isolate_)), | 292 innermost_function_(Function::Handle(isolate_)), |
| 294 literal_token_(LiteralToken::Handle(isolate_)), | 293 literal_token_(LiteralToken::Handle(isolate_)), |
| 295 current_class_(Class::Handle(isolate_)), | 294 current_class_(Class::Handle(isolate_)), |
| 296 library_(Library::Handle(isolate_, library.raw())), | 295 library_(Library::Handle(isolate_, library.raw())), |
| 297 try_blocks_list_(NULL), | 296 try_blocks_list_(NULL), |
| 298 last_used_try_index_(0), | 297 last_used_try_index_(0), |
| 299 unregister_pending_function_(false) { | 298 unregister_pending_function_(false) { |
| 300 ASSERT(tokens_iterator_.IsValid()); | 299 ASSERT(tokens_iterator_.IsValid()); |
| 301 ASSERT(!library.IsNull()); | 300 ASSERT(!library.IsNull()); |
| 302 } | 301 } |
| 303 | 302 |
| 304 | 303 |
| 305 // For parsing a function. | 304 // For parsing a function. |
| 306 Parser::Parser(const Script& script, | 305 Parser::Parser(const Script& script, |
| 307 ParsedFunction* parsed_function, | 306 ParsedFunction* parsed_function, |
| 308 intptr_t token_position) | 307 intptr_t token_position) |
| 309 : isolate_(Isolate::Current()), | 308 : isolate_(Isolate::Current()), |
| 310 script_(Script::Handle(isolate_, script.raw())), | 309 script_(Script::Handle(isolate_, script.raw())), |
| 311 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), | 310 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), |
| 312 token_position), | 311 token_position), |
| 313 token_kind_(Token::kILLEGAL), | 312 token_kind_(Token::kILLEGAL), |
| 314 current_block_(NULL), | 313 current_block_(NULL), |
| 315 is_top_level_(false), | 314 is_top_level_(false), |
| 316 await_is_keyword_(false), | |
| 317 current_member_(NULL), | 315 current_member_(NULL), |
| 318 allow_function_literals_(true), | 316 allow_function_literals_(true), |
| 319 parsed_function_(parsed_function), | 317 parsed_function_(parsed_function), |
| 320 innermost_function_(Function::Handle(isolate_, | 318 innermost_function_(Function::Handle(isolate_, |
| 321 parsed_function->function().raw())), | 319 parsed_function->function().raw())), |
| 322 literal_token_(LiteralToken::Handle(isolate_)), | 320 literal_token_(LiteralToken::Handle(isolate_)), |
| 323 current_class_(Class::Handle(isolate_, | 321 current_class_(Class::Handle(isolate_, |
| 324 parsed_function->function().Owner())), | 322 parsed_function->function().Owner())), |
| 325 library_(Library::Handle(isolate_, Class::Handle( | 323 library_(Library::Handle(isolate_, Class::Handle( |
| 326 isolate_, | 324 isolate_, |
| (...skipping 2721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3048 | 3046 |
| 3049 OpenBlock(); // Open a nested scope for the outermost function block. | 3047 OpenBlock(); // Open a nested scope for the outermost function block. |
| 3050 | 3048 |
| 3051 Function& async_closure = Function::ZoneHandle(I); | 3049 Function& async_closure = Function::ZoneHandle(I); |
| 3052 if (func.IsAsyncFunction() && !func.is_async_closure()) { | 3050 if (func.IsAsyncFunction() && !func.is_async_closure()) { |
| 3053 async_closure = OpenAsyncFunction(formal_params_pos); | 3051 async_closure = OpenAsyncFunction(formal_params_pos); |
| 3054 } else if (func.is_async_closure()) { | 3052 } else if (func.is_async_closure()) { |
| 3055 OpenAsyncClosure(); | 3053 OpenAsyncClosure(); |
| 3056 } | 3054 } |
| 3057 | 3055 |
| 3058 // For async functions and their inner closures parse "await" as a keyword. | |
| 3059 if (func.IsAsyncFunction() || func.is_async_closure()) { | |
| 3060 await_is_keyword_ = true; | |
| 3061 } | |
| 3062 | |
| 3063 intptr_t end_token_pos = 0; | 3056 intptr_t end_token_pos = 0; |
| 3064 if (CurrentToken() == Token::kLBRACE) { | 3057 if (CurrentToken() == Token::kLBRACE) { |
| 3065 ConsumeToken(); | 3058 ConsumeToken(); |
| 3066 if (String::Handle(I, func.name()).Equals( | 3059 if (String::Handle(I, func.name()).Equals( |
| 3067 Symbols::EqualOperator())) { | 3060 Symbols::EqualOperator())) { |
| 3068 const Class& owner = Class::Handle(I, func.Owner()); | 3061 const Class& owner = Class::Handle(I, func.Owner()); |
| 3069 if (!owner.IsObjectClass()) { | 3062 if (!owner.IsObjectClass()) { |
| 3070 AddEqualityNullCheck(); | 3063 AddEqualityNullCheck(); |
| 3071 } | 3064 } |
| 3072 } | 3065 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3121 func.set_end_token_pos(end_token_pos); | 3114 func.set_end_token_pos(end_token_pos); |
| 3122 SequenceNode* body = CloseBlock(); | 3115 SequenceNode* body = CloseBlock(); |
| 3123 if (func.IsAsyncFunction() && !func.is_async_closure()) { | 3116 if (func.IsAsyncFunction() && !func.is_async_closure()) { |
| 3124 body = CloseAsyncFunction(async_closure, body); | 3117 body = CloseAsyncFunction(async_closure, body); |
| 3125 } else if (func.is_async_closure()) { | 3118 } else if (func.is_async_closure()) { |
| 3126 CloseAsyncClosure(body); | 3119 CloseAsyncClosure(body); |
| 3127 } | 3120 } |
| 3128 current_block_->statements->Add(body); | 3121 current_block_->statements->Add(body); |
| 3129 innermost_function_ = saved_innermost_function.raw(); | 3122 innermost_function_ = saved_innermost_function.raw(); |
| 3130 last_used_try_index_ = saved_try_index; | 3123 last_used_try_index_ = saved_try_index; |
| 3131 await_is_keyword_ = false; | |
| 3132 return CloseBlock(); | 3124 return CloseBlock(); |
| 3133 } | 3125 } |
| 3134 | 3126 |
| 3135 | 3127 |
| 3136 void Parser::AddEqualityNullCheck() { | 3128 void Parser::AddEqualityNullCheck() { |
| 3137 AstNode* argument = | 3129 AstNode* argument = |
| 3138 new LoadLocalNode(Scanner::kNoSourcePos, | 3130 new LoadLocalNode(Scanner::kNoSourcePos, |
| 3139 current_block_->scope->parent()->VariableAt(1)); | 3131 current_block_->scope->parent()->VariableAt(1)); |
| 3140 LiteralNode* null_operand = | 3132 LiteralNode* null_operand = |
| 3141 new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(I)); | 3133 new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(I)); |
| (...skipping 3210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6352 *value = Bool::True().raw(); | 6344 *value = Bool::True().raw(); |
| 6353 return true; | 6345 return true; |
| 6354 } else if (CurrentToken() == Token::kFALSE) { | 6346 } else if (CurrentToken() == Token::kFALSE) { |
| 6355 *value = Bool::False().raw(); | 6347 *value = Bool::False().raw(); |
| 6356 return true; | 6348 return true; |
| 6357 } | 6349 } |
| 6358 return false; | 6350 return false; |
| 6359 } | 6351 } |
| 6360 | 6352 |
| 6361 | 6353 |
| 6362 // Returns true if the current token is | 6354 // Returns true if the current token is kIDENT or a pseudo-keyword. |
| 6363 // * kIDENT, | |
| 6364 // * or a pseudo-keyword, | |
| 6365 // * or is not the literal "await" in an async function. | |
| 6366 bool Parser::IsIdentifier() { | 6355 bool Parser::IsIdentifier() { |
| 6367 return Token::IsIdentifier(CurrentToken()) && | 6356 return Token::IsIdentifier(CurrentToken()); |
| 6368 (!await_is_keyword_ || | |
| 6369 (CurrentLiteral()->raw() != Symbols::Await().raw())); | |
| 6370 } | 6357 } |
| 6371 | 6358 |
| 6372 | 6359 |
| 6373 // Returns true if the next tokens can be parsed as a an optionally | 6360 // Returns true if the next tokens can be parsed as a an optionally |
| 6374 // qualified identifier: [ident '.'] ident. | 6361 // qualified identifier: [ident '.'] ident. |
| 6375 // Current token position is not restored. | 6362 // Current token position is not restored. |
| 6376 bool Parser::TryParseQualIdent() { | 6363 bool Parser::TryParseQualIdent() { |
| 6377 if (CurrentToken() != Token::kIDENT) { | 6364 if (CurrentToken() != Token::kIDENT) { |
| 6378 return false; | 6365 return false; |
| 6379 } | 6366 } |
| (...skipping 2176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8556 parsed_function()->reset_have_seen_await(); | 8543 parsed_function()->reset_have_seen_await(); |
| 8557 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); | 8544 AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades); |
| 8558 if (parsed_function()->have_seen_await()) { | 8545 if (parsed_function()->have_seen_await()) { |
| 8559 if (!current_block_->scope->LookupVariable( | 8546 if (!current_block_->scope->LookupVariable( |
| 8560 Symbols::AsyncOperation(), true)) { | 8547 Symbols::AsyncOperation(), true)) { |
| 8561 // Async operations are always encapsulated into a local function. We only | 8548 // Async operations are always encapsulated into a local function. We only |
| 8562 // need to transform the expression when generating code for this inner | 8549 // need to transform the expression when generating code for this inner |
| 8563 // function. | 8550 // function. |
| 8564 return expr; | 8551 return expr; |
| 8565 } | 8552 } |
| 8566 OpenBlock(); | 8553 SequenceNode* intermediates_block = new(I) SequenceNode( |
| 8567 AwaitTransformer at(current_block_->statements, | 8554 Scanner::kNoSourcePos, current_block_->scope); |
| 8568 library_, | 8555 AwaitTransformer at(intermediates_block, library_, parsed_function()); |
| 8569 parsed_function()); | |
| 8570 AstNode* result = at.Transform(expr); | 8556 AstNode* result = at.Transform(expr); |
| 8571 current_block_->statements->Add(CloseBlock()); | 8557 current_block_->statements->Add(intermediates_block); |
| 8572 parsed_function()->reset_have_seen_await(); | 8558 parsed_function()->reset_have_seen_await(); |
| 8573 return result; | 8559 return result; |
| 8574 } | 8560 } |
| 8575 return expr; | 8561 return expr; |
| 8576 } | 8562 } |
| 8577 | 8563 |
| 8578 | 8564 |
| 8579 AstNode* Parser::ParseExpr(bool require_compiletime_const, | 8565 AstNode* Parser::ParseExpr(bool require_compiletime_const, |
| 8580 bool consume_cascades) { | 8566 bool consume_cascades) { |
| 8581 TRACE_PARSER("ParseExpr"); | 8567 TRACE_PARSER("ParseExpr"); |
| (...skipping 2364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10946 TRACE_PARSER("ParsePrimary"); | 10932 TRACE_PARSER("ParsePrimary"); |
| 10947 ASSERT(!is_top_level_); | 10933 ASSERT(!is_top_level_); |
| 10948 AstNode* primary = NULL; | 10934 AstNode* primary = NULL; |
| 10949 const Token::Kind token = CurrentToken(); | 10935 const Token::Kind token = CurrentToken(); |
| 10950 if (IsFunctionLiteral()) { | 10936 if (IsFunctionLiteral()) { |
| 10951 // The name of a literal function is visible from inside the function, but | 10937 // The name of a literal function is visible from inside the function, but |
| 10952 // must not collide with names in the scope declaring the literal. | 10938 // must not collide with names in the scope declaring the literal. |
| 10953 OpenBlock(); | 10939 OpenBlock(); |
| 10954 primary = ParseFunctionStatement(true); | 10940 primary = ParseFunctionStatement(true); |
| 10955 CloseBlock(); | 10941 CloseBlock(); |
| 10956 } else if ((CurrentLiteral()->raw() == Symbols::Await().raw()) && | 10942 } else if (IsLiteral("await") && |
| 10957 (parsed_function()->function().IsAsyncFunction() || | 10943 (parsed_function()->function().IsAsyncFunction() || |
| 10958 parsed_function()->function().is_async_closure())) { | 10944 parsed_function()->function().is_async_closure())) { |
| 10959 // The body of an async function is parsed multiple times. The first time | 10945 // The body of an async function is parsed multiple times. The first time |
| 10960 // when setting up an AsyncFunction() for generating relevant scope | 10946 // when setting up an AsyncFunction() for generating relevant scope |
| 10961 // information. The second time the body is parsed for actually generating | 10947 // information. The second time the body is parsed for actually generating |
| 10962 // code. | 10948 // code. |
| 10963 TRACE_PARSER("ParseAwaitExpr"); | 10949 TRACE_PARSER("ParseAwaitExpr"); |
| 10964 ConsumeToken(); | 10950 ConsumeToken(); |
| 10965 parsed_function()->record_await(); | 10951 parsed_function()->record_await(); |
| 10966 primary = new(I) AwaitNode( | 10952 primary = new(I) AwaitNode( |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11497 void Parser::SkipQualIdent() { | 11483 void Parser::SkipQualIdent() { |
| 11498 ASSERT(IsIdentifier()); | 11484 ASSERT(IsIdentifier()); |
| 11499 ConsumeToken(); | 11485 ConsumeToken(); |
| 11500 if (CurrentToken() == Token::kPERIOD) { | 11486 if (CurrentToken() == Token::kPERIOD) { |
| 11501 ConsumeToken(); // Consume the kPERIOD token. | 11487 ConsumeToken(); // Consume the kPERIOD token. |
| 11502 ExpectIdentifier("identifier expected after '.'"); | 11488 ExpectIdentifier("identifier expected after '.'"); |
| 11503 } | 11489 } |
| 11504 } | 11490 } |
| 11505 | 11491 |
| 11506 } // namespace dart | 11492 } // namespace dart |
| OLD | NEW |