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