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

Side by Side Diff: src/parser.cc

Issue 1149043005: [destructuring] Grand for statement parsing unification. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 7 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
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/pattern-rewriter.cc » ('j') | test/mjsunit/harmony/destructuring.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698