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