[parser cleanup] Use BlockState consistently in Parser
This avoids manual, fragile assignment to Parser::scope_. And once all such assignments are removed, BlockState might become much more valuable as a place to reset scope-related state. Also remove unnecessary nullptr checks after calls to FinalizeBlockScope. Review URL: https://codereview.chromium.org/1583453003 Cr-Commit-Position: refs/heads/master@{#33313}
This commit is contained in:
parent
e13f2ff40b
commit
f17e9adf99
@ -3328,7 +3328,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,
|
||||
@ -3381,150 +3380,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());
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
BlockState block_state(&scope_, inner_scope);
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Make the comma-separated list of temp_x = x assignments.
|
||||
int inner_var_proxy_pos = scanner()->location().beg_pos;
|
||||
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));
|
||||
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);
|
||||
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());
|
||||
}
|
||||
|
||||
compound_next_statement = factory()->NewExpressionStatement(
|
||||
compound_next, RelocInfo::kNoPosition);
|
||||
}
|
||||
// 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: 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());
|
||||
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 (flag == 1) break;}}
|
||||
{
|
||||
Expression* compare = NULL;
|
||||
// Make compare expresion: flag == 1.
|
||||
// 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());
|
||||
}
|
||||
|
||||
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);
|
||||
compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
|
||||
RelocInfo::kNoPosition);
|
||||
flag_cond = 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());
|
||||
}
|
||||
|
||||
inner_scope->set_end_position(scanner()->location().end_pos);
|
||||
inner_block->set_scope(inner_scope);
|
||||
scope_ = for_scope;
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
compound_next_statement = factory()->NewExpressionStatement(
|
||||
compound_next, 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());
|
||||
|
||||
// Make statement: {{if (flag == 1) break;}}
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
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;
|
||||
@ -3542,9 +3547,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);
|
||||
@ -3627,8 +3632,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);
|
||||
@ -3639,70 +3644,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);
|
||||
|
||||
PatternRewriter::DeclareAndInitializeVariables(
|
||||
each_initialization_block, &descriptor, &decl,
|
||||
IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
|
||||
: nullptr,
|
||||
CHECK_OK);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
// 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);
|
||||
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());
|
||||
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);
|
||||
@ -3760,19 +3763,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);
|
||||
@ -3799,40 +3799,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);
|
||||
if (peek() != Token::SEMICOLON) {
|
||||
cond = ParseExpression(true, CHECK_OK);
|
||||
}
|
||||
Expect(Token::SEMICOLON, CHECK_OK);
|
||||
|
||||
if (peek() != Token::RPAREN) {
|
||||
Expression* exp = ParseExpression(true, CHECK_OK);
|
||||
next = factory()->NewExpressionStatement(exp, exp->position());
|
||||
}
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
|
||||
body = ParseSubStatement(NULL, 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);
|
||||
|
||||
Statement* 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) {
|
||||
|
Loading…
Reference in New Issue
Block a user