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

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
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 7207 matching lines...) Expand 10 before | Expand all | Expand 10 after
7218 // it to the loop body. 7218 // it to the loop body.
7219 if (await_preamble != NULL) { 7219 if (await_preamble != NULL) {
7220 dowhile_body->Add(await_preamble); 7220 dowhile_body->Add(await_preamble);
7221 } 7221 }
7222 ExpectToken(Token::kRPAREN); 7222 ExpectToken(Token::kRPAREN);
7223 ExpectSemicolon(); 7223 ExpectSemicolon();
7224 return new(I) DoWhileNode(do_pos, label, cond_expr, dowhile_body); 7224 return new(I) DoWhileNode(do_pos, label, cond_expr, dowhile_body);
7225 } 7225 }
7226 7226
7227 7227
7228 AstNode* Parser::ParseAwaitForStatement(String* label_name) {
7229 TRACE_PARSER("ParseAwaitForStatement");
7230 ASSERT(IsAwaitKeyword());
7231 const intptr_t await_for_pos = TokenPos();
7232 ConsumeToken(); // await.
7233 ASSERT(CurrentToken() == Token::kFOR);
7234 ConsumeToken(); // for.
7235 ExpectToken(Token::kLPAREN);
7236
7237 // Parse loop variable.
7238 bool loop_var_is_final = (CurrentToken() == Token::kFINAL);
7239 if (CurrentToken() == Token::kCONST) {
7240 ReportError("Loop variable cannot be 'const'");
7241 }
7242 const String* loop_var_name = NULL;
7243 intptr_t loop_var_pos = 0;
7244 bool new_loop_var = false;
7245 AbstractType& loop_var_type = AbstractType::ZoneHandle(I);
7246 if (LookaheadToken(1) == Token::kIN) {
7247 // For loop does not declare a local loop variable.
7248 loop_var_pos = TokenPos();
7249 loop_var_name = ExpectIdentifier("variable name expected");
7250 } else {
7251 // Declaration of a new loop variable.
7252 // Delay creation of the local variable until we know its actual
7253 // position, which is inside the loop body.
7254 new_loop_var = true;
7255 loop_var_type = ParseConstFinalVarOrType(
7256 FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize :
7257 ClassFinalizer::kIgnore);
7258 loop_var_name = ExpectIdentifier("variable name expected");
7259 }
7260
7261 // Parse stream expression.
7262 ExpectToken(Token::kIN);
7263 const intptr_t stream_pos = TokenPos();
7264 AstNode* stream_expr =
7265 ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
7266 ExpectToken(Token::kRPAREN);
7267
7268 OpenBlock();
7269
7270 // Build creation of implicit StreamIterator.
7271 // var :for-in-iter = new StreamIterator(stream_expr).
7272 const Class& stream_iterator_cls =
7273 Class::ZoneHandle(I, I->object_store()->stream_iterator_class());
7274 ASSERT(!stream_iterator_cls.IsNull());
7275 const Function& iterator_ctor =
7276 Function::ZoneHandle(I, stream_iterator_cls.LookupFunction(
7277 Symbols::StreamIteratorConstructor()));
7278 ASSERT(!iterator_ctor.IsNull());
7279 ArgumentListNode* ctor_args = new (I) ArgumentListNode(Scanner::kNoSourcePos);
7280 ctor_args->Add(stream_expr);
7281 ConstructorCallNode* ctor_call =
7282 new (I) ConstructorCallNode(Scanner::kNoSourcePos,
7283 TypeArguments::ZoneHandle(I),
7284 iterator_ctor,
7285 ctor_args);
7286 const AbstractType& iterator_type = Type::ZoneHandle(I, Type::DynamicType());
7287 LocalVariable* iterator_var = new(I) LocalVariable(
7288 stream_pos, Symbols::ForInIter(), iterator_type);
7289 current_block_->scope->AddVariable(iterator_var);
7290 AstNode* iterator_init =
7291 new(I) StoreLocalNode(stream_pos, iterator_var, ctor_call);
7292 current_block_->statements->Add(iterator_init);
7293
7294 // Build while loop condition.
7295 // while (await :for-in-iter.moveNext())
7296 ArgumentListNode* no_args = new(I) ArgumentListNode(stream_pos);
7297 AstNode* iterator_moveNext = new(I) InstanceCallNode(
7298 stream_pos,
7299 new(I) LoadLocalNode(stream_pos, iterator_var),
7300 Symbols::MoveNext(),
7301 no_args);
7302 AstNode* await_moveNext = new (I) AwaitNode(stream_pos, iterator_moveNext);
7303 OpenBlock();
7304 AwaitTransformer at(current_block_->statements,
7305 parsed_function(),
7306 async_temp_scope_);
7307 AstNode* transformed_await = at.Transform(await_moveNext);
7308 SequenceNode* await_preamble = CloseBlock();
7309
7310 // Parse the for loop body. Ideally, we would use ParseNestedStatement()
7311 // here, but that does not work well because we have to insert an implicit
7312 // variable assignment and potentially a variable declaration in the
7313 // loop body.
7314 OpenLoopBlock();
7315 SourceLabel* label =
7316 SourceLabel::New(await_for_pos, label_name, SourceLabel::kFor);
7317 current_block_->scope->AddLabel(label);
7318 const intptr_t loop_var_assignment_pos = TokenPos();
7319
7320 AstNode* iterator_current = new(I) InstanceGetterNode(
7321 loop_var_assignment_pos,
7322 new(I) LoadLocalNode(loop_var_assignment_pos, iterator_var),
7323 Symbols::Current());
7324
7325 // Generate assignment of next iterator value to loop variable.
7326 AstNode* loop_var_assignment = NULL;
7327 if (new_loop_var) {
7328 // The for loop variable is new for each iteration.
7329 // Create a variable and add it to the loop body scope.
7330 LocalVariable* loop_var =
7331 new(I) LocalVariable(loop_var_assignment_pos,
7332 *loop_var_name,
7333 loop_var_type);;
7334 if (loop_var_is_final) {
7335 loop_var->set_is_final();
7336 }
7337 current_block_->scope->AddVariable(loop_var);
7338 loop_var_assignment = new(I) StoreLocalNode(
7339 loop_var_assignment_pos, loop_var, iterator_current);
7340 } else {
7341 AstNode* loop_var_primary =
7342 ResolveIdent(loop_var_pos, *loop_var_name, false);
7343 ASSERT(!loop_var_primary->IsPrimaryNode());
7344 loop_var_assignment = CreateAssignmentNode(loop_var_primary,
7345 iterator_current,
7346 loop_var_name,
7347 loop_var_assignment_pos);
7348 ASSERT(loop_var_assignment != NULL);
7349 }
7350 current_block_->statements->Add(loop_var_assignment);
7351
7352 // Now parse the for-in loop statement or block.
7353 if (CurrentToken() == Token::kLBRACE) {
7354 ConsumeToken();
7355 ParseStatementSequence();
7356 ExpectToken(Token::kRBRACE);
7357 } else {
7358 AstNode* statement = ParseStatement();
7359 if (statement != NULL) {
7360 current_block_->statements->Add(statement);
7361 }
7362 }
7363 SequenceNode* for_loop_statement = CloseBlock();
7364
7365 WhileNode* while_node = new (I) WhileNode(await_for_pos,
7366 label,
7367 transformed_await,
7368 await_preamble,
7369 for_loop_statement);
7370 current_block_->statements->Add(while_node);
7371
7372 return CloseBlock(); // Implicit block around while loop.
7373 }
7374
7375
7228 AstNode* Parser::ParseForInStatement(intptr_t forin_pos, 7376 AstNode* Parser::ParseForInStatement(intptr_t forin_pos,
7229 SourceLabel* label) { 7377 SourceLabel* label) {
7230 TRACE_PARSER("ParseForInStatement"); 7378 TRACE_PARSER("ParseForInStatement");
7231 bool loop_var_is_final = (CurrentToken() == Token::kFINAL); 7379 bool loop_var_is_final = (CurrentToken() == Token::kFINAL);
7232 if (CurrentToken() == Token::kCONST) { 7380 if (CurrentToken() == Token::kCONST) {
7233 ReportError("Loop variable cannot be 'const'"); 7381 ReportError("Loop variable cannot be 'const'");
7234 } 7382 }
7235 const String* loop_var_name = NULL; 7383 const String* loop_var_name = NULL;
7236 intptr_t loop_var_pos = 0; 7384 intptr_t loop_var_pos = 0;
7237 bool new_loop_var = false; 7385 bool new_loop_var = false;
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after
8084 ConsumeToken(); // Consume colon. 8232 ConsumeToken(); // Consume colon.
8085 } 8233 }
8086 } 8234 }
8087 const intptr_t statement_pos = TokenPos(); 8235 const intptr_t statement_pos = TokenPos();
8088 const Token::Kind token = CurrentToken(); 8236 const Token::Kind token = CurrentToken();
8089 8237
8090 if (token == Token::kWHILE) { 8238 if (token == Token::kWHILE) {
8091 statement = ParseWhileStatement(label_name); 8239 statement = ParseWhileStatement(label_name);
8092 } else if (token == Token::kFOR) { 8240 } else if (token == Token::kFOR) {
8093 statement = ParseForStatement(label_name); 8241 statement = ParseForStatement(label_name);
8242 } else if (IsAwaitKeyword() && (LookaheadToken(1) == Token::kFOR)) {
8243 statement = ParseAwaitForStatement(label_name);
8094 } else if (token == Token::kDO) { 8244 } else if (token == Token::kDO) {
8095 statement = ParseDoWhileStatement(label_name); 8245 statement = ParseDoWhileStatement(label_name);
8096 } else if (token == Token::kSWITCH) { 8246 } else if (token == Token::kSWITCH) {
8097 statement = ParseSwitchStatement(label_name); 8247 statement = ParseSwitchStatement(label_name);
8098 } else if (token == Token::kTRY) { 8248 } else if (token == Token::kTRY) {
8099 statement = ParseTryStatement(label_name); 8249 statement = ParseTryStatement(label_name);
8100 } else if (token == Token::kRETURN) { 8250 } else if (token == Token::kRETURN) {
8101 const intptr_t return_pos = TokenPos(); 8251 const intptr_t return_pos = TokenPos();
8102 ConsumeToken(); 8252 ConsumeToken();
8103 if (CurrentToken() != Token::kSEMICOLON) { 8253 if (CurrentToken() != Token::kSEMICOLON) {
(...skipping 3686 matching lines...) Expand 10 before | Expand all | Expand 10 after
11790 void Parser::SkipQualIdent() { 11940 void Parser::SkipQualIdent() {
11791 ASSERT(IsIdentifier()); 11941 ASSERT(IsIdentifier());
11792 ConsumeToken(); 11942 ConsumeToken();
11793 if (CurrentToken() == Token::kPERIOD) { 11943 if (CurrentToken() == Token::kPERIOD) {
11794 ConsumeToken(); // Consume the kPERIOD token. 11944 ConsumeToken(); // Consume the kPERIOD token.
11795 ExpectIdentifier("identifier expected after '.'"); 11945 ExpectIdentifier("identifier expected after '.'");
11796 } 11946 }
11797 } 11947 }
11798 11948
11799 } // namespace dart 11949 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | tests/language/await_for_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698