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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/ast-expression-visitor.h" | 9 #include "src/ast/ast-expression-visitor.h" |
10 #include "src/ast/ast-literal-reindexer.h" | 10 #include "src/ast/ast-literal-reindexer.h" |
(...skipping 3299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3310 // labels: for (; flag == 1; flag = 0, temp_x = x) { | 3310 // labels: for (; flag == 1; flag = 0, temp_x = x) { |
3311 // body | 3311 // body |
3312 // } | 3312 // } |
3313 // {{ if (flag == 1) // Body used break. | 3313 // {{ if (flag == 1) // Body used break. |
3314 // break; | 3314 // break; |
3315 // }} | 3315 // }} |
3316 // } | 3316 // } |
3317 // } | 3317 // } |
3318 | 3318 |
3319 DCHECK(names->length() > 0); | 3319 DCHECK(names->length() > 0); |
3320 Scope* for_scope = scope_; | |
3321 ZoneList<Variable*> temps(names->length(), zone()); | 3320 ZoneList<Variable*> temps(names->length(), zone()); |
3322 | 3321 |
3323 Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false, | 3322 Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false, |
3324 RelocInfo::kNoPosition); | 3323 RelocInfo::kNoPosition); |
3325 | 3324 |
3326 // Add statement: let/const x = i. | 3325 // Add statement: let/const x = i. |
3327 outer_block->statements()->Add(init, zone()); | 3326 outer_block->statements()->Add(init, zone()); |
3328 | 3327 |
3329 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); | 3328 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); |
3330 | 3329 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3363 zone()); | 3362 zone()); |
3364 | 3363 |
3365 // Make statement: outer: for (;;) | 3364 // Make statement: outer: for (;;) |
3366 // Note that we don't actually create the label, or set this loop up as an | 3365 // Note that we don't actually create the label, or set this loop up as an |
3367 // explicit break target, instead handing it directly to those nodes that | 3366 // explicit break target, instead handing it directly to those nodes that |
3368 // need to know about it. This should be safe because we don't run any code | 3367 // need to know about it. This should be safe because we don't run any code |
3369 // in this function that looks up break targets. | 3368 // in this function that looks up break targets. |
3370 ForStatement* outer_loop = | 3369 ForStatement* outer_loop = |
3371 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); | 3370 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); |
3372 outer_block->statements()->Add(outer_loop, zone()); | 3371 outer_block->statements()->Add(outer_loop, zone()); |
3373 | 3372 outer_block->set_scope(scope_); |
3374 outer_block->set_scope(for_scope); | |
3375 scope_ = inner_scope; | |
3376 | 3373 |
3377 Block* inner_block = | 3374 Block* inner_block = |
3378 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | 3375 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
3379 Block* ignore_completion_block = factory()->NewBlock( | 3376 { |
3380 NULL, names->length() + 3, true, RelocInfo::kNoPosition); | 3377 BlockState block_state(&scope_, inner_scope); |
3381 ZoneList<Variable*> inner_vars(names->length(), zone()); | |
3382 // For each let variable x: | |
3383 // make statement: let/const x = temp_x. | |
3384 VariableMode mode = is_const ? CONST : LET; | |
3385 for (int i = 0; i < names->length(); i++) { | |
3386 VariableProxy* proxy = NewUnresolved(names->at(i), mode); | |
3387 Declaration* declaration = factory()->NewVariableDeclaration( | |
3388 proxy, mode, scope_, RelocInfo::kNoPosition); | |
3389 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | |
3390 inner_vars.Add(declaration->proxy()->var(), zone()); | |
3391 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | |
3392 Assignment* assignment = factory()->NewAssignment( | |
3393 Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition); | |
3394 Statement* assignment_statement = | |
3395 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | |
3396 DCHECK(init->position() != RelocInfo::kNoPosition); | |
3397 proxy->var()->set_initializer_position(init->position()); | |
3398 ignore_completion_block->statements()->Add(assignment_statement, zone()); | |
3399 } | |
3400 | 3378 |
3401 // Make statement: if (first == 1) { first = 0; } else { next; } | 3379 Block* ignore_completion_block = factory()->NewBlock( |
3402 if (next) { | 3380 NULL, names->length() + 3, true, RelocInfo::kNoPosition); |
3403 DCHECK(first); | 3381 ZoneList<Variable*> inner_vars(names->length(), zone()); |
3404 Expression* compare = NULL; | 3382 // For each let variable x: |
3405 // Make compare expression: first == 1. | 3383 // make statement: let/const x = temp_x. |
3406 { | 3384 VariableMode mode = is_const ? CONST : LET; |
3407 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3385 for (int i = 0; i < names->length(); i++) { |
3408 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | 3386 VariableProxy* proxy = NewUnresolved(names->at(i), mode); |
3409 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1, | 3387 Declaration* declaration = factory()->NewVariableDeclaration( |
3410 RelocInfo::kNoPosition); | 3388 proxy, mode, scope_, RelocInfo::kNoPosition); |
| 3389 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
| 3390 inner_vars.Add(declaration->proxy()->var(), zone()); |
| 3391 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
| 3392 Assignment* assignment = factory()->NewAssignment( |
| 3393 Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition); |
| 3394 Statement* assignment_statement = |
| 3395 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| 3396 DCHECK(init->position() != RelocInfo::kNoPosition); |
| 3397 proxy->var()->set_initializer_position(init->position()); |
| 3398 ignore_completion_block->statements()->Add(assignment_statement, zone()); |
3411 } | 3399 } |
3412 Statement* clear_first = NULL; | 3400 |
3413 // Make statement: first = 0. | 3401 // Make statement: if (first == 1) { first = 0; } else { next; } |
3414 { | 3402 if (next) { |
3415 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | 3403 DCHECK(first); |
3416 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); | 3404 Expression* compare = NULL; |
3417 Assignment* assignment = factory()->NewAssignment( | 3405 // Make compare expression: first == 1. |
3418 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition); | 3406 { |
3419 clear_first = | 3407 Expression* const1 = |
3420 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 3408 factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
| 3409 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
| 3410 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1, |
| 3411 RelocInfo::kNoPosition); |
| 3412 } |
| 3413 Statement* clear_first = NULL; |
| 3414 // Make statement: first = 0. |
| 3415 { |
| 3416 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
| 3417 Expression* const0 = |
| 3418 factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); |
| 3419 Assignment* assignment = factory()->NewAssignment( |
| 3420 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition); |
| 3421 clear_first = factory()->NewExpressionStatement(assignment, |
| 3422 RelocInfo::kNoPosition); |
| 3423 } |
| 3424 Statement* clear_first_or_next = factory()->NewIfStatement( |
| 3425 compare, clear_first, next, RelocInfo::kNoPosition); |
| 3426 ignore_completion_block->statements()->Add(clear_first_or_next, zone()); |
3421 } | 3427 } |
3422 Statement* clear_first_or_next = factory()->NewIfStatement( | |
3423 compare, clear_first, next, RelocInfo::kNoPosition); | |
3424 ignore_completion_block->statements()->Add(clear_first_or_next, zone()); | |
3425 } | |
3426 | 3428 |
3427 Variable* flag = scope_->NewTemporary(temp_name); | 3429 Variable* flag = scope_->NewTemporary(temp_name); |
3428 // Make statement: flag = 1. | 3430 // Make statement: flag = 1. |
3429 { | |
3430 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
3431 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | |
3432 Assignment* assignment = factory()->NewAssignment( | |
3433 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition); | |
3434 Statement* assignment_statement = | |
3435 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | |
3436 ignore_completion_block->statements()->Add(assignment_statement, zone()); | |
3437 } | |
3438 | |
3439 // Make statement: if (!cond) break. | |
3440 if (cond) { | |
3441 Statement* stop = | |
3442 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); | |
3443 Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | |
3444 ignore_completion_block->statements()->Add( | |
3445 factory()->NewIfStatement(cond, noop, stop, cond->position()), zone()); | |
3446 } | |
3447 | |
3448 inner_block->statements()->Add(ignore_completion_block, zone()); | |
3449 // Make cond expression for main loop: flag == 1. | |
3450 Expression* flag_cond = NULL; | |
3451 { | |
3452 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | |
3453 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
3454 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, | |
3455 RelocInfo::kNoPosition); | |
3456 } | |
3457 | |
3458 // Create chain of expressions "flag = 0, temp_x = x, ..." | |
3459 Statement* compound_next_statement = NULL; | |
3460 { | |
3461 Expression* compound_next = NULL; | |
3462 // Make expression: flag = 0. | |
3463 { | 3431 { |
3464 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | 3432 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
3465 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); | 3433 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
3466 compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy, | 3434 Assignment* assignment = factory()->NewAssignment( |
3467 const0, RelocInfo::kNoPosition); | 3435 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition); |
| 3436 Statement* assignment_statement = |
| 3437 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| 3438 ignore_completion_block->statements()->Add(assignment_statement, zone()); |
3468 } | 3439 } |
3469 | 3440 |
3470 // Make the comma-separated list of temp_x = x assignments. | 3441 // Make statement: if (!cond) break. |
3471 int inner_var_proxy_pos = scanner()->location().beg_pos; | 3442 if (cond) { |
3472 for (int i = 0; i < names->length(); i++) { | 3443 Statement* stop = |
3473 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | 3444 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); |
3474 VariableProxy* proxy = | 3445 Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
3475 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos); | 3446 ignore_completion_block->statements()->Add( |
3476 Assignment* assignment = factory()->NewAssignment( | 3447 factory()->NewIfStatement(cond, noop, stop, cond->position()), |
3477 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); | 3448 zone()); |
3478 compound_next = factory()->NewBinaryOperation( | |
3479 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition); | |
3480 } | 3449 } |
3481 | 3450 |
3482 compound_next_statement = factory()->NewExpressionStatement( | 3451 inner_block->statements()->Add(ignore_completion_block, zone()); |
3483 compound_next, RelocInfo::kNoPosition); | 3452 // Make cond expression for main loop: flag == 1. |
3484 } | 3453 Expression* flag_cond = NULL; |
3485 | |
3486 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x) | |
3487 // Note that we re-use the original loop node, which retains its labels | |
3488 // and ensures that any break or continue statements in body point to | |
3489 // the right place. | |
3490 loop->Initialize(NULL, flag_cond, compound_next_statement, body); | |
3491 inner_block->statements()->Add(loop, zone()); | |
3492 | |
3493 // Make statement: {{if (flag == 1) break;}} | |
3494 { | |
3495 Expression* compare = NULL; | |
3496 // Make compare expresion: flag == 1. | |
3497 { | 3454 { |
3498 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3455 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
3499 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | 3456 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
3500 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, | 3457 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, |
3501 RelocInfo::kNoPosition); | 3458 RelocInfo::kNoPosition); |
3502 } | 3459 } |
3503 Statement* stop = | 3460 |
3504 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); | 3461 // Create chain of expressions "flag = 0, temp_x = x, ..." |
3505 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | 3462 Statement* compound_next_statement = NULL; |
3506 Statement* if_flag_break = | 3463 { |
3507 factory()->NewIfStatement(compare, stop, empty, RelocInfo::kNoPosition); | 3464 Expression* compound_next = NULL; |
3508 Block* ignore_completion_block = | 3465 // Make expression: flag = 0. |
3509 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); | 3466 { |
3510 ignore_completion_block->statements()->Add(if_flag_break, zone()); | 3467 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
3511 inner_block->statements()->Add(ignore_completion_block, zone()); | 3468 Expression* const0 = |
| 3469 factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); |
| 3470 compound_next = factory()->NewAssignment( |
| 3471 Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition); |
| 3472 } |
| 3473 |
| 3474 // Make the comma-separated list of temp_x = x assignments. |
| 3475 int inner_var_proxy_pos = scanner()->location().beg_pos; |
| 3476 for (int i = 0; i < names->length(); i++) { |
| 3477 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
| 3478 VariableProxy* proxy = |
| 3479 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos); |
| 3480 Assignment* assignment = factory()->NewAssignment( |
| 3481 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); |
| 3482 compound_next = factory()->NewBinaryOperation( |
| 3483 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition); |
| 3484 } |
| 3485 |
| 3486 compound_next_statement = factory()->NewExpressionStatement( |
| 3487 compound_next, RelocInfo::kNoPosition); |
| 3488 } |
| 3489 |
| 3490 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x) |
| 3491 // Note that we re-use the original loop node, which retains its labels |
| 3492 // and ensures that any break or continue statements in body point to |
| 3493 // the right place. |
| 3494 loop->Initialize(NULL, flag_cond, compound_next_statement, body); |
| 3495 inner_block->statements()->Add(loop, zone()); |
| 3496 |
| 3497 // Make statement: {{if (flag == 1) break;}} |
| 3498 { |
| 3499 Expression* compare = NULL; |
| 3500 // Make compare expresion: flag == 1. |
| 3501 { |
| 3502 Expression* const1 = |
| 3503 factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
| 3504 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
| 3505 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, |
| 3506 RelocInfo::kNoPosition); |
| 3507 } |
| 3508 Statement* stop = |
| 3509 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); |
| 3510 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
| 3511 Statement* if_flag_break = factory()->NewIfStatement( |
| 3512 compare, stop, empty, RelocInfo::kNoPosition); |
| 3513 Block* ignore_completion_block = |
| 3514 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); |
| 3515 ignore_completion_block->statements()->Add(if_flag_break, zone()); |
| 3516 inner_block->statements()->Add(ignore_completion_block, zone()); |
| 3517 } |
| 3518 |
| 3519 inner_scope->set_end_position(scanner()->location().end_pos); |
| 3520 inner_block->set_scope(inner_scope); |
3512 } | 3521 } |
3513 | 3522 |
3514 inner_scope->set_end_position(scanner()->location().end_pos); | |
3515 inner_block->set_scope(inner_scope); | |
3516 scope_ = for_scope; | |
3517 | |
3518 outer_loop->Initialize(NULL, NULL, NULL, inner_block); | 3523 outer_loop->Initialize(NULL, NULL, NULL, inner_block); |
3519 return outer_block; | 3524 return outer_block; |
3520 } | 3525 } |
3521 | 3526 |
3522 | 3527 |
3523 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 3528 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
3524 bool* ok) { | 3529 bool* ok) { |
3525 // ForStatement :: | 3530 // ForStatement :: |
3526 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 3531 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
3527 | 3532 |
3528 int stmt_pos = peek_position(); | 3533 int stmt_pos = peek_position(); |
3529 bool is_const = false; | 3534 bool is_const = false; |
3530 Statement* init = NULL; | 3535 Statement* init = NULL; |
3531 ZoneList<const AstRawString*> lexical_bindings(1, zone()); | 3536 ZoneList<const AstRawString*> lexical_bindings(1, zone()); |
3532 | 3537 |
3533 // Create an in-between scope for let-bound iteration variables. | 3538 // Create an in-between scope for let-bound iteration variables. |
3534 Scope* saved_scope = scope_; | |
3535 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3539 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
3536 scope_ = for_scope; | 3540 |
| 3541 BlockState block_state(&scope_, for_scope); |
3537 Expect(Token::FOR, CHECK_OK); | 3542 Expect(Token::FOR, CHECK_OK); |
3538 Expect(Token::LPAREN, CHECK_OK); | 3543 Expect(Token::LPAREN, CHECK_OK); |
3539 for_scope->set_start_position(scanner()->location().beg_pos); | 3544 for_scope->set_start_position(scanner()->location().beg_pos); |
3540 bool is_let_identifier_expression = false; | 3545 bool is_let_identifier_expression = false; |
3541 DeclarationParsingResult parsing_result; | 3546 DeclarationParsingResult parsing_result; |
3542 if (peek() != Token::SEMICOLON) { | 3547 if (peek() != Token::SEMICOLON) { |
3543 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || | 3548 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || |
3544 (peek() == Token::LET && IsNextLetKeyword())) { | 3549 (peek() == Token::LET && IsNextLetKeyword())) { |
3545 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); | 3550 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); |
3546 is_const = parsing_result.descriptor.mode == CONST; | 3551 is_const = parsing_result.descriptor.mode == CONST; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3609 // { | 3614 // { |
3610 // <let x' be a temporary variable> | 3615 // <let x' be a temporary variable> |
3611 // for (x' in/of e) { | 3616 // for (x' in/of e) { |
3612 // let/const/var x; | 3617 // let/const/var x; |
3613 // x = x'; | 3618 // x = x'; |
3614 // b; | 3619 // b; |
3615 // } | 3620 // } |
3616 // let x; // for TDZ | 3621 // let x; // for TDZ |
3617 // } | 3622 // } |
3618 | 3623 |
3619 Variable* temp = scope_->NewTemporary( | 3624 Variable* temp = |
3620 ast_value_factory()->dot_for_string()); | 3625 scope_->NewTemporary(ast_value_factory()->dot_for_string()); |
3621 ForEachStatement* loop = | 3626 ForEachStatement* loop = |
3622 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3627 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3623 Target target(&this->target_stack_, loop); | 3628 Target target(&this->target_stack_, loop); |
3624 | 3629 |
3625 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3630 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3626 | 3631 |
3627 Expect(Token::RPAREN, CHECK_OK); | 3632 Expect(Token::RPAREN, CHECK_OK); |
3628 | 3633 |
3629 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); | 3634 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); |
3630 body_scope->set_start_position(scanner()->location().beg_pos); | 3635 body_scope->set_start_position(scanner()->location().beg_pos); |
3631 scope_ = body_scope; | |
3632 | |
3633 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
3634 | 3636 |
3635 Block* body_block = | 3637 Block* body_block = |
3636 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | 3638 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
3637 | 3639 |
3638 auto each_initialization_block = | |
3639 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); | |
3640 { | 3640 { |
3641 auto descriptor = parsing_result.descriptor; | 3641 BlockState block_state(&scope_, body_scope); |
3642 descriptor.declaration_pos = RelocInfo::kNoPosition; | |
3643 descriptor.initialization_pos = RelocInfo::kNoPosition; | |
3644 decl.initializer = factory()->NewVariableProxy(temp); | |
3645 | 3642 |
3646 PatternRewriter::DeclareAndInitializeVariables( | 3643 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
3647 each_initialization_block, &descriptor, &decl, | 3644 |
3648 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings | 3645 auto each_initialization_block = |
3649 : nullptr, | 3646 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); |
3650 CHECK_OK); | 3647 { |
| 3648 auto descriptor = parsing_result.descriptor; |
| 3649 descriptor.declaration_pos = RelocInfo::kNoPosition; |
| 3650 descriptor.initialization_pos = RelocInfo::kNoPosition; |
| 3651 decl.initializer = factory()->NewVariableProxy(temp); |
| 3652 |
| 3653 PatternRewriter::DeclareAndInitializeVariables( |
| 3654 each_initialization_block, &descriptor, &decl, |
| 3655 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings |
| 3656 : nullptr, |
| 3657 CHECK_OK); |
| 3658 } |
| 3659 |
| 3660 body_block->statements()->Add(each_initialization_block, zone()); |
| 3661 body_block->statements()->Add(body, zone()); |
| 3662 VariableProxy* temp_proxy = |
| 3663 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); |
| 3664 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, |
| 3665 false); |
3651 } | 3666 } |
3652 | |
3653 body_block->statements()->Add(each_initialization_block, zone()); | |
3654 body_block->statements()->Add(body, zone()); | |
3655 VariableProxy* temp_proxy = | |
3656 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | |
3657 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, | |
3658 false); | |
3659 scope_ = for_scope; | |
3660 body_scope->set_end_position(scanner()->location().end_pos); | 3667 body_scope->set_end_position(scanner()->location().end_pos); |
3661 body_scope = body_scope->FinalizeBlockScope(); | 3668 body_scope = body_scope->FinalizeBlockScope(); |
3662 if (body_scope != nullptr) { | |
3663 body_block->set_scope(body_scope); | 3669 body_block->set_scope(body_scope); |
3664 } | |
3665 | 3670 |
3666 // Create a TDZ for any lexically-bound names. | 3671 // Create a TDZ for any lexically-bound names. |
3667 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { | 3672 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { |
3668 DCHECK_NULL(init_block); | 3673 DCHECK_NULL(init_block); |
3669 | 3674 |
3670 init_block = | 3675 init_block = |
3671 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition); | 3676 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition); |
3672 | 3677 |
3673 for (int i = 0; i < lexical_bindings.length(); ++i) { | 3678 for (int i = 0; i < lexical_bindings.length(); ++i) { |
3674 // TODO(adamk): This needs to be some sort of special | 3679 // TODO(adamk): This needs to be some sort of special |
3675 // INTERNAL variable that's invisible to the debugger | 3680 // INTERNAL variable that's invisible to the debugger |
3676 // but visible to everything else. | 3681 // but visible to everything else. |
3677 VariableProxy* tdz_proxy = NewUnresolved(lexical_bindings[i], LET); | 3682 VariableProxy* tdz_proxy = |
3678 Declaration* tdz_decl = factory()->NewVariableDeclaration( | 3683 NewUnresolved(lexical_bindings[i], LET); |
3679 tdz_proxy, LET, scope_, RelocInfo::kNoPosition); | 3684 Declaration* tdz_decl = factory()->NewVariableDeclaration( |
3680 Variable* tdz_var = Declare(tdz_decl, DeclarationDescriptor::NORMAL, | 3685 tdz_proxy, LET, scope_, RelocInfo::kNoPosition); |
3681 true, CHECK_OK); | 3686 Variable* tdz_var = Declare( |
3682 tdz_var->set_initializer_position(position()); | 3687 tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
| 3688 tdz_var->set_initializer_position(position()); |
| 3689 } |
3683 } | 3690 } |
3684 } | |
3685 | 3691 |
3686 scope_ = saved_scope; | |
3687 for_scope->set_end_position(scanner()->location().end_pos); | 3692 for_scope->set_end_position(scanner()->location().end_pos); |
3688 for_scope = for_scope->FinalizeBlockScope(); | 3693 for_scope = for_scope->FinalizeBlockScope(); |
3689 // Parsed for-in loop w/ variable declarations. | 3694 // Parsed for-in loop w/ variable declarations. |
3690 if (init_block != nullptr) { | 3695 if (init_block != nullptr) { |
3691 init_block->statements()->Add(loop, zone()); | 3696 init_block->statements()->Add(loop, zone()); |
3692 if (for_scope != nullptr) { | 3697 init_block->set_scope(for_scope); |
3693 init_block->set_scope(for_scope); | |
3694 } | |
3695 return init_block; | 3698 return init_block; |
3696 } else { | 3699 } else { |
3697 DCHECK_NULL(for_scope); | 3700 DCHECK_NULL(for_scope); |
3698 return loop; | 3701 return loop; |
3699 } | 3702 } |
3700 } else { | 3703 } else { |
3701 init = parsing_result.BuildInitializationBlock( | 3704 init = parsing_result.BuildInitializationBlock( |
3702 IsLexicalVariableMode(parsing_result.descriptor.mode) | 3705 IsLexicalVariableMode(parsing_result.descriptor.mode) |
3703 ? &lexical_bindings | 3706 ? &lexical_bindings |
3704 : nullptr, | 3707 : nullptr, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3741 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3744 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3742 Expect(Token::RPAREN, CHECK_OK); | 3745 Expect(Token::RPAREN, CHECK_OK); |
3743 | 3746 |
3744 // Make a block around the statement in case a lexical binding | 3747 // Make a block around the statement in case a lexical binding |
3745 // is introduced, e.g. by a FunctionDeclaration. | 3748 // is introduced, e.g. by a FunctionDeclaration. |
3746 // This block must not use for_scope as its scope because if a | 3749 // This block must not use for_scope as its scope because if a |
3747 // lexical binding is introduced which overlaps with the for-in/of, | 3750 // lexical binding is introduced which overlaps with the for-in/of, |
3748 // expressions in head of the loop should actually have variables | 3751 // expressions in head of the loop should actually have variables |
3749 // resolved in the outer scope. | 3752 // resolved in the outer scope. |
3750 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); | 3753 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); |
3751 scope_ = body_scope; | 3754 BlockState block_state(&scope_, body_scope); |
3752 Block* block = | 3755 Block* block = |
3753 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | 3756 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); |
3754 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3757 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
3755 block->statements()->Add(body, zone()); | 3758 block->statements()->Add(body, zone()); |
3756 InitializeForEachStatement(loop, expression, enumerable, block, | 3759 InitializeForEachStatement(loop, expression, enumerable, block, |
3757 is_destructuring); | 3760 is_destructuring); |
3758 scope_ = saved_scope; | |
3759 body_scope->set_end_position(scanner()->location().end_pos); | 3761 body_scope->set_end_position(scanner()->location().end_pos); |
3760 body_scope = body_scope->FinalizeBlockScope(); | 3762 body_scope = body_scope->FinalizeBlockScope(); |
3761 if (body_scope != nullptr) { | 3763 block->set_scope(body_scope); |
3762 block->set_scope(body_scope); | |
3763 } | |
3764 for_scope->set_end_position(scanner()->location().end_pos); | 3764 for_scope->set_end_position(scanner()->location().end_pos); |
3765 for_scope = for_scope->FinalizeBlockScope(); | 3765 for_scope = for_scope->FinalizeBlockScope(); |
3766 DCHECK(for_scope == nullptr); | 3766 DCHECK(for_scope == nullptr); |
3767 // Parsed for-in loop. | 3767 // Parsed for-in loop. |
3768 return loop; | 3768 return loop; |
3769 | 3769 |
3770 } else { | 3770 } else { |
3771 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); | 3771 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); |
3772 } | 3772 } |
3773 } | 3773 } |
3774 } | 3774 } |
3775 | 3775 |
3776 // Standard 'for' loop | 3776 // Standard 'for' loop |
3777 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); | 3777 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); |
3778 Target target(&this->target_stack_, loop); | 3778 Target target(&this->target_stack_, loop); |
3779 | 3779 |
3780 // Parsed initializer at this point. | 3780 // Parsed initializer at this point. |
3781 // Detect attempts at 'let' declarations in sloppy mode. | 3781 // Detect attempts at 'let' declarations in sloppy mode. |
3782 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER && | 3782 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER && |
3783 is_sloppy(language_mode()) && is_let_identifier_expression) { | 3783 is_sloppy(language_mode()) && is_let_identifier_expression) { |
3784 ReportMessage(MessageTemplate::kSloppyLexical, NULL); | 3784 ReportMessage(MessageTemplate::kSloppyLexical, NULL); |
3785 *ok = false; | 3785 *ok = false; |
3786 return NULL; | 3786 return NULL; |
3787 } | 3787 } |
3788 Expect(Token::SEMICOLON, CHECK_OK); | 3788 Expect(Token::SEMICOLON, CHECK_OK); |
3789 | 3789 |
| 3790 Expression* cond = NULL; |
| 3791 Statement* next = NULL; |
| 3792 Statement* body = NULL; |
| 3793 |
3790 // If there are let bindings, then condition and the next statement of the | 3794 // If there are let bindings, then condition and the next statement of the |
3791 // for loop must be parsed in a new scope. | 3795 // for loop must be parsed in a new scope. |
3792 Scope* inner_scope = NULL; | 3796 Scope* inner_scope = scope_; |
3793 if (lexical_bindings.length() > 0) { | 3797 if (lexical_bindings.length() > 0) { |
3794 inner_scope = NewScope(for_scope, BLOCK_SCOPE); | 3798 inner_scope = NewScope(for_scope, BLOCK_SCOPE); |
3795 inner_scope->set_start_position(scanner()->location().beg_pos); | 3799 inner_scope->set_start_position(scanner()->location().beg_pos); |
3796 scope_ = inner_scope; | |
3797 } | 3800 } |
| 3801 { |
| 3802 BlockState block_state(&scope_, inner_scope); |
3798 | 3803 |
3799 Expression* cond = NULL; | 3804 if (peek() != Token::SEMICOLON) { |
3800 if (peek() != Token::SEMICOLON) { | 3805 cond = ParseExpression(true, CHECK_OK); |
3801 cond = ParseExpression(true, CHECK_OK); | 3806 } |
| 3807 Expect(Token::SEMICOLON, CHECK_OK); |
| 3808 |
| 3809 if (peek() != Token::RPAREN) { |
| 3810 Expression* exp = ParseExpression(true, CHECK_OK); |
| 3811 next = factory()->NewExpressionStatement(exp, exp->position()); |
| 3812 } |
| 3813 Expect(Token::RPAREN, CHECK_OK); |
| 3814 |
| 3815 body = ParseSubStatement(NULL, CHECK_OK); |
3802 } | 3816 } |
3803 Expect(Token::SEMICOLON, CHECK_OK); | |
3804 | |
3805 Statement* next = NULL; | |
3806 if (peek() != Token::RPAREN) { | |
3807 Expression* exp = ParseExpression(true, CHECK_OK); | |
3808 next = factory()->NewExpressionStatement(exp, exp->position()); | |
3809 } | |
3810 Expect(Token::RPAREN, CHECK_OK); | |
3811 | |
3812 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
3813 | 3817 |
3814 Statement* result = NULL; | 3818 Statement* result = NULL; |
3815 if (lexical_bindings.length() > 0) { | 3819 if (lexical_bindings.length() > 0) { |
3816 scope_ = for_scope; | 3820 BlockState block_state(&scope_, for_scope); |
3817 result = DesugarLexicalBindingsInForStatement( | 3821 result = DesugarLexicalBindingsInForStatement( |
3818 inner_scope, is_const, &lexical_bindings, loop, init, cond, | 3822 inner_scope, is_const, &lexical_bindings, loop, init, cond, |
3819 next, body, CHECK_OK); | 3823 next, body, CHECK_OK); |
3820 scope_ = saved_scope; | |
3821 for_scope->set_end_position(scanner()->location().end_pos); | 3824 for_scope->set_end_position(scanner()->location().end_pos); |
3822 } else { | 3825 } else { |
3823 scope_ = saved_scope; | |
3824 for_scope->set_end_position(scanner()->location().end_pos); | 3826 for_scope->set_end_position(scanner()->location().end_pos); |
3825 for_scope = for_scope->FinalizeBlockScope(); | 3827 for_scope = for_scope->FinalizeBlockScope(); |
3826 if (for_scope) { | 3828 if (for_scope) { |
3827 // Rewrite a for statement of the form | 3829 // Rewrite a for statement of the form |
3828 // for (const x = i; c; n) b | 3830 // for (const x = i; c; n) b |
3829 // | 3831 // |
3830 // into | 3832 // into |
3831 // | 3833 // |
3832 // { | 3834 // { |
3833 // const x = i; | 3835 // const x = i; |
(...skipping 1614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5448 auto class_literal = value->AsClassLiteral(); | 5450 auto class_literal = value->AsClassLiteral(); |
5449 if (class_literal->raw_name() == nullptr) { | 5451 if (class_literal->raw_name() == nullptr) { |
5450 class_literal->set_raw_name(name); | 5452 class_literal->set_raw_name(name); |
5451 } | 5453 } |
5452 } | 5454 } |
5453 } | 5455 } |
5454 | 5456 |
5455 | 5457 |
5456 } // namespace internal | 5458 } // namespace internal |
5457 } // namespace v8 | 5459 } // namespace v8 |
OLD | NEW |