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

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