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

Unified Diff: src/parsing/parser.cc

Issue 2351233002: [parser] Refactor of Parse*Statement*, part 8 (Closed)
Patch Set: The real patch Created 4 years, 3 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
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index a406b66ae32490e15c9c66db05696864132cdaf1..a6bd065d92a5f1eddeac4e36bf4a5e2ed1ad615c 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -1995,6 +1995,124 @@ Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt,
return stmt;
}
+// Special case for legacy for (var ... = ... in ...)
marja 2016/09/20 19:36:30 Could this comment also explain what it is rewritt
nickie 2016/09/21 09:20:02 Done, with a bit of reverse-engineering. You may
+Block* Parser::RewriteForVarInLegacy(ForInfo* for_info) {
+ const DeclarationParsingResult::Declaration& decl =
+ for_info->parsing_result.declarations[0];
+ if (!for_info->bound_names_are_lexical && decl.pattern->IsVariableProxy() &&
+ decl.initializer != nullptr) {
+ DCHECK(!allow_harmony_for_in());
+ ++use_counts_[v8::Isolate::kForInInitializer];
+ const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name();
+ VariableProxy* single_var = NewUnresolved(name);
+ Block* init_block = factory()->NewBlock(
+ nullptr, 2, true, for_info->parsing_result.descriptor.declaration_pos);
+ init_block->statements()->Add(
+ factory()->NewExpressionStatement(
+ factory()->NewAssignment(Token::ASSIGN, single_var,
+ decl.initializer, kNoSourcePosition),
+ kNoSourcePosition),
+ zone());
+ return init_block;
+ } else {
marja 2016/09/20 19:36:30 Style nit: else { } around the return is unnecessa
nickie 2016/09/21 09:20:02 Done.
+ return nullptr;
+ }
+}
+
+// Rewrite a for-in/of statement of the form
+//
+// for (let/const/var x in/of e) b
+//
+// into
+//
+// {
+// <let x' be a temporary variable>
+// for (x' in/of e) {
+// let/const/var x;
+// x = x';
+// b;
+// }
+// let x; // for TDZ
+// }
+std::pair<Block*, Expression*> Parser::DesugarBindingInForEachStatement(
+ ForInfo* for_info, bool* ok) {
+ DeclarationParsingResult::Declaration& decl =
+ for_info->parsing_result.declarations[0];
+ Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
+ auto each_initialization_block =
+ factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
+ {
+ auto descriptor = for_info->parsing_result.descriptor;
+ descriptor.declaration_pos = kNoSourcePosition;
+ descriptor.initialization_pos = kNoSourcePosition;
+ decl.initializer = factory()->NewVariableProxy(temp);
+
+ bool is_for_var_of =
+ for_info->mode == ForEachStatement::ITERATE &&
+ for_info->parsing_result.descriptor.mode == VariableMode::VAR;
+
+ PatternRewriter::DeclareAndInitializeVariables(
+ this, each_initialization_block, &descriptor, &decl,
+ (for_info->bound_names_are_lexical || is_for_var_of)
+ ? &for_info->bound_names
+ : nullptr,
+ CHECK_OK_VALUE(std::make_pair(nullptr, nullptr)));
+
+ // Annex B.3.5 prohibits the form
+ // `try {} catch(e) { for (var e of {}); }`
+ // So if we are parsing a statement like `for (var ... of ...)`
+ // we need to walk up the scope chain and look for catch scopes
+ // which have a simple binding, then compare their binding against
+ // all of the names declared in the init of the for-of we're
+ // parsing.
+ if (is_for_var_of) {
+ Scope* catch_scope = scope();
+ while (catch_scope != nullptr && !catch_scope->is_declaration_scope()) {
+ if (catch_scope->is_catch_scope()) {
+ auto name = catch_scope->catch_variable_name();
+ if (name !=
marja 2016/09/20 19:36:30 Style nit: I'd combine these two nested if's: if
nickie 2016/09/21 09:20:02 Done. I think the part "name != ... dot_catch_str
marja 2016/09/21 10:31:42 I was thinking the same, wondering if it's redunda
nickie 2016/09/21 10:33:05 OK, let's play it safe and leave it.
+ ast_value_factory()
+ ->dot_catch_string()) { // i.e. is a simple binding
+ if (for_info->bound_names.Contains(name)) {
+ ReportMessageAt(for_info->parsing_result.bindings_loc,
+ MessageTemplate::kVarRedeclaration, name);
+ *ok = false;
+ return std::make_pair(nullptr, nullptr);
+ }
+ }
+ }
+ catch_scope = catch_scope->outer_scope();
+ }
+ }
+ }
+
+ Block* body_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition);
+ body_block->statements()->Add(each_initialization_block, zone());
+ VariableProxy* temp_proxy = factory()->NewVariableProxy(
+ temp, for_info->each_loc.beg_pos, for_info->each_loc.end_pos);
+ return std::make_pair(body_block, temp_proxy);
+}
+
+// Create a TDZ for any lexically-bound names in for in/of statements.
+Block* Parser::CreateForEachStatementTDZ(Block* init_block, ForInfo* for_info,
+ bool* ok) {
+ if (for_info->bound_names_are_lexical) {
+ DCHECK_NULL(init_block);
+
+ init_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
+
+ for (int i = 0; i < for_info->bound_names.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.
+ Declaration* tdz_decl = DeclareVariable(for_info->bound_names[i], LET,
+ kNoSourcePosition, CHECK_OK);
+ tdz_decl->proxy()->var()->set_initializer_position(position());
+ }
+ }
+ return init_block;
+}
+
Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
Expression* each,
Expression* iterable,
@@ -2119,9 +2237,8 @@ Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
}
Statement* Parser::DesugarLexicalBindingsInForStatement(
- Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
ForStatement* loop, Statement* init, Expression* cond, Statement* next,
- Statement* body, bool* ok) {
+ Statement* body, Scope* inner_scope, ForInfo* for_info, bool* ok) {
// ES6 13.7.4.8 specifies that on each loop iteration the let variables are
// copied into a new environment. Moreover, the "next" statement must be
// evaluated not in the environment of the just completed iteration but in
@@ -2159,11 +2276,11 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
// }
// }
- DCHECK(names->length() > 0);
- ZoneList<Variable*> temps(names->length(), zone());
+ DCHECK(for_info->bound_names.length() > 0);
+ ZoneList<Variable*> temps(for_info->bound_names.length(), zone());
- Block* outer_block =
- factory()->NewBlock(NULL, names->length() + 4, false, kNoSourcePosition);
+ Block* outer_block = factory()->NewBlock(
+ NULL, for_info->bound_names.length() + 4, false, kNoSourcePosition);
// Add statement: let/const x = i.
outer_block->statements()->Add(init, zone());
@@ -2172,8 +2289,8 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
// For each lexical variable x:
// make statement: temp_x = x.
- for (int i = 0; i < names->length(); i++) {
- VariableProxy* proxy = NewUnresolved(names->at(i));
+ for (int i = 0; i < for_info->bound_names.length(); i++) {
+ VariableProxy* proxy = NewUnresolved(for_info->bound_names[i]);
Variable* temp = NewTemporary(temp_name);
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, temp_proxy,
@@ -2217,14 +2334,15 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
{
BlockState block_state(&scope_state_, inner_scope);
- Block* ignore_completion_block =
- factory()->NewBlock(NULL, names->length() + 3, true, kNoSourcePosition);
- ZoneList<Variable*> inner_vars(names->length(), zone());
+ Block* ignore_completion_block = factory()->NewBlock(
+ NULL, for_info->bound_names.length() + 3, true, kNoSourcePosition);
marja 2016/09/20 19:36:30 Nit: pls update to nullptr while anyway modifying
nickie 2016/09/21 09:20:02 Done. Here and elsewhere.
+ ZoneList<Variable*> inner_vars(for_info->bound_names.length(), zone());
// For each let variable x:
// make statement: let/const x = temp_x.
- for (int i = 0; i < names->length(); i++) {
- Declaration* decl =
- DeclareVariable(names->at(i), mode, kNoSourcePosition, CHECK_OK);
+ for (int i = 0; i < for_info->bound_names.length(); i++) {
+ Declaration* decl = DeclareVariable(
+ for_info->bound_names[i], for_info->parsing_result.descriptor.mode,
+ kNoSourcePosition, CHECK_OK);
inner_vars.Add(decl->proxy()->var(), zone());
VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
Assignment* assignment = factory()->NewAssignment(
@@ -2308,7 +2426,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
// 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++) {
+ for (int i = 0; i < for_info->bound_names.length(); i++) {
VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
VariableProxy* proxy =
factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | src/parsing/parser-base.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698