| 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 7216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |