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

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

Issue 662603003: Implement await for statement (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 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
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 7216 matching lines...) Expand 10 before | Expand all | Expand 10 after
7227 // it to the loop body. 7227 // it to the loop body.
7228 if (await_preamble != NULL) { 7228 if (await_preamble != NULL) {
7229 dowhile_body->Add(await_preamble); 7229 dowhile_body->Add(await_preamble);
7230 } 7230 }
7231 ExpectToken(Token::kRPAREN); 7231 ExpectToken(Token::kRPAREN);
7232 ExpectSemicolon(); 7232 ExpectSemicolon();
7233 return new(I) DoWhileNode(do_pos, label, cond_expr, dowhile_body); 7233 return new(I) DoWhileNode(do_pos, label, cond_expr, dowhile_body);
7234 } 7234 }
7235 7235
7236 7236
7237 AstNode* Parser::ParseAwaitForStatement(String* label_name) {
7238 TRACE_PARSER("ParseAwaitForStatement");
7239 ASSERT(IsAwaitKeyword());
7240 const intptr_t await_for_pos = TokenPos();
7241 ConsumeToken(); // await.
7242 ASSERT(CurrentToken() == Token::kFOR);
7243 ConsumeToken(); // for.
7244 ExpectToken(Token::kLPAREN);
7245
7246 // Parse loop variable.
7247 bool loop_var_is_final = (CurrentToken() == Token::kFINAL);
7248 if (CurrentToken() == Token::kCONST) {
7249 ReportError("Loop variable cannot be 'const'");
7250 }
7251 const String* loop_var_name = NULL;
7252 intptr_t loop_var_pos = 0;
7253 bool new_loop_var = false;
7254 AbstractType& loop_var_type = AbstractType::ZoneHandle(I);
7255 if (LookaheadToken(1) == Token::kIN) {
7256 // For loop does not declare a local loop variable.
7257 loop_var_pos = TokenPos();
7258 loop_var_name = ExpectIdentifier("variable name expected");
Ivan Posva 2014/10/27 06:55:24 This line can be moved out of the if-else. The if-
hausner 2014/10/27 17:58:24 Done.
7259 } else {
7260 // Declaration of a new loop variable.
7261 // Delay creation of the local variable until we know its actual
7262 // position, which is inside the loop body.
7263 new_loop_var = true;
7264 loop_var_type = ParseConstFinalVarOrType(
7265 FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize :
7266 ClassFinalizer::kIgnore);
7267 loop_var_name = ExpectIdentifier("variable name expected");
Ivan Posva 2014/10/27 06:55:24 loop_var_pos is not being set in this case. Why?
hausner 2014/10/27 17:58:24 The position isn't used in this case, but I agree
7268 }
7269
7270 // Parse stream expression.
7271 ExpectToken(Token::kIN);
7272 const intptr_t stream_pos = TokenPos();
7273 AstNode* stream_expr =
7274 ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
7275 ExpectToken(Token::kRPAREN);
7276
7277 OpenBlock();
7278
7279 // Build creation of implicit StreamIterator.
7280 // var :for-in-iter = new StreamIterator(stream_expr).
7281 const Class& stream_iterator_cls =
7282 Class::ZoneHandle(I, I->object_store()->stream_iterator_class());
7283 ASSERT(!stream_iterator_cls.IsNull());
7284 const Function& iterator_ctor =
7285 Function::ZoneHandle(I, stream_iterator_cls.LookupFunction(
7286 Symbols::StreamIteratorConstructor()));
7287 ASSERT(!iterator_ctor.IsNull());
7288 ArgumentListNode* ctor_args = new (I) ArgumentListNode(Scanner::kNoSourcePos);
7289 ctor_args->Add(stream_expr);
7290 ConstructorCallNode* ctor_call =
7291 new (I) ConstructorCallNode(Scanner::kNoSourcePos,
7292 TypeArguments::ZoneHandle(I),
7293 iterator_ctor,
7294 ctor_args);
7295 const AbstractType& iterator_type = Type::ZoneHandle(I, Type::DynamicType());
7296 LocalVariable* iterator_var = new(I) LocalVariable(
7297 stream_pos, Symbols::ForInIter(), iterator_type);
7298 current_block_->scope->AddVariable(iterator_var);
7299 AstNode* iterator_init =
7300 new(I) StoreLocalNode(stream_pos, iterator_var, ctor_call);
7301 current_block_->statements->Add(iterator_init);
7302
7303 // Build while loop condition.
7304 // while (await :for-in-iter.moveNext())
7305 ArgumentListNode* no_args = new(I) ArgumentListNode(stream_pos);
7306 AstNode* iterator_moveNext = new(I) InstanceCallNode(
7307 stream_pos,
7308 new(I) LoadLocalNode(stream_pos, iterator_var),
7309 Symbols::MoveNext(),
7310 no_args);
7311 AstNode* await_moveNext = new (I) AwaitNode(stream_pos, iterator_moveNext);
7312 OpenBlock();
7313 AwaitTransformer at(current_block_->statements,
7314 parsed_function(),
7315 async_temp_scope_);
7316 AstNode* transformed_await = at.Transform(await_moveNext);
7317 SequenceNode* await_preamble = CloseBlock();
7318
7319 // Parse the for loop body. Ideally, we would use ParseNestedStatement()
7320 // here, but that does not work well because we have to insert an implicit
7321 // variable assignment and potentially a variable declaration in the
7322 // loop body.
7323 OpenLoopBlock();
7324 SourceLabel* label =
7325 SourceLabel::New(await_for_pos, label_name, SourceLabel::kFor);
7326 current_block_->scope->AddLabel(label);
7327 const intptr_t loop_var_assignment_pos = TokenPos();
7328
7329 AstNode* iterator_current = new(I) InstanceGetterNode(
7330 loop_var_assignment_pos,
7331 new(I) LoadLocalNode(loop_var_assignment_pos, iterator_var),
7332 Symbols::Current());
7333
7334 // Generate assignment of next iterator value to loop variable.
7335 AstNode* loop_var_assignment = NULL;
7336 if (new_loop_var) {
7337 // The for loop variable is new for each iteration.
7338 // Create a variable and add it to the loop body scope.
7339 LocalVariable* loop_var =
7340 new(I) LocalVariable(loop_var_assignment_pos,
7341 *loop_var_name,
7342 loop_var_type);;
7343 if (loop_var_is_final) {
7344 loop_var->set_is_final();
7345 }
7346 current_block_->scope->AddVariable(loop_var);
7347 loop_var_assignment = new(I) StoreLocalNode(
7348 loop_var_assignment_pos, loop_var, iterator_current);
7349 } else {
7350 AstNode* loop_var_primary =
7351 ResolveIdent(loop_var_pos, *loop_var_name, false);
7352 ASSERT(!loop_var_primary->IsPrimaryNode());
7353 loop_var_assignment = CreateAssignmentNode(loop_var_primary,
7354 iterator_current,
7355 loop_var_name,
7356 loop_var_assignment_pos);
7357 ASSERT(loop_var_assignment != NULL);
7358 }
7359 current_block_->statements->Add(loop_var_assignment);
7360
7361 // Now parse the for-in loop statement or block.
7362 if (CurrentToken() == Token::kLBRACE) {
7363 ConsumeToken();
7364 ParseStatementSequence();
7365 ExpectToken(Token::kRBRACE);
7366 } else {
7367 AstNode* statement = ParseStatement();
7368 if (statement != NULL) {
7369 current_block_->statements->Add(statement);
7370 }
7371 }
7372 SequenceNode* for_loop_statement = CloseBlock();
7373
7374 WhileNode* while_node = new (I) WhileNode(await_for_pos,
7375 label,
7376 transformed_await,
7377 await_preamble,
7378 for_loop_statement);
7379 current_block_->statements->Add(while_node);
7380
7381 return CloseBlock(); // Implicit block around while loop.
7382 }
7383
7384
7237 AstNode* Parser::ParseForInStatement(intptr_t forin_pos, 7385 AstNode* Parser::ParseForInStatement(intptr_t forin_pos,
7238 SourceLabel* label) { 7386 SourceLabel* label) {
7239 TRACE_PARSER("ParseForInStatement"); 7387 TRACE_PARSER("ParseForInStatement");
7240 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); 7388 bool loop_var_is_final = (CurrentToken() == Token::kFINAL);
7241 if (CurrentToken() == Token::kCONST) { 7389 if (CurrentToken() == Token::kCONST) {
7242 ReportError("Loop variable cannot be 'const'"); 7390 ReportError("Loop variable cannot be 'const'");
7243 } 7391 }
7244 const String* loop_var_name = NULL; 7392 const String* loop_var_name = NULL;
7245 intptr_t loop_var_pos = 0; 7393 intptr_t loop_var_pos = 0;
7246 bool new_loop_var = false; 7394 bool new_loop_var = false;
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after
8093 ConsumeToken(); // Consume colon. 8241 ConsumeToken(); // Consume colon.
8094 } 8242 }
8095 } 8243 }
8096 const intptr_t statement_pos = TokenPos(); 8244 const intptr_t statement_pos = TokenPos();
8097 const Token::Kind token = CurrentToken(); 8245 const Token::Kind token = CurrentToken();
8098 8246
8099 if (token == Token::kWHILE) { 8247 if (token == Token::kWHILE) {
8100 statement = ParseWhileStatement(label_name); 8248 statement = ParseWhileStatement(label_name);
8101 } else if (token == Token::kFOR) { 8249 } else if (token == Token::kFOR) {
8102 statement = ParseForStatement(label_name); 8250 statement = ParseForStatement(label_name);
8251 } else if (IsAwaitKeyword() && (LookaheadToken(1) == Token::kFOR)) {
8252 statement = ParseAwaitForStatement(label_name);
8103 } else if (token == Token::kDO) { 8253 } else if (token == Token::kDO) {
8104 statement = ParseDoWhileStatement(label_name); 8254 statement = ParseDoWhileStatement(label_name);
8105 } else if (token == Token::kSWITCH) { 8255 } else if (token == Token::kSWITCH) {
8106 statement = ParseSwitchStatement(label_name); 8256 statement = ParseSwitchStatement(label_name);
8107 } else if (token == Token::kTRY) { 8257 } else if (token == Token::kTRY) {
8108 statement = ParseTryStatement(label_name); 8258 statement = ParseTryStatement(label_name);
8109 } else if (token == Token::kRETURN) { 8259 } else if (token == Token::kRETURN) {
8110 const intptr_t return_pos = TokenPos(); 8260 const intptr_t return_pos = TokenPos();
8111 ConsumeToken(); 8261 ConsumeToken();
8112 if (CurrentToken() != Token::kSEMICOLON) { 8262 if (CurrentToken() != Token::kSEMICOLON) {
(...skipping 3686 matching lines...) Expand 10 before | Expand all | Expand 10 after
11799 void Parser::SkipQualIdent() { 11949 void Parser::SkipQualIdent() {
11800 ASSERT(IsIdentifier()); 11950 ASSERT(IsIdentifier());
11801 ConsumeToken(); 11951 ConsumeToken();
11802 if (CurrentToken() == Token::kPERIOD) { 11952 if (CurrentToken() == Token::kPERIOD) {
11803 ConsumeToken(); // Consume the kPERIOD token. 11953 ConsumeToken(); // Consume the kPERIOD token.
11804 ExpectIdentifier("identifier expected after '.'"); 11954 ExpectIdentifier("identifier expected after '.'");
11805 } 11955 }
11806 } 11956 }
11807 11957
11808 } // namespace dart 11958 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698