| 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 |