Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: runtime/vm/parser.cc

Issue 508643004: Fix scope/context behavior in await transformer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: add await_is_keyword_ indicator to parser Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« runtime/vm/parser.h ('K') | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698