| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index fd403040c6e05d5201144e183479da8f78a789c5..a3cc8a50a4761321e6a3af9540f87e1f4a6331a6 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -3317,7 +3317,6 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| // }
|
|
|
| DCHECK(names->length() > 0);
|
| - Scope* for_scope = scope_;
|
| ZoneList<Variable*> temps(names->length(), zone());
|
|
|
| Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false,
|
| @@ -3370,150 +3369,156 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| ForStatement* outer_loop =
|
| factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
|
| outer_block->statements()->Add(outer_loop, zone());
|
| -
|
| - outer_block->set_scope(for_scope);
|
| - scope_ = inner_scope;
|
| + outer_block->set_scope(scope_);
|
|
|
| Block* inner_block =
|
| factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
|
| - Block* ignore_completion_block = factory()->NewBlock(
|
| - NULL, names->length() + 3, true, RelocInfo::kNoPosition);
|
| - ZoneList<Variable*> inner_vars(names->length(), zone());
|
| - // For each let variable x:
|
| - // make statement: let/const x = temp_x.
|
| - VariableMode mode = is_const ? CONST : LET;
|
| - for (int i = 0; i < names->length(); i++) {
|
| - VariableProxy* proxy = NewUnresolved(names->at(i), mode);
|
| - Declaration* declaration = factory()->NewVariableDeclaration(
|
| - proxy, mode, scope_, RelocInfo::kNoPosition);
|
| - Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| - inner_vars.Add(declaration->proxy()->var(), zone());
|
| - VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
|
| - Assignment* assignment = factory()->NewAssignment(
|
| - Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition);
|
| - Statement* assignment_statement =
|
| - factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
|
| - DCHECK(init->position() != RelocInfo::kNoPosition);
|
| - proxy->var()->set_initializer_position(init->position());
|
| - ignore_completion_block->statements()->Add(assignment_statement, zone());
|
| - }
|
| + {
|
| + BlockState block_state(&scope_, inner_scope);
|
|
|
| - // Make statement: if (first == 1) { first = 0; } else { next; }
|
| - if (next) {
|
| - DCHECK(first);
|
| - Expression* compare = NULL;
|
| - // Make compare expression: first == 1.
|
| - {
|
| - Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
|
| - VariableProxy* first_proxy = factory()->NewVariableProxy(first);
|
| - compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
|
| - RelocInfo::kNoPosition);
|
| - }
|
| - Statement* clear_first = NULL;
|
| - // Make statement: first = 0.
|
| - {
|
| - VariableProxy* first_proxy = factory()->NewVariableProxy(first);
|
| - Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
|
| + Block* ignore_completion_block = factory()->NewBlock(
|
| + NULL, names->length() + 3, true, RelocInfo::kNoPosition);
|
| + ZoneList<Variable*> inner_vars(names->length(), zone());
|
| + // For each let variable x:
|
| + // make statement: let/const x = temp_x.
|
| + VariableMode mode = is_const ? CONST : LET;
|
| + for (int i = 0; i < names->length(); i++) {
|
| + VariableProxy* proxy = NewUnresolved(names->at(i), mode);
|
| + Declaration* declaration = factory()->NewVariableDeclaration(
|
| + proxy, mode, scope_, RelocInfo::kNoPosition);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + inner_vars.Add(declaration->proxy()->var(), zone());
|
| + VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
|
| Assignment* assignment = factory()->NewAssignment(
|
| - Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition);
|
| - clear_first =
|
| + Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition);
|
| + Statement* assignment_statement =
|
| factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
|
| + DCHECK(init->position() != RelocInfo::kNoPosition);
|
| + proxy->var()->set_initializer_position(init->position());
|
| + ignore_completion_block->statements()->Add(assignment_statement, zone());
|
| }
|
| - Statement* clear_first_or_next = factory()->NewIfStatement(
|
| - compare, clear_first, next, RelocInfo::kNoPosition);
|
| - ignore_completion_block->statements()->Add(clear_first_or_next, zone());
|
| - }
|
|
|
| - Variable* flag = scope_->NewTemporary(temp_name);
|
| - // Make statement: flag = 1.
|
| - {
|
| - VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
|
| - Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
|
| - Assignment* assignment = factory()->NewAssignment(
|
| - Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
|
| - Statement* assignment_statement =
|
| - factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
|
| - ignore_completion_block->statements()->Add(assignment_statement, zone());
|
| - }
|
| + // Make statement: if (first == 1) { first = 0; } else { next; }
|
| + if (next) {
|
| + DCHECK(first);
|
| + Expression* compare = NULL;
|
| + // Make compare expression: first == 1.
|
| + {
|
| + Expression* const1 =
|
| + factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
|
| + VariableProxy* first_proxy = factory()->NewVariableProxy(first);
|
| + compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
|
| + RelocInfo::kNoPosition);
|
| + }
|
| + Statement* clear_first = NULL;
|
| + // Make statement: first = 0.
|
| + {
|
| + VariableProxy* first_proxy = factory()->NewVariableProxy(first);
|
| + Expression* const0 =
|
| + factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
|
| + Assignment* assignment = factory()->NewAssignment(
|
| + Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition);
|
| + clear_first = factory()->NewExpressionStatement(assignment,
|
| + RelocInfo::kNoPosition);
|
| + }
|
| + Statement* clear_first_or_next = factory()->NewIfStatement(
|
| + compare, clear_first, next, RelocInfo::kNoPosition);
|
| + ignore_completion_block->statements()->Add(clear_first_or_next, zone());
|
| + }
|
|
|
| - // Make statement: if (!cond) break.
|
| - if (cond) {
|
| - Statement* stop =
|
| - factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
|
| - Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
|
| - ignore_completion_block->statements()->Add(
|
| - factory()->NewIfStatement(cond, noop, stop, cond->position()), zone());
|
| - }
|
| + Variable* flag = scope_->NewTemporary(temp_name);
|
| + // Make statement: flag = 1.
|
| + {
|
| + VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
|
| + Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
|
| + Assignment* assignment = factory()->NewAssignment(
|
| + Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
|
| + Statement* assignment_statement =
|
| + factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
|
| + ignore_completion_block->statements()->Add(assignment_statement, zone());
|
| + }
|
|
|
| - inner_block->statements()->Add(ignore_completion_block, zone());
|
| - // Make cond expression for main loop: flag == 1.
|
| - Expression* flag_cond = NULL;
|
| - {
|
| - Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
|
| - VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
|
| - flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
|
| - RelocInfo::kNoPosition);
|
| - }
|
| + // Make statement: if (!cond) break.
|
| + if (cond) {
|
| + Statement* stop =
|
| + factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
|
| + Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
|
| + ignore_completion_block->statements()->Add(
|
| + factory()->NewIfStatement(cond, noop, stop, cond->position()),
|
| + zone());
|
| + }
|
|
|
| - // Create chain of expressions "flag = 0, temp_x = x, ..."
|
| - Statement* compound_next_statement = NULL;
|
| - {
|
| - Expression* compound_next = NULL;
|
| - // Make expression: flag = 0.
|
| + inner_block->statements()->Add(ignore_completion_block, zone());
|
| + // Make cond expression for main loop: flag == 1.
|
| + Expression* flag_cond = NULL;
|
| {
|
| + Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
|
| VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
|
| - Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
|
| - compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy,
|
| - const0, RelocInfo::kNoPosition);
|
| + flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
|
| + RelocInfo::kNoPosition);
|
| }
|
|
|
| - // Make the comma-separated list of temp_x = x assignments.
|
| - int inner_var_proxy_pos = scanner()->location().beg_pos;
|
| - for (int i = 0; i < names->length(); i++) {
|
| - VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
|
| - VariableProxy* proxy =
|
| - factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
|
| - Assignment* assignment = factory()->NewAssignment(
|
| - Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
|
| - compound_next = factory()->NewBinaryOperation(
|
| - Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition);
|
| - }
|
| + // Create chain of expressions "flag = 0, temp_x = x, ..."
|
| + Statement* compound_next_statement = NULL;
|
| + {
|
| + Expression* compound_next = NULL;
|
| + // Make expression: flag = 0.
|
| + {
|
| + VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
|
| + Expression* const0 =
|
| + factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
|
| + compound_next = factory()->NewAssignment(
|
| + Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
|
| + }
|
|
|
| - compound_next_statement = factory()->NewExpressionStatement(
|
| - compound_next, RelocInfo::kNoPosition);
|
| - }
|
| + // Make the comma-separated list of temp_x = x assignments.
|
| + int inner_var_proxy_pos = scanner()->location().beg_pos;
|
| + for (int i = 0; i < names->length(); i++) {
|
| + VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
|
| + VariableProxy* proxy =
|
| + factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
|
| + Assignment* assignment = factory()->NewAssignment(
|
| + Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
|
| + compound_next = factory()->NewBinaryOperation(
|
| + Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition);
|
| + }
|
|
|
| - // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
|
| - // Note that we re-use the original loop node, which retains its labels
|
| - // and ensures that any break or continue statements in body point to
|
| - // the right place.
|
| - loop->Initialize(NULL, flag_cond, compound_next_statement, body);
|
| - inner_block->statements()->Add(loop, zone());
|
| + compound_next_statement = factory()->NewExpressionStatement(
|
| + compound_next, RelocInfo::kNoPosition);
|
| + }
|
|
|
| - // Make statement: {{if (flag == 1) break;}}
|
| - {
|
| - Expression* compare = NULL;
|
| - // Make compare expresion: flag == 1.
|
| + // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
|
| + // Note that we re-use the original loop node, which retains its labels
|
| + // and ensures that any break or continue statements in body point to
|
| + // the right place.
|
| + loop->Initialize(NULL, flag_cond, compound_next_statement, body);
|
| + inner_block->statements()->Add(loop, zone());
|
| +
|
| + // Make statement: {{if (flag == 1) break;}}
|
| {
|
| - Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
|
| - VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
|
| - compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
|
| - RelocInfo::kNoPosition);
|
| + Expression* compare = NULL;
|
| + // Make compare expresion: flag == 1.
|
| + {
|
| + Expression* const1 =
|
| + factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
|
| + VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
|
| + compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
|
| + RelocInfo::kNoPosition);
|
| + }
|
| + Statement* stop =
|
| + factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
|
| + Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
|
| + Statement* if_flag_break = factory()->NewIfStatement(
|
| + compare, stop, empty, RelocInfo::kNoPosition);
|
| + Block* ignore_completion_block =
|
| + factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
|
| + ignore_completion_block->statements()->Add(if_flag_break, zone());
|
| + inner_block->statements()->Add(ignore_completion_block, zone());
|
| }
|
| - Statement* stop =
|
| - factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
|
| - Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
|
| - Statement* if_flag_break =
|
| - factory()->NewIfStatement(compare, stop, empty, RelocInfo::kNoPosition);
|
| - Block* ignore_completion_block =
|
| - factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
|
| - ignore_completion_block->statements()->Add(if_flag_break, zone());
|
| - inner_block->statements()->Add(ignore_completion_block, zone());
|
| - }
|
|
|
| - inner_scope->set_end_position(scanner()->location().end_pos);
|
| - inner_block->set_scope(inner_scope);
|
| - scope_ = for_scope;
|
| + inner_scope->set_end_position(scanner()->location().end_pos);
|
| + inner_block->set_scope(inner_scope);
|
| + }
|
|
|
| outer_loop->Initialize(NULL, NULL, NULL, inner_block);
|
| return outer_block;
|
| @@ -3531,9 +3536,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| ZoneList<const AstRawString*> lexical_bindings(1, zone());
|
|
|
| // Create an in-between scope for let-bound iteration variables.
|
| - Scope* saved_scope = scope_;
|
| Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
|
| - scope_ = for_scope;
|
| +
|
| + BlockState block_state(&scope_, for_scope);
|
| Expect(Token::FOR, CHECK_OK);
|
| Expect(Token::LPAREN, CHECK_OK);
|
| for_scope->set_start_position(scanner()->location().beg_pos);
|
| @@ -3616,8 +3621,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| // let x; // for TDZ
|
| // }
|
|
|
| - Variable* temp = scope_->NewTemporary(
|
| - ast_value_factory()->dot_for_string());
|
| + Variable* temp =
|
| + scope_->NewTemporary(ast_value_factory()->dot_for_string());
|
| ForEachStatement* loop =
|
| factory()->NewForEachStatement(mode, labels, stmt_pos);
|
| Target target(&this->target_stack_, loop);
|
| @@ -3628,70 +3633,68 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|
|
| Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
|
| body_scope->set_start_position(scanner()->location().beg_pos);
|
| - scope_ = body_scope;
|
| -
|
| - Statement* body = ParseSubStatement(NULL, CHECK_OK);
|
|
|
| Block* body_block =
|
| factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
|
|
|
| - auto each_initialization_block =
|
| - factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
|
| {
|
| - auto descriptor = parsing_result.descriptor;
|
| - descriptor.declaration_pos = RelocInfo::kNoPosition;
|
| - descriptor.initialization_pos = RelocInfo::kNoPosition;
|
| - decl.initializer = factory()->NewVariableProxy(temp);
|
| + BlockState block_state(&scope_, body_scope);
|
| +
|
| + Statement* body = ParseSubStatement(NULL, CHECK_OK);
|
| +
|
| + auto each_initialization_block =
|
| + factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
|
| + {
|
| + auto descriptor = parsing_result.descriptor;
|
| + descriptor.declaration_pos = RelocInfo::kNoPosition;
|
| + descriptor.initialization_pos = RelocInfo::kNoPosition;
|
| + decl.initializer = factory()->NewVariableProxy(temp);
|
| +
|
| + PatternRewriter::DeclareAndInitializeVariables(
|
| + each_initialization_block, &descriptor, &decl,
|
| + IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
|
| + : nullptr,
|
| + CHECK_OK);
|
| + }
|
|
|
| - PatternRewriter::DeclareAndInitializeVariables(
|
| - each_initialization_block, &descriptor, &decl,
|
| - IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
|
| - : nullptr,
|
| - CHECK_OK);
|
| + body_block->statements()->Add(each_initialization_block, zone());
|
| + body_block->statements()->Add(body, zone());
|
| + VariableProxy* temp_proxy =
|
| + factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
|
| + InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
|
| + false);
|
| }
|
| -
|
| - body_block->statements()->Add(each_initialization_block, zone());
|
| - body_block->statements()->Add(body, zone());
|
| - VariableProxy* temp_proxy =
|
| - factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
|
| - InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
|
| - false);
|
| - scope_ = for_scope;
|
| body_scope->set_end_position(scanner()->location().end_pos);
|
| body_scope = body_scope->FinalizeBlockScope();
|
| - if (body_scope != nullptr) {
|
| body_block->set_scope(body_scope);
|
| - }
|
|
|
| - // Create a TDZ for any lexically-bound names.
|
| - if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
|
| - DCHECK_NULL(init_block);
|
| -
|
| - init_block =
|
| - factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
|
| -
|
| - for (int i = 0; i < lexical_bindings.length(); ++i) {
|
| - // TODO(adamk): This needs to be some sort of special
|
| - // INTERNAL variable that's invisible to the debugger
|
| - // but visible to everything else.
|
| - VariableProxy* tdz_proxy = NewUnresolved(lexical_bindings[i], LET);
|
| - Declaration* tdz_decl = factory()->NewVariableDeclaration(
|
| - tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
|
| - Variable* tdz_var = Declare(tdz_decl, DeclarationDescriptor::NORMAL,
|
| - true, CHECK_OK);
|
| - tdz_var->set_initializer_position(position());
|
| + // Create a TDZ for any lexically-bound names.
|
| + if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
|
| + DCHECK_NULL(init_block);
|
| +
|
| + init_block =
|
| + factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
|
| +
|
| + for (int i = 0; i < lexical_bindings.length(); ++i) {
|
| + // TODO(adamk): This needs to be some sort of special
|
| + // INTERNAL variable that's invisible to the debugger
|
| + // but visible to everything else.
|
| + VariableProxy* tdz_proxy =
|
| + NewUnresolved(lexical_bindings[i], LET);
|
| + Declaration* tdz_decl = factory()->NewVariableDeclaration(
|
| + tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
|
| + Variable* tdz_var = Declare(
|
| + tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| + tdz_var->set_initializer_position(position());
|
| + }
|
| }
|
| - }
|
|
|
| - scope_ = saved_scope;
|
| for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| // Parsed for-in loop w/ variable declarations.
|
| if (init_block != nullptr) {
|
| init_block->statements()->Add(loop, zone());
|
| - if (for_scope != nullptr) {
|
| - init_block->set_scope(for_scope);
|
| - }
|
| + init_block->set_scope(for_scope);
|
| return init_block;
|
| } else {
|
| DCHECK_NULL(for_scope);
|
| @@ -3748,19 +3751,16 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| // expressions in head of the loop should actually have variables
|
| // resolved in the outer scope.
|
| Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE);
|
| - scope_ = body_scope;
|
| + BlockState block_state(&scope_, body_scope);
|
| Block* block =
|
| factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
|
| Statement* body = ParseSubStatement(NULL, CHECK_OK);
|
| block->statements()->Add(body, zone());
|
| InitializeForEachStatement(loop, expression, enumerable, block,
|
| is_destructuring);
|
| - scope_ = saved_scope;
|
| body_scope->set_end_position(scanner()->location().end_pos);
|
| body_scope = body_scope->FinalizeBlockScope();
|
| - if (body_scope != nullptr) {
|
| - block->set_scope(body_scope);
|
| - }
|
| + block->set_scope(body_scope);
|
| for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| DCHECK(for_scope == nullptr);
|
| @@ -3787,40 +3787,42 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| }
|
| Expect(Token::SEMICOLON, CHECK_OK);
|
|
|
| + Expression* cond = NULL;
|
| + Statement* next = NULL;
|
| + Statement* body = NULL;
|
| +
|
| // If there are let bindings, then condition and the next statement of the
|
| // for loop must be parsed in a new scope.
|
| - Scope* inner_scope = NULL;
|
| + Scope* inner_scope = scope_;
|
| if (lexical_bindings.length() > 0) {
|
| inner_scope = NewScope(for_scope, BLOCK_SCOPE);
|
| inner_scope->set_start_position(scanner()->location().beg_pos);
|
| - scope_ = inner_scope;
|
| }
|
| + {
|
| + BlockState block_state(&scope_, inner_scope);
|
|
|
| - Expression* cond = NULL;
|
| - if (peek() != Token::SEMICOLON) {
|
| - cond = ParseExpression(true, CHECK_OK);
|
| - }
|
| - Expect(Token::SEMICOLON, CHECK_OK);
|
| + if (peek() != Token::SEMICOLON) {
|
| + cond = ParseExpression(true, CHECK_OK);
|
| + }
|
| + Expect(Token::SEMICOLON, CHECK_OK);
|
|
|
| - Statement* next = NULL;
|
| - if (peek() != Token::RPAREN) {
|
| - Expression* exp = ParseExpression(true, CHECK_OK);
|
| - next = factory()->NewExpressionStatement(exp, exp->position());
|
| - }
|
| - Expect(Token::RPAREN, CHECK_OK);
|
| + if (peek() != Token::RPAREN) {
|
| + Expression* exp = ParseExpression(true, CHECK_OK);
|
| + next = factory()->NewExpressionStatement(exp, exp->position());
|
| + }
|
| + Expect(Token::RPAREN, CHECK_OK);
|
|
|
| - Statement* body = ParseSubStatement(NULL, CHECK_OK);
|
| + body = ParseSubStatement(NULL, CHECK_OK);
|
| + }
|
|
|
| Statement* result = NULL;
|
| if (lexical_bindings.length() > 0) {
|
| - scope_ = for_scope;
|
| + BlockState block_state(&scope_, for_scope);
|
| result = DesugarLexicalBindingsInForStatement(
|
| inner_scope, is_const, &lexical_bindings, loop, init, cond,
|
| next, body, CHECK_OK);
|
| - scope_ = saved_scope;
|
| for_scope->set_end_position(scanner()->location().end_pos);
|
| } else {
|
| - scope_ = saved_scope;
|
| for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| if (for_scope) {
|
|
|