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

Unified Diff: src/parsing/parser-base.h

Issue 2645353002: [parser] Refactor ParseForStatement. (Closed)
Patch Set: code review (adamk@ and uninitialized value fix) Created 3 years, 11 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser-base.h
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index eade9a7402a4b7200e286d8b1f9067bbe6a88e5e..7db2d4a7f44a08315332472fd467c269b4ee3077 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -1302,6 +1302,20 @@ class ParserBase {
bool* ok);
StatementT ParseTryStatement(bool* ok);
StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
+ StatementT ParseForEachStatementWithDeclarations(
+ int stmt_pos, ForInfo* for_info, BlockState* for_state,
+ ZoneList<const AstRawString*>* labels, bool* ok);
+ StatementT ParseForEachStatementWithoutDeclarations(
+ int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
+ ForInfo* for_info, BlockState* for_state,
+ ZoneList<const AstRawString*>* labels, bool* ok);
+
+ // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }'
+ StatementT ParseStandardForLoop(int stmt_pos, StatementT init,
+ bool bound_names_are_lexical,
+ ForInfo* for_info, BlockState* for_state,
+ ZoneList<const AstRawString*>* labels,
+ bool* ok);
bool IsNextLetKeyword();
bool IsTrivialExpression();
@@ -5380,173 +5394,193 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
for_state.set_is_hidden();
StatementT init = impl()->NullStatement();
- if (peek() != Token::SEMICOLON) {
- // An initializer is present.
- if (peek() == Token::VAR || peek() == Token::CONST ||
- (peek() == Token::LET && IsNextLetKeyword())) {
- // The initializer contains declarations.
- ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
- nullptr, CHECK_OK);
- bound_names_are_lexical =
- IsLexicalVariableMode(for_info.parsing_result.descriptor.mode);
- for_info.position = scanner()->location().beg_pos;
-
- if (CheckInOrOf(&for_info.mode)) {
- // Just one declaration followed by in/of.
- if (for_info.parsing_result.declarations.length() != 1) {
- impl()->ReportMessageAt(
- for_info.parsing_result.bindings_loc,
- MessageTemplate::kForInOfLoopMultiBindings,
- ForEachStatement::VisitModeString(for_info.mode));
- *ok = false;
- return impl()->NullStatement();
- }
- if (for_info.parsing_result.first_initializer_loc.IsValid() &&
- (is_strict(language_mode()) ||
- for_info.mode == ForEachStatement::ITERATE ||
- bound_names_are_lexical ||
- !impl()->IsIdentifier(
- for_info.parsing_result.declarations[0].pattern))) {
- impl()->ReportMessageAt(
- for_info.parsing_result.first_initializer_loc,
- MessageTemplate::kForInOfLoopInitializer,
- ForEachStatement::VisitModeString(for_info.mode));
- *ok = false;
- return impl()->NullStatement();
- }
- BlockT init_block = impl()->RewriteForVarInLegacy(for_info);
+ if (peek() == Token::VAR || peek() == Token::CONST ||
+ (peek() == Token::LET && IsNextLetKeyword())) {
+ // The initializer contains declarations.
+ ParseVariableDeclarations(kForStatement, &for_info.parsing_result, nullptr,
+ CHECK_OK);
+ bound_names_are_lexical =
+ IsLexicalVariableMode(for_info.parsing_result.descriptor.mode);
+ for_info.position = scanner()->location().beg_pos;
+
+ if (CheckInOrOf(&for_info.mode)) {
+ return ParseForEachStatementWithDeclarations(stmt_pos, &for_info,
+ &for_state, labels, ok);
+ }
+
+ // One or more declaration not followed by in/of.
+ init = impl()->BuildInitializationBlock(
+ &for_info.parsing_result,
+ bound_names_are_lexical ? &for_info.bound_names : nullptr, CHECK_OK);
+ } else if (peek() != Token::SEMICOLON) {
+ // The initializer does not contain declarations.
+ int lhs_beg_pos = peek_position();
+ ExpressionClassifier classifier(this);
+ ExpressionT expression = ParseExpressionCoverGrammar(false, CHECK_OK);
+ int lhs_end_pos = scanner()->location().end_pos;
+
+ bool is_for_each = CheckInOrOf(&for_info.mode);
+ bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
+ expression->IsObjectLiteral());
+
+ if (is_destructuring) {
+ ValidateAssignmentPattern(CHECK_OK);
+ } else {
+ impl()->RewriteNonPattern(CHECK_OK);
+ }
- auto loop =
- factory()->NewForEachStatement(for_info.mode, labels, stmt_pos);
- typename Types::Target target(this, loop);
+ if (is_for_each) {
+ return ParseForEachStatementWithoutDeclarations(
+ stmt_pos, expression, lhs_beg_pos, lhs_end_pos, &for_info, &for_state,
+ labels, ok);
+ }
+ // Initializer is just an expression.
+ init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
+ }
- int each_keyword_pos = scanner()->location().beg_pos;
+ // Standard 'for' loop, we have parsed the initializer at this point.
+ return ParseStandardForLoop(stmt_pos, init, bound_names_are_lexical,
+ &for_info, &for_state, labels, ok);
+}
- ExpressionT enumerable = impl()->EmptyExpression();
- if (for_info.mode == ForEachStatement::ITERATE) {
- ExpressionClassifier classifier(this);
- enumerable = ParseAssignmentExpression(true, CHECK_OK);
- impl()->RewriteNonPattern(CHECK_OK);
- } else {
- enumerable = ParseExpression(true, CHECK_OK);
- }
+template <typename Impl>
+typename ParserBase<Impl>::StatementT
+ParserBase<Impl>::ParseForEachStatementWithDeclarations(
+ int stmt_pos, ForInfo* for_info, BlockState* for_state,
+ ZoneList<const AstRawString*>* labels, bool* ok) {
+ // Just one declaration followed by in/of.
+ if (for_info->parsing_result.declarations.length() != 1) {
+ impl()->ReportMessageAt(for_info->parsing_result.bindings_loc,
+ MessageTemplate::kForInOfLoopMultiBindings,
+ ForEachStatement::VisitModeString(for_info->mode));
+ *ok = false;
+ return impl()->NullStatement();
+ }
+ if (for_info->parsing_result.first_initializer_loc.IsValid() &&
+ (is_strict(language_mode()) ||
+ for_info->mode == ForEachStatement::ITERATE ||
+ IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
+ !impl()->IsIdentifier(
+ for_info->parsing_result.declarations[0].pattern))) {
+ impl()->ReportMessageAt(for_info->parsing_result.first_initializer_loc,
+ MessageTemplate::kForInOfLoopInitializer,
+ ForEachStatement::VisitModeString(for_info->mode));
+ *ok = false;
+ return impl()->NullStatement();
+ }
- Expect(Token::RPAREN, CHECK_OK);
+ BlockT init_block = impl()->RewriteForVarInLegacy(*for_info);
- StatementT final_loop = impl()->NullStatement();
- {
- ReturnExprScope no_tail_calls(function_state_,
- ReturnExprContext::kInsideForInOfBody);
- BlockState block_state(zone(), &scope_state_);
- block_state.set_start_position(scanner()->location().beg_pos);
-
- StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
-
- BlockT body_block = impl()->NullBlock();
- ExpressionT each_variable = impl()->EmptyExpression();
- impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
- &each_variable, CHECK_OK);
- body_block->statements()->Add(body, zone());
- final_loop = impl()->InitializeForEachStatement(
- loop, each_variable, enumerable, body_block, each_keyword_pos);
-
- block_state.set_end_position(scanner()->location().end_pos);
- body_block->set_scope(block_state.FinalizedBlockScope());
- }
+ auto loop = factory()->NewForEachStatement(for_info->mode, labels, stmt_pos);
+ typename Types::Target target(this, loop);
- init_block =
- impl()->CreateForEachStatementTDZ(init_block, for_info, ok);
+ int each_keyword_pos = scanner()->location().beg_pos;
- for_state.set_end_position(scanner()->location().end_pos);
- Scope* for_scope = for_state.FinalizedBlockScope();
- // Parsed for-in loop w/ variable declarations.
- if (!impl()->IsNullStatement(init_block)) {
- init_block->statements()->Add(final_loop, zone());
- init_block->set_scope(for_scope);
- return init_block;
- } else {
- DCHECK_NULL(for_scope);
- return final_loop;
- }
- } else {
- // One or more declaration not followed by in/of.
- init = impl()->BuildInitializationBlock(
- &for_info.parsing_result,
- bound_names_are_lexical ? &for_info.bound_names : nullptr,
- CHECK_OK);
- }
- } else {
- // The initializer does not contain declarations.
- int lhs_beg_pos = peek_position();
- ExpressionClassifier classifier(this);
- ExpressionT expression = ParseExpressionCoverGrammar(false, CHECK_OK);
- int lhs_end_pos = scanner()->location().end_pos;
+ ExpressionT enumerable = impl()->EmptyExpression();
+ if (for_info->mode == ForEachStatement::ITERATE) {
+ ExpressionClassifier classifier(this);
+ enumerable = ParseAssignmentExpression(true, CHECK_OK);
+ impl()->RewriteNonPattern(CHECK_OK);
+ } else {
+ enumerable = ParseExpression(true, CHECK_OK);
+ }
- bool is_for_each = CheckInOrOf(&for_info.mode);
- bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
- expression->IsObjectLiteral());
+ Expect(Token::RPAREN, CHECK_OK);
- if (is_destructuring) {
- ValidateAssignmentPattern(CHECK_OK);
- } else {
- impl()->RewriteNonPattern(CHECK_OK);
- }
+ StatementT final_loop = impl()->NullStatement();
+ {
+ ReturnExprScope no_tail_calls(function_state_,
+ ReturnExprContext::kInsideForInOfBody);
+ BlockState block_state(zone(), &scope_state_);
+ block_state.set_start_position(scanner()->location().beg_pos);
- if (is_for_each) {
- // Initializer is reference followed by in/of.
- if (!is_destructuring) {
- expression = impl()->CheckAndRewriteReferenceExpression(
- expression, lhs_beg_pos, lhs_end_pos,
- MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK);
- }
+ StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
- auto loop =
- factory()->NewForEachStatement(for_info.mode, labels, stmt_pos);
- typename Types::Target target(this, loop);
+ BlockT body_block = impl()->NullBlock();
+ ExpressionT each_variable = impl()->EmptyExpression();
+ impl()->DesugarBindingInForEachStatement(for_info, &body_block,
+ &each_variable, CHECK_OK);
+ body_block->statements()->Add(body, zone());
+ final_loop = impl()->InitializeForEachStatement(
+ loop, each_variable, enumerable, body_block, each_keyword_pos);
- int each_keyword_pos = scanner()->location().beg_pos;
+ block_state.set_end_position(scanner()->location().end_pos);
+ body_block->set_scope(block_state.FinalizedBlockScope());
+ }
- ExpressionT enumerable = impl()->EmptyExpression();
- if (for_info.mode == ForEachStatement::ITERATE) {
- ExpressionClassifier classifier(this);
- enumerable = ParseAssignmentExpression(true, CHECK_OK);
- impl()->RewriteNonPattern(CHECK_OK);
- } else {
- enumerable = ParseExpression(true, CHECK_OK);
- }
+ init_block = impl()->CreateForEachStatementTDZ(init_block, *for_info, ok);
- Expect(Token::RPAREN, CHECK_OK);
+ for_state->set_end_position(scanner()->location().end_pos);
+ Scope* for_scope = for_state->FinalizedBlockScope();
+ // Parsed for-in loop w/ variable declarations.
+ if (!impl()->IsNullStatement(init_block)) {
+ init_block->statements()->Add(final_loop, zone());
+ init_block->set_scope(for_scope);
+ return init_block;
+ }
- {
- ReturnExprScope no_tail_calls(function_state_,
- ReturnExprContext::kInsideForInOfBody);
- BlockState block_state(zone(), &scope_state_);
- block_state.set_start_position(scanner()->location().beg_pos);
-
- // For legacy compat reasons, give for loops similar treatment to
- // if statements in allowing a function declaration for a body
- StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
- block_state.set_end_position(scanner()->location().end_pos);
- StatementT final_loop = impl()->InitializeForEachStatement(
- loop, expression, enumerable, body, each_keyword_pos);
-
- Scope* for_scope = for_state.FinalizedBlockScope();
- DCHECK_NULL(for_scope);
- USE(for_scope);
- Scope* block_scope = block_state.FinalizedBlockScope();
- DCHECK_NULL(block_scope);
- USE(block_scope);
- return final_loop;
- }
- } else {
- // Initializer is just an expression.
- init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
- }
- }
+ DCHECK_NULL(for_scope);
+ return final_loop;
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::StatementT
+ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
+ int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
+ ForInfo* for_info, BlockState* for_state,
+ ZoneList<const AstRawString*>* labels, bool* ok) {
+ // Initializer is reference followed by in/of.
+ if (!expression->IsArrayLiteral() && !expression->IsObjectLiteral()) {
+ expression = impl()->CheckAndRewriteReferenceExpression(
+ expression, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
+ kSyntaxError, CHECK_OK);
}
- // Standard 'for' loop, we have parsed the initializer at this point.
+ auto loop = factory()->NewForEachStatement(for_info->mode, labels, stmt_pos);
+ typename Types::Target target(this, loop);
+
+ int each_keyword_pos = scanner()->location().beg_pos;
+
+ ExpressionT enumerable = impl()->EmptyExpression();
+ if (for_info->mode == ForEachStatement::ITERATE) {
+ ExpressionClassifier classifier(this);
+ enumerable = ParseAssignmentExpression(true, CHECK_OK);
+ impl()->RewriteNonPattern(CHECK_OK);
+ } else {
+ enumerable = ParseExpression(true, CHECK_OK);
+ }
+
+ Expect(Token::RPAREN, CHECK_OK);
+
+ {
+ ReturnExprScope no_tail_calls(function_state_,
+ ReturnExprContext::kInsideForInOfBody);
+ BlockState block_state(zone(), &scope_state_);
+ block_state.set_start_position(scanner()->location().beg_pos);
+
+ // For legacy compat reasons, give for loops similar treatment to
+ // if statements in allowing a function declaration for a body
+ StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
+ block_state.set_end_position(scanner()->location().end_pos);
+ StatementT final_loop = impl()->InitializeForEachStatement(
+ loop, expression, enumerable, body, each_keyword_pos);
+
+ Scope* for_scope = for_state->FinalizedBlockScope();
+ DCHECK_NULL(for_scope);
+ USE(for_scope);
+ Scope* block_scope = block_state.FinalizedBlockScope();
+ DCHECK_NULL(block_scope);
+ USE(block_scope);
+ return final_loop;
+ }
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStandardForLoop(
+ int stmt_pos, StatementT init, bool bound_names_are_lexical,
+ ForInfo* for_info, BlockState* for_state,
+ ZoneList<const AstRawString*>* labels, bool* ok) {
auto loop = factory()->NewForStatement(labels, stmt_pos);
typename Types::Target target(this, loop);
@@ -5560,7 +5594,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
// for loop must be parsed in a new scope.
Scope* inner_scope = scope();
// TODO(verwaest): Allocate this through a ScopeState as well.
- if (bound_names_are_lexical && for_info.bound_names.length() > 0) {
+ if (bound_names_are_lexical && for_info->bound_names.length() > 0) {
inner_scope = NewScopeWithParent(inner_scope, BLOCK_SCOPE);
inner_scope->set_start_position(scanner()->location().beg_pos);
}
@@ -5581,46 +5615,46 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
body = ParseScopedStatement(nullptr, true, CHECK_OK);
}
- if (bound_names_are_lexical && for_info.bound_names.length() > 0) {
+ if (bound_names_are_lexical && for_info->bound_names.length() > 0) {
auto result = impl()->DesugarLexicalBindingsInForStatement(
- loop, init, cond, next, body, inner_scope, for_info, CHECK_OK);
- for_state.set_end_position(scanner()->location().end_pos);
+ loop, init, cond, next, body, inner_scope, *for_info, CHECK_OK);
+ for_state->set_end_position(scanner()->location().end_pos);
return result;
- } else {
- for_state.set_end_position(scanner()->location().end_pos);
- Scope* for_scope = for_state.FinalizedBlockScope();
- if (for_scope != nullptr) {
- // Rewrite a for statement of the form
- // for (const x = i; c; n) b
- //
- // into
- //
- // {
- // const x = i;
- // for (; c; n) b
- // }
- //
- // or, desugar
- // for (; c; n) b
- // into
- // {
- // for (; c; n) b
- // }
- // just in case b introduces a lexical binding some other way, e.g., if b
- // is a FunctionDeclaration.
- BlockT block = factory()->NewBlock(nullptr, 2, false, kNoSourcePosition);
- if (!impl()->IsNullStatement(init)) {
- block->statements()->Add(init, zone());
- }
- block->statements()->Add(loop, zone());
- block->set_scope(for_scope);
- loop->Initialize(init, cond, next, body);
- return block;
- } else {
- loop->Initialize(init, cond, next, body);
- return loop;
- }
}
+
+ for_state->set_end_position(scanner()->location().end_pos);
+ Scope* for_scope = for_state->FinalizedBlockScope();
+ if (for_scope != nullptr) {
+ // Rewrite a for statement of the form
+ // for (const x = i; c; n) b
+ //
+ // into
+ //
+ // {
+ // const x = i;
+ // for (; c; n) b
+ // }
+ //
+ // or, desugar
+ // for (; c; n) b
+ // into
+ // {
+ // for (; c; n) b
+ // }
+ // just in case b introduces a lexical binding some other way, e.g., if b
+ // is a FunctionDeclaration.
+ BlockT block = factory()->NewBlock(nullptr, 2, false, kNoSourcePosition);
+ if (!impl()->IsNullStatement(init)) {
+ block->statements()->Add(init, zone());
+ }
+ block->statements()->Add(loop, zone());
+ block->set_scope(for_scope);
+ loop->Initialize(init, cond, next, body);
+ return block;
+ }
+
+ loop->Initialize(init, cond, next, body);
+ return loop;
}
#undef CHECK_OK
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698