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

Unified Diff: src/parser.cc

Issue 1149043005: [destructuring] Grand for statement parsing unification. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase feedback Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/pattern-rewriter.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index b9d2c2f9e7df66c6e5e0feebf727001aac2915be..ee0f7dc6804848109197ed9878835d791e3d77f4 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2295,8 +2295,8 @@ const AstRawString* Parser::DeclarationParsingResult::SingleName() const {
Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
ZoneList<const AstRawString*>* names, bool* ok) {
- Block* result =
- descriptor.parser->factory()->NewBlock(NULL, 1, true, descriptor.pos);
+ Block* result = descriptor.parser->factory()->NewBlock(
+ NULL, 1, true, descriptor.declaration_pos);
for (auto declaration : declarations) {
PatternRewriter::DeclareAndInitializeVariables(
result, &descriptor, &declaration, names, CHECK_OK);
@@ -2350,7 +2350,8 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
// BindingPattern '=' AssignmentExpression
parsing_result->descriptor.parser = this;
- parsing_result->descriptor.pos = peek_position();
+ parsing_result->descriptor.declaration_pos = peek_position();
+ parsing_result->descriptor.initialization_pos = peek_position();
parsing_result->descriptor.mode = VAR;
// True if the binding needs initialization. 'let' and 'const' declared
// bindings are created uninitialized by their declaration nodes and
@@ -3417,11 +3418,10 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
bool is_let_identifier_expression = false;
DeclarationParsingResult parsing_result;
if (peek() != Token::SEMICOLON) {
- if (peek() == Token::VAR ||
- (peek() == Token::CONST && is_sloppy(language_mode()))) {
+ if (peek() == Token::VAR || peek() == Token::CONST ||
+ (peek() == Token::LET && is_strict(language_mode()))) {
ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
- Block* variable_statement =
- parsing_result.BuildInitializationBlock(nullptr, CHECK_OK);
+ is_const = parsing_result.descriptor.mode == CONST;
int num_decl = parsing_result.declarations.length();
bool accept_IN = num_decl >= 1;
@@ -3454,124 +3454,100 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
*ok = false;
return nullptr;
}
- ForEachStatement* loop =
- factory()->NewForEachStatement(mode, labels, stmt_pos);
- Target target(&this->target_stack_, loop);
- Expression* enumerable = ParseExpression(true, CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
-
- VariableProxy* each =
- scope_->NewUnresolved(factory(), parsing_result.SingleName(),
- Variable::NORMAL, each_beg_pos, each_end_pos);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
- InitializeForEachStatement(loop, each, enumerable, body);
- Block* result =
- factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
- result->AddStatement(variable_statement, zone());
- result->AddStatement(loop, zone());
- scope_ = saved_scope;
- for_scope->set_end_position(scanner()->location().end_pos);
- for_scope = for_scope->FinalizeBlockScope();
- DCHECK(for_scope == NULL);
- // Parsed for-in loop w/ variable/const declaration.
- return result;
- } else {
- init = variable_statement;
- }
- } else if ((peek() == Token::LET || peek() == Token::CONST) &&
- is_strict(language_mode())) {
- is_const = peek() == Token::CONST;
- ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
- DCHECK(parsing_result.descriptor.pos != RelocInfo::kNoPosition);
-
- int num_decl = parsing_result.declarations.length();
- bool accept_IN = num_decl >= 1;
- bool accept_OF = true;
- ForEachStatement::VisitMode mode;
- int each_beg_pos = scanner()->location().beg_pos;
- int each_end_pos = scanner()->location().end_pos;
-
- if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
- if (!*ok) return nullptr;
- if (num_decl != 1) {
- const char* loop_type =
- mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
- ParserTraits::ReportMessageAt(
- parsing_result.bindings_loc,
- MessageTemplate::kForInOfLoopMultiBindings, loop_type);
- *ok = false;
- return nullptr;
- }
- if (parsing_result.first_initializer_loc.IsValid() &&
- (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
- if (mode == ForEachStatement::ITERATE) {
- ReportMessageAt(parsing_result.first_initializer_loc,
- MessageTemplate::kForOfLoopInitializer);
- } else {
- ReportMessageAt(parsing_result.first_initializer_loc,
- MessageTemplate::kForInLoopInitializer);
- }
- *ok = false;
- return nullptr;
+ DCHECK(parsing_result.declarations.length() == 1);
+ Block* init_block = nullptr;
+
+ // special case for legacy for (var/const x =.... in)
+ if (is_sloppy(language_mode()) &&
+ !IsLexicalVariableMode(parsing_result.descriptor.mode) &&
+ parsing_result.declarations[0].initializer != nullptr) {
+ VariableProxy* single_var = scope_->NewUnresolved(
+ factory(), parsing_result.SingleName(), Variable::NORMAL,
+ each_beg_pos, each_end_pos);
+ init_block = factory()->NewBlock(
+ nullptr, 2, true, parsing_result.descriptor.declaration_pos);
+ init_block->AddStatement(
+ factory()->NewExpressionStatement(
+ factory()->NewAssignment(
+ Token::ASSIGN, single_var,
+ parsing_result.declarations[0].initializer,
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ zone());
}
- // Rewrite a for-in statement of the form
+
+ // Rewrite a for-in/of statement of the form
//
- // for (let/const x in e) b
+ // for (let/const/var x in/of e) b
//
// into
//
// <let x' be a temporary variable>
- // for (x' in e) {
- // let/const x;
+ // for (x' in/of e) {
+ // let/const/var x;
// x = x';
// b;
// }
- // TODO(keuchel): Move the temporary variable to the block scope, after
- // implementing stack allocated block scoped variables.
Variable* temp = scope_->DeclarationScope()->NewTemporary(
ast_value_factory()->dot_for_string());
- VariableProxy* temp_proxy =
- factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, stmt_pos);
Target target(&this->target_stack_, loop);
- // The expression does not see the loop variable.
+ // The expression does not see the lexical loop variables.
scope_ = saved_scope;
Expression* enumerable = ParseExpression(true, CHECK_OK);
scope_ = for_scope;
Expect(Token::RPAREN, CHECK_OK);
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, parsing_result.descriptor.pos);
+ auto each_initialization_block =
+ factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
{
DCHECK(parsing_result.declarations.length() == 1);
DeclarationParsingResult::Declaration decl =
parsing_result.declarations[0];
- decl.initializer = temp_proxy;
+ auto descriptor = parsing_result.descriptor;
+ descriptor.declaration_pos = RelocInfo::kNoPosition;
+ decl.initializer = factory()->NewVariableProxy(temp);
+
PatternRewriter::DeclareAndInitializeVariables(
- each_initialization_block, &parsing_result.descriptor, &decl,
- &lexical_bindings, CHECK_OK);
+ each_initialization_block, &descriptor, &decl,
+ IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
+ : nullptr,
+ CHECK_OK);
}
body_block->AddStatement(each_initialization_block, zone());
body_block->AddStatement(body, zone());
+ VariableProxy* temp_proxy =
+ factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
scope_ = saved_scope;
for_scope->set_end_position(scanner()->location().end_pos);
for_scope = for_scope->FinalizeBlockScope();
- body_block->set_scope(for_scope);
- // Parsed for-in loop w/ let declaration.
- return loop;
+ if (for_scope != nullptr) {
+ body_block->set_scope(for_scope);
+ }
+ // Parsed for-in loop w/ variable declarations.
+ if (init_block != nullptr) {
+ init_block->AddStatement(loop, zone());
+ return init_block;
+ } else {
+ return loop;
+ }
} else {
- init = parsing_result.BuildInitializationBlock(&lexical_bindings,
- CHECK_OK);
+ init = parsing_result.BuildInitializationBlock(
+ IsLexicalVariableMode(parsing_result.descriptor.mode)
+ ? &lexical_bindings
+ : nullptr,
+ CHECK_OK);
}
} else {
Scanner::Location lhs_location = scanner()->peek_location();
@@ -3579,9 +3555,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
ForEachStatement::VisitMode mode;
bool accept_OF = expression->IsVariableProxy();
is_let_identifier_expression =
- expression->IsVariableProxy() &&
- expression->AsVariableProxy()->raw_name() ==
- ast_value_factory()->let_string();
+ expression->IsVariableProxy() &&
+ expression->AsVariableProxy()->raw_name() ==
+ ast_value_factory()->let_string();
if (CheckInOrOf(accept_OF, &mode, ok)) {
if (!*ok) return nullptr;
« no previous file with comments | « src/parser.h ('k') | src/pattern-rewriter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698