Chromium Code Reviews| 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 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |