Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/ast.h" | 8 #include "src/ast.h" |
| 9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
| 10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
| (...skipping 2277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2288 const Declaration& declaration = declarations.at(0); | 2288 const Declaration& declaration = declarations.at(0); |
| 2289 if (declaration.pattern->IsVariableProxy()) { | 2289 if (declaration.pattern->IsVariableProxy()) { |
| 2290 return declaration.pattern->AsVariableProxy()->raw_name(); | 2290 return declaration.pattern->AsVariableProxy()->raw_name(); |
| 2291 } | 2291 } |
| 2292 return nullptr; | 2292 return nullptr; |
| 2293 } | 2293 } |
| 2294 | 2294 |
| 2295 | 2295 |
| 2296 Block* Parser::DeclarationParsingResult::BuildInitializationBlock( | 2296 Block* Parser::DeclarationParsingResult::BuildInitializationBlock( |
| 2297 ZoneList<const AstRawString*>* names, bool* ok) { | 2297 ZoneList<const AstRawString*>* names, bool* ok) { |
| 2298 Block* result = | 2298 Block* result = descriptor.parser->factory()->NewBlock( |
| 2299 descriptor.parser->factory()->NewBlock(NULL, 1, true, descriptor.pos); | 2299 NULL, 1, true, descriptor.declaration_pos); |
| 2300 for (auto declaration : declarations) { | 2300 for (auto declaration : declarations) { |
| 2301 PatternRewriter::DeclareAndInitializeVariables( | 2301 PatternRewriter::DeclareAndInitializeVariables( |
| 2302 result, &descriptor, &declaration, names, CHECK_OK); | 2302 result, &descriptor, &declaration, names, CHECK_OK); |
| 2303 } | 2303 } |
| 2304 return result; | 2304 return result; |
| 2305 } | 2305 } |
| 2306 | 2306 |
| 2307 | 2307 |
| 2308 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, | 2308 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
| 2309 ZoneList<const AstRawString*>* names, | 2309 ZoneList<const AstRawString*>* names, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2343 // ConstDeclaration :: | 2343 // ConstDeclaration :: |
| 2344 // const ConstBinding (',' ConstBinding)* ';' | 2344 // const ConstBinding (',' ConstBinding)* ';' |
| 2345 // ConstBinding :: | 2345 // ConstBinding :: |
| 2346 // Identifier '=' AssignmentExpression | 2346 // Identifier '=' AssignmentExpression |
| 2347 // | 2347 // |
| 2348 // TODO(ES6): | 2348 // TODO(ES6): |
| 2349 // ConstBinding :: | 2349 // ConstBinding :: |
| 2350 // BindingPattern '=' AssignmentExpression | 2350 // BindingPattern '=' AssignmentExpression |
| 2351 | 2351 |
| 2352 parsing_result->descriptor.parser = this; | 2352 parsing_result->descriptor.parser = this; |
| 2353 parsing_result->descriptor.pos = peek_position(); | 2353 parsing_result->descriptor.declaration_pos = peek_position(); |
| 2354 parsing_result->descriptor.initialization_pos = peek_position(); | |
| 2354 parsing_result->descriptor.mode = VAR; | 2355 parsing_result->descriptor.mode = VAR; |
| 2355 // True if the binding needs initialization. 'let' and 'const' declared | 2356 // True if the binding needs initialization. 'let' and 'const' declared |
| 2356 // bindings are created uninitialized by their declaration nodes and | 2357 // bindings are created uninitialized by their declaration nodes and |
| 2357 // need initialization. 'var' declared bindings are always initialized | 2358 // need initialization. 'var' declared bindings are always initialized |
| 2358 // immediately by their declaration nodes. | 2359 // immediately by their declaration nodes. |
| 2359 parsing_result->descriptor.needs_init = false; | 2360 parsing_result->descriptor.needs_init = false; |
| 2360 parsing_result->descriptor.is_const = false; | 2361 parsing_result->descriptor.is_const = false; |
| 2361 parsing_result->descriptor.init_op = Token::INIT_VAR; | 2362 parsing_result->descriptor.init_op = Token::INIT_VAR; |
| 2362 if (peek() == Token::VAR) { | 2363 if (peek() == Token::VAR) { |
| 2363 if (is_strong(language_mode())) { | 2364 if (is_strong(language_mode())) { |
| (...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3410 // Create an in-between scope for let-bound iteration variables. | 3411 // Create an in-between scope for let-bound iteration variables. |
| 3411 Scope* saved_scope = scope_; | 3412 Scope* saved_scope = scope_; |
| 3412 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3413 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
| 3413 scope_ = for_scope; | 3414 scope_ = for_scope; |
| 3414 Expect(Token::FOR, CHECK_OK); | 3415 Expect(Token::FOR, CHECK_OK); |
| 3415 Expect(Token::LPAREN, CHECK_OK); | 3416 Expect(Token::LPAREN, CHECK_OK); |
| 3416 for_scope->set_start_position(scanner()->location().beg_pos); | 3417 for_scope->set_start_position(scanner()->location().beg_pos); |
| 3417 bool is_let_identifier_expression = false; | 3418 bool is_let_identifier_expression = false; |
| 3418 DeclarationParsingResult parsing_result; | 3419 DeclarationParsingResult parsing_result; |
| 3419 if (peek() != Token::SEMICOLON) { | 3420 if (peek() != Token::SEMICOLON) { |
| 3420 if (peek() == Token::VAR || | 3421 if (peek() == Token::VAR || peek() == Token::CONST || |
| 3421 (peek() == Token::CONST && is_sloppy(language_mode()))) { | 3422 (peek() == Token::LET && is_strict(language_mode()))) { |
| 3422 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); | 3423 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); |
| 3423 Block* variable_statement = | 3424 is_const = parsing_result.descriptor.mode == CONST; |
| 3424 parsing_result.BuildInitializationBlock(nullptr, CHECK_OK); | |
| 3425 | 3425 |
| 3426 int num_decl = parsing_result.declarations.length(); | 3426 int num_decl = parsing_result.declarations.length(); |
| 3427 bool accept_IN = num_decl >= 1; | 3427 bool accept_IN = num_decl >= 1; |
| 3428 bool accept_OF = true; | 3428 bool accept_OF = true; |
| 3429 ForEachStatement::VisitMode mode; | 3429 ForEachStatement::VisitMode mode; |
| 3430 int each_beg_pos = scanner()->location().beg_pos; | 3430 int each_beg_pos = scanner()->location().beg_pos; |
| 3431 int each_end_pos = scanner()->location().end_pos; | 3431 int each_end_pos = scanner()->location().end_pos; |
| 3432 | 3432 |
| 3433 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { | 3433 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { |
| 3434 if (!*ok) return nullptr; | 3434 if (!*ok) return nullptr; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 3447 ReportMessageAt(parsing_result.first_initializer_loc, | 3447 ReportMessageAt(parsing_result.first_initializer_loc, |
| 3448 MessageTemplate::kForOfLoopInitializer); | 3448 MessageTemplate::kForOfLoopInitializer); |
| 3449 } else { | 3449 } else { |
| 3450 // TODO(caitp): This should be an error in sloppy mode too. | 3450 // TODO(caitp): This should be an error in sloppy mode too. |
| 3451 ReportMessageAt(parsing_result.first_initializer_loc, | 3451 ReportMessageAt(parsing_result.first_initializer_loc, |
| 3452 MessageTemplate::kForInLoopInitializer); | 3452 MessageTemplate::kForInLoopInitializer); |
| 3453 } | 3453 } |
| 3454 *ok = false; | 3454 *ok = false; |
| 3455 return nullptr; | 3455 return nullptr; |
| 3456 } | 3456 } |
| 3457 | |
| 3458 DCHECK(parsing_result.declarations.length() == 1); | |
| 3459 Block* init_block = nullptr; | |
| 3460 | |
| 3461 // special case for legacy for (var/const x =.... in) | |
|
rossberg
2015/05/21 17:18:04
Does this actually work with const? You are doing
Dmitry Lomov (no reviews)
2015/05/21 17:22:01
It should only work for legacy const and it does (
| |
| 3462 if (is_sloppy(language_mode()) && | |
| 3463 !IsLexicalVariableMode(parsing_result.descriptor.mode) && | |
| 3464 parsing_result.declarations[0].initializer != nullptr) { | |
|
rossberg
2015/05/21 17:18:04
Don't you need to also check that the LHS is a sim
Dmitry Lomov (no reviews)
2015/05/21 17:22:01
No this is done in the parser (see tests in test-p
| |
| 3465 VariableProxy* single_var = scope_->NewUnresolved( | |
| 3466 factory(), parsing_result.SingleName(), Variable::NORMAL, | |
| 3467 each_beg_pos, each_end_pos); | |
| 3468 init_block = factory()->NewBlock( | |
| 3469 nullptr, 2, true, parsing_result.descriptor.declaration_pos); | |
| 3470 init_block->AddStatement( | |
| 3471 factory()->NewExpressionStatement( | |
| 3472 factory()->NewAssignment( | |
| 3473 Token::ASSIGN, single_var, | |
| 3474 parsing_result.declarations[0].initializer, | |
| 3475 RelocInfo::kNoPosition), | |
| 3476 RelocInfo::kNoPosition), | |
| 3477 zone()); | |
| 3478 } | |
| 3479 | |
| 3480 // Rewrite a for-in/of statement of the form | |
| 3481 // | |
| 3482 // for (let/const/var x in/of e) b | |
| 3483 // | |
| 3484 // into | |
| 3485 // | |
| 3486 // <let x' be a temporary variable> | |
| 3487 // for (x' in/of e) { | |
| 3488 // let/const/var x; | |
| 3489 // x = x'; | |
| 3490 // b; | |
| 3491 // } | |
| 3492 | |
| 3493 Variable* temp = scope_->DeclarationScope()->NewTemporary( | |
| 3494 ast_value_factory()->dot_for_string()); | |
| 3457 ForEachStatement* loop = | 3495 ForEachStatement* loop = |
| 3458 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3496 factory()->NewForEachStatement(mode, labels, stmt_pos); |
| 3459 Target target(&this->target_stack_, loop); | 3497 Target target(&this->target_stack_, loop); |
| 3460 | 3498 |
| 3461 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3499 // The expression does not see the lexical loop variables. |
| 3462 Expect(Token::RPAREN, CHECK_OK); | |
| 3463 | |
| 3464 VariableProxy* each = | |
| 3465 scope_->NewUnresolved(factory(), parsing_result.SingleName(), | |
| 3466 Variable::NORMAL, each_beg_pos, each_end_pos); | |
| 3467 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
| 3468 InitializeForEachStatement(loop, each, enumerable, body); | |
| 3469 Block* result = | |
| 3470 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | |
| 3471 result->AddStatement(variable_statement, zone()); | |
| 3472 result->AddStatement(loop, zone()); | |
| 3473 scope_ = saved_scope; | |
| 3474 for_scope->set_end_position(scanner()->location().end_pos); | |
| 3475 for_scope = for_scope->FinalizeBlockScope(); | |
| 3476 DCHECK(for_scope == NULL); | |
| 3477 // Parsed for-in loop w/ variable/const declaration. | |
| 3478 return result; | |
| 3479 } else { | |
| 3480 init = variable_statement; | |
| 3481 } | |
| 3482 } else if ((peek() == Token::LET || peek() == Token::CONST) && | |
| 3483 is_strict(language_mode())) { | |
| 3484 is_const = peek() == Token::CONST; | |
| 3485 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); | |
| 3486 DCHECK(parsing_result.descriptor.pos != RelocInfo::kNoPosition); | |
| 3487 | |
| 3488 int num_decl = parsing_result.declarations.length(); | |
| 3489 bool accept_IN = num_decl >= 1; | |
| 3490 bool accept_OF = true; | |
| 3491 ForEachStatement::VisitMode mode; | |
| 3492 int each_beg_pos = scanner()->location().beg_pos; | |
| 3493 int each_end_pos = scanner()->location().end_pos; | |
| 3494 | |
| 3495 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { | |
| 3496 if (!*ok) return nullptr; | |
| 3497 if (num_decl != 1) { | |
| 3498 const char* loop_type = | |
| 3499 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; | |
| 3500 ParserTraits::ReportMessageAt( | |
| 3501 parsing_result.bindings_loc, | |
| 3502 MessageTemplate::kForInOfLoopMultiBindings, loop_type); | |
| 3503 *ok = false; | |
| 3504 return nullptr; | |
| 3505 } | |
| 3506 if (parsing_result.first_initializer_loc.IsValid() && | |
| 3507 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { | |
| 3508 if (mode == ForEachStatement::ITERATE) { | |
| 3509 ReportMessageAt(parsing_result.first_initializer_loc, | |
| 3510 MessageTemplate::kForOfLoopInitializer); | |
| 3511 } else { | |
| 3512 ReportMessageAt(parsing_result.first_initializer_loc, | |
| 3513 MessageTemplate::kForInLoopInitializer); | |
| 3514 } | |
| 3515 *ok = false; | |
| 3516 return nullptr; | |
| 3517 } | |
| 3518 // Rewrite a for-in statement of the form | |
| 3519 // | |
| 3520 // for (let/const x in e) b | |
| 3521 // | |
| 3522 // into | |
| 3523 // | |
| 3524 // <let x' be a temporary variable> | |
| 3525 // for (x' in e) { | |
| 3526 // let/const x; | |
| 3527 // x = x'; | |
| 3528 // b; | |
| 3529 // } | |
| 3530 | |
| 3531 // TODO(keuchel): Move the temporary variable to the block scope, after | |
| 3532 // implementing stack allocated block scoped variables. | |
| 3533 Variable* temp = scope_->DeclarationScope()->NewTemporary( | |
| 3534 ast_value_factory()->dot_for_string()); | |
| 3535 VariableProxy* temp_proxy = | |
| 3536 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | |
| 3537 ForEachStatement* loop = | |
| 3538 factory()->NewForEachStatement(mode, labels, stmt_pos); | |
| 3539 Target target(&this->target_stack_, loop); | |
| 3540 | |
| 3541 // The expression does not see the loop variable. | |
| 3542 scope_ = saved_scope; | 3500 scope_ = saved_scope; |
| 3543 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3501 Expression* enumerable = ParseExpression(true, CHECK_OK); |
| 3544 scope_ = for_scope; | 3502 scope_ = for_scope; |
| 3545 Expect(Token::RPAREN, CHECK_OK); | 3503 Expect(Token::RPAREN, CHECK_OK); |
| 3546 | 3504 |
| 3547 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3505 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
| 3506 | |
| 3548 Block* body_block = | 3507 Block* body_block = |
| 3549 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | 3508 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
| 3550 | 3509 |
| 3551 auto each_initialization_block = factory()->NewBlock( | 3510 auto each_initialization_block = |
| 3552 nullptr, 1, true, parsing_result.descriptor.pos); | 3511 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); |
| 3553 { | 3512 { |
| 3554 DCHECK(parsing_result.declarations.length() == 1); | 3513 DCHECK(parsing_result.declarations.length() == 1); |
| 3555 DeclarationParsingResult::Declaration decl = | 3514 DeclarationParsingResult::Declaration decl = |
| 3556 parsing_result.declarations[0]; | 3515 parsing_result.declarations[0]; |
| 3557 decl.initializer = temp_proxy; | 3516 auto descriptor = parsing_result.descriptor; |
| 3517 descriptor.declaration_pos = RelocInfo::kNoPosition; | |
| 3518 decl.initializer = factory()->NewVariableProxy(temp); | |
| 3519 | |
| 3558 PatternRewriter::DeclareAndInitializeVariables( | 3520 PatternRewriter::DeclareAndInitializeVariables( |
| 3559 each_initialization_block, &parsing_result.descriptor, &decl, | 3521 each_initialization_block, &descriptor, &decl, |
| 3560 &lexical_bindings, CHECK_OK); | 3522 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings |
| 3523 : nullptr, | |
| 3524 CHECK_OK); | |
| 3561 } | 3525 } |
| 3562 | 3526 |
| 3563 body_block->AddStatement(each_initialization_block, zone()); | 3527 body_block->AddStatement(each_initialization_block, zone()); |
| 3564 body_block->AddStatement(body, zone()); | 3528 body_block->AddStatement(body, zone()); |
| 3529 VariableProxy* temp_proxy = | |
| 3530 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | |
| 3565 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); | 3531 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); |
| 3566 scope_ = saved_scope; | 3532 scope_ = saved_scope; |
| 3567 for_scope->set_end_position(scanner()->location().end_pos); | 3533 for_scope->set_end_position(scanner()->location().end_pos); |
| 3568 for_scope = for_scope->FinalizeBlockScope(); | 3534 for_scope = for_scope->FinalizeBlockScope(); |
| 3569 body_block->set_scope(for_scope); | 3535 if (for_scope != nullptr) { |
| 3570 // Parsed for-in loop w/ let declaration. | 3536 body_block->set_scope(for_scope); |
| 3571 return loop; | 3537 } |
| 3538 // Parsed for-in loop w/ variable declarations. | |
| 3539 if (init_block != nullptr) { | |
| 3540 init_block->AddStatement(loop, zone()); | |
| 3541 return init_block; | |
| 3542 } else { | |
| 3543 return loop; | |
| 3544 } | |
| 3572 } else { | 3545 } else { |
| 3573 init = parsing_result.BuildInitializationBlock(&lexical_bindings, | 3546 init = parsing_result.BuildInitializationBlock( |
| 3574 CHECK_OK); | 3547 IsLexicalVariableMode(parsing_result.descriptor.mode) |
| 3548 ? &lexical_bindings | |
| 3549 : nullptr, | |
| 3550 CHECK_OK); | |
| 3575 } | 3551 } |
| 3576 } else { | 3552 } else { |
| 3577 Scanner::Location lhs_location = scanner()->peek_location(); | 3553 Scanner::Location lhs_location = scanner()->peek_location(); |
| 3578 Expression* expression = ParseExpression(false, CHECK_OK); | 3554 Expression* expression = ParseExpression(false, CHECK_OK); |
| 3579 ForEachStatement::VisitMode mode; | 3555 ForEachStatement::VisitMode mode; |
| 3580 bool accept_OF = expression->IsVariableProxy(); | 3556 bool accept_OF = expression->IsVariableProxy(); |
| 3581 is_let_identifier_expression = | 3557 is_let_identifier_expression = |
| 3582 expression->IsVariableProxy() && | 3558 expression->IsVariableProxy() && |
| 3583 expression->AsVariableProxy()->raw_name() == | 3559 expression->AsVariableProxy()->raw_name() == |
| 3584 ast_value_factory()->let_string(); | 3560 ast_value_factory()->let_string(); |
| 3585 | 3561 |
| 3586 if (CheckInOrOf(accept_OF, &mode, ok)) { | 3562 if (CheckInOrOf(accept_OF, &mode, ok)) { |
| 3587 if (!*ok) return nullptr; | 3563 if (!*ok) return nullptr; |
| 3588 expression = this->CheckAndRewriteReferenceExpression( | 3564 expression = this->CheckAndRewriteReferenceExpression( |
| 3589 expression, lhs_location, MessageTemplate::kInvalidLhsInFor, | 3565 expression, lhs_location, MessageTemplate::kInvalidLhsInFor, |
| 3590 CHECK_OK); | 3566 CHECK_OK); |
| 3591 | 3567 |
| 3592 ForEachStatement* loop = | 3568 ForEachStatement* loop = |
| 3593 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3569 factory()->NewForEachStatement(mode, labels, stmt_pos); |
| 3594 Target target(&this->target_stack_, loop); | 3570 Target target(&this->target_stack_, loop); |
| (...skipping 2213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5808 | 5784 |
| 5809 Expression* Parser::SpreadCallNew(Expression* function, | 5785 Expression* Parser::SpreadCallNew(Expression* function, |
| 5810 ZoneList<v8::internal::Expression*>* args, | 5786 ZoneList<v8::internal::Expression*>* args, |
| 5811 int pos) { | 5787 int pos) { |
| 5812 args->InsertAt(0, function, zone()); | 5788 args->InsertAt(0, function, zone()); |
| 5813 | 5789 |
| 5814 return factory()->NewCallRuntime( | 5790 return factory()->NewCallRuntime( |
| 5815 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5791 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
| 5816 } | 5792 } |
| 5817 } } // namespace v8::internal | 5793 } } // namespace v8::internal |
| OLD | NEW |