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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h" 10 #include "src/ast/ast-expression-rewriter.h"
(...skipping 1977 matching lines...) Expand 10 before | Expand all | Expand 10 after
1988 zone()); 1988 zone());
1989 block->statements()->Add(body, zone()); 1989 block->statements()->Add(body, zone());
1990 body = block; 1990 body = block;
1991 each = factory()->NewVariableProxy(temp); 1991 each = factory()->NewVariableProxy(temp);
1992 } 1992 }
1993 stmt->AsForInStatement()->Initialize(each, subject, body); 1993 stmt->AsForInStatement()->Initialize(each, subject, body);
1994 } 1994 }
1995 return stmt; 1995 return stmt;
1996 } 1996 }
1997 1997
1998 // 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
1999 Block* Parser::RewriteForVarInLegacy(ForInfo* for_info) {
2000 const DeclarationParsingResult::Declaration& decl =
2001 for_info->parsing_result.declarations[0];
2002 if (!for_info->bound_names_are_lexical && decl.pattern->IsVariableProxy() &&
2003 decl.initializer != nullptr) {
2004 DCHECK(!allow_harmony_for_in());
2005 ++use_counts_[v8::Isolate::kForInInitializer];
2006 const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name();
2007 VariableProxy* single_var = NewUnresolved(name);
2008 Block* init_block = factory()->NewBlock(
2009 nullptr, 2, true, for_info->parsing_result.descriptor.declaration_pos);
2010 init_block->statements()->Add(
2011 factory()->NewExpressionStatement(
2012 factory()->NewAssignment(Token::ASSIGN, single_var,
2013 decl.initializer, kNoSourcePosition),
2014 kNoSourcePosition),
2015 zone());
2016 return init_block;
2017 } else {
marja 2016/09/20 19:36:30 Style nit: else { } around the return is unnecessa
nickie 2016/09/21 09:20:02 Done.
2018 return nullptr;
2019 }
2020 }
2021
2022 // Rewrite a for-in/of statement of the form
2023 //
2024 // for (let/const/var x in/of e) b
2025 //
2026 // into
2027 //
2028 // {
2029 // <let x' be a temporary variable>
2030 // for (x' in/of e) {
2031 // let/const/var x;
2032 // x = x';
2033 // b;
2034 // }
2035 // let x; // for TDZ
2036 // }
2037 std::pair<Block*, Expression*> Parser::DesugarBindingInForEachStatement(
2038 ForInfo* for_info, bool* ok) {
2039 DeclarationParsingResult::Declaration& decl =
2040 for_info->parsing_result.declarations[0];
2041 Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
2042 auto each_initialization_block =
2043 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
2044 {
2045 auto descriptor = for_info->parsing_result.descriptor;
2046 descriptor.declaration_pos = kNoSourcePosition;
2047 descriptor.initialization_pos = kNoSourcePosition;
2048 decl.initializer = factory()->NewVariableProxy(temp);
2049
2050 bool is_for_var_of =
2051 for_info->mode == ForEachStatement::ITERATE &&
2052 for_info->parsing_result.descriptor.mode == VariableMode::VAR;
2053
2054 PatternRewriter::DeclareAndInitializeVariables(
2055 this, each_initialization_block, &descriptor, &decl,
2056 (for_info->bound_names_are_lexical || is_for_var_of)
2057 ? &for_info->bound_names
2058 : nullptr,
2059 CHECK_OK_VALUE(std::make_pair(nullptr, nullptr)));
2060
2061 // Annex B.3.5 prohibits the form
2062 // `try {} catch(e) { for (var e of {}); }`
2063 // So if we are parsing a statement like `for (var ... of ...)`
2064 // we need to walk up the scope chain and look for catch scopes
2065 // which have a simple binding, then compare their binding against
2066 // all of the names declared in the init of the for-of we're
2067 // parsing.
2068 if (is_for_var_of) {
2069 Scope* catch_scope = scope();
2070 while (catch_scope != nullptr && !catch_scope->is_declaration_scope()) {
2071 if (catch_scope->is_catch_scope()) {
2072 auto name = catch_scope->catch_variable_name();
2073 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.
2074 ast_value_factory()
2075 ->dot_catch_string()) { // i.e. is a simple binding
2076 if (for_info->bound_names.Contains(name)) {
2077 ReportMessageAt(for_info->parsing_result.bindings_loc,
2078 MessageTemplate::kVarRedeclaration, name);
2079 *ok = false;
2080 return std::make_pair(nullptr, nullptr);
2081 }
2082 }
2083 }
2084 catch_scope = catch_scope->outer_scope();
2085 }
2086 }
2087 }
2088
2089 Block* body_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition);
2090 body_block->statements()->Add(each_initialization_block, zone());
2091 VariableProxy* temp_proxy = factory()->NewVariableProxy(
2092 temp, for_info->each_loc.beg_pos, for_info->each_loc.end_pos);
2093 return std::make_pair(body_block, temp_proxy);
2094 }
2095
2096 // Create a TDZ for any lexically-bound names in for in/of statements.
2097 Block* Parser::CreateForEachStatementTDZ(Block* init_block, ForInfo* for_info,
2098 bool* ok) {
2099 if (for_info->bound_names_are_lexical) {
2100 DCHECK_NULL(init_block);
2101
2102 init_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
2103
2104 for (int i = 0; i < for_info->bound_names.length(); ++i) {
2105 // TODO(adamk): This needs to be some sort of special
2106 // INTERNAL variable that's invisible to the debugger
2107 // but visible to everything else.
2108 Declaration* tdz_decl = DeclareVariable(for_info->bound_names[i], LET,
2109 kNoSourcePosition, CHECK_OK);
2110 tdz_decl->proxy()->var()->set_initializer_position(position());
2111 }
2112 }
2113 return init_block;
2114 }
2115
1998 Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of, 2116 Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
1999 Expression* each, 2117 Expression* each,
2000 Expression* iterable, 2118 Expression* iterable,
2001 Statement* body, bool finalize, 2119 Statement* body, bool finalize,
2002 int next_result_pos) { 2120 int next_result_pos) {
2003 // Create the auxiliary expressions needed for iterating over the iterable, 2121 // Create the auxiliary expressions needed for iterating over the iterable,
2004 // and initialize the given ForOfStatement with them. 2122 // and initialize the given ForOfStatement with them.
2005 // If finalize is true, also instrument the loop with code that performs the 2123 // If finalize is true, also instrument the loop with code that performs the
2006 // proper ES6 iterator finalization. In that case, the result is not 2124 // proper ES6 iterator finalization. In that case, the result is not
2007 // immediately a ForOfStatement. 2125 // immediately a ForOfStatement.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
2112 block->statements()->Add(set_completion_normal, zone()); 2230 block->statements()->Add(set_completion_normal, zone());
2113 body = block; 2231 body = block;
2114 } 2232 }
2115 2233
2116 for_of->Initialize(body, iterator, assign_iterator, next_result, result_done, 2234 for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
2117 assign_each); 2235 assign_each);
2118 return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of; 2236 return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of;
2119 } 2237 }
2120 2238
2121 Statement* Parser::DesugarLexicalBindingsInForStatement( 2239 Statement* Parser::DesugarLexicalBindingsInForStatement(
2122 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
2123 ForStatement* loop, Statement* init, Expression* cond, Statement* next, 2240 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
2124 Statement* body, bool* ok) { 2241 Statement* body, Scope* inner_scope, ForInfo* for_info, bool* ok) {
2125 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are 2242 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
2126 // copied into a new environment. Moreover, the "next" statement must be 2243 // copied into a new environment. Moreover, the "next" statement must be
2127 // evaluated not in the environment of the just completed iteration but in 2244 // evaluated not in the environment of the just completed iteration but in
2128 // that of the upcoming one. We achieve this with the following desugaring. 2245 // that of the upcoming one. We achieve this with the following desugaring.
2129 // Extra care is needed to preserve the completion value of the original loop. 2246 // Extra care is needed to preserve the completion value of the original loop.
2130 // 2247 //
2131 // We are given a for statement of the form 2248 // We are given a for statement of the form
2132 // 2249 //
2133 // labels: for (let/const x = i; cond; next) body 2250 // labels: for (let/const x = i; cond; next) body
2134 // 2251 //
(...skipping 17 matching lines...) Expand all
2152 // }} 2269 // }}
2153 // labels: for (; flag == 1; flag = 0, temp_x = x) { 2270 // labels: for (; flag == 1; flag = 0, temp_x = x) {
2154 // body 2271 // body
2155 // } 2272 // }
2156 // {{ if (flag == 1) // Body used break. 2273 // {{ if (flag == 1) // Body used break.
2157 // break; 2274 // break;
2158 // }} 2275 // }}
2159 // } 2276 // }
2160 // } 2277 // }
2161 2278
2162 DCHECK(names->length() > 0); 2279 DCHECK(for_info->bound_names.length() > 0);
2163 ZoneList<Variable*> temps(names->length(), zone()); 2280 ZoneList<Variable*> temps(for_info->bound_names.length(), zone());
2164 2281
2165 Block* outer_block = 2282 Block* outer_block = factory()->NewBlock(
2166 factory()->NewBlock(NULL, names->length() + 4, false, kNoSourcePosition); 2283 NULL, for_info->bound_names.length() + 4, false, kNoSourcePosition);
2167 2284
2168 // Add statement: let/const x = i. 2285 // Add statement: let/const x = i.
2169 outer_block->statements()->Add(init, zone()); 2286 outer_block->statements()->Add(init, zone());
2170 2287
2171 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); 2288 const AstRawString* temp_name = ast_value_factory()->dot_for_string();
2172 2289
2173 // For each lexical variable x: 2290 // For each lexical variable x:
2174 // make statement: temp_x = x. 2291 // make statement: temp_x = x.
2175 for (int i = 0; i < names->length(); i++) { 2292 for (int i = 0; i < for_info->bound_names.length(); i++) {
2176 VariableProxy* proxy = NewUnresolved(names->at(i)); 2293 VariableProxy* proxy = NewUnresolved(for_info->bound_names[i]);
2177 Variable* temp = NewTemporary(temp_name); 2294 Variable* temp = NewTemporary(temp_name);
2178 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); 2295 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
2179 Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, temp_proxy, 2296 Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, temp_proxy,
2180 proxy, kNoSourcePosition); 2297 proxy, kNoSourcePosition);
2181 Statement* assignment_statement = 2298 Statement* assignment_statement =
2182 factory()->NewExpressionStatement(assignment, kNoSourcePosition); 2299 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2183 outer_block->statements()->Add(assignment_statement, zone()); 2300 outer_block->statements()->Add(assignment_statement, zone());
2184 temps.Add(temp, zone()); 2301 temps.Add(temp, zone());
2185 } 2302 }
2186 2303
(...skipping 23 matching lines...) Expand all
2210 // in this function that looks up break targets. 2327 // in this function that looks up break targets.
2211 ForStatement* outer_loop = 2328 ForStatement* outer_loop =
2212 factory()->NewForStatement(NULL, kNoSourcePosition); 2329 factory()->NewForStatement(NULL, kNoSourcePosition);
2213 outer_block->statements()->Add(outer_loop, zone()); 2330 outer_block->statements()->Add(outer_loop, zone());
2214 outer_block->set_scope(scope()); 2331 outer_block->set_scope(scope());
2215 2332
2216 Block* inner_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition); 2333 Block* inner_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition);
2217 { 2334 {
2218 BlockState block_state(&scope_state_, inner_scope); 2335 BlockState block_state(&scope_state_, inner_scope);
2219 2336
2220 Block* ignore_completion_block = 2337 Block* ignore_completion_block = factory()->NewBlock(
2221 factory()->NewBlock(NULL, names->length() + 3, true, kNoSourcePosition); 2338 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.
2222 ZoneList<Variable*> inner_vars(names->length(), zone()); 2339 ZoneList<Variable*> inner_vars(for_info->bound_names.length(), zone());
2223 // For each let variable x: 2340 // For each let variable x:
2224 // make statement: let/const x = temp_x. 2341 // make statement: let/const x = temp_x.
2225 for (int i = 0; i < names->length(); i++) { 2342 for (int i = 0; i < for_info->bound_names.length(); i++) {
2226 Declaration* decl = 2343 Declaration* decl = DeclareVariable(
2227 DeclareVariable(names->at(i), mode, kNoSourcePosition, CHECK_OK); 2344 for_info->bound_names[i], for_info->parsing_result.descriptor.mode,
2345 kNoSourcePosition, CHECK_OK);
2228 inner_vars.Add(decl->proxy()->var(), zone()); 2346 inner_vars.Add(decl->proxy()->var(), zone());
2229 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); 2347 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
2230 Assignment* assignment = factory()->NewAssignment( 2348 Assignment* assignment = factory()->NewAssignment(
2231 Token::INIT, decl->proxy(), temp_proxy, kNoSourcePosition); 2349 Token::INIT, decl->proxy(), temp_proxy, kNoSourcePosition);
2232 Statement* assignment_statement = 2350 Statement* assignment_statement =
2233 factory()->NewExpressionStatement(assignment, kNoSourcePosition); 2351 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2234 DCHECK(init->position() != kNoSourcePosition); 2352 DCHECK(init->position() != kNoSourcePosition);
2235 decl->proxy()->var()->set_initializer_position(init->position()); 2353 decl->proxy()->var()->set_initializer_position(init->position());
2236 ignore_completion_block->statements()->Add(assignment_statement, zone()); 2354 ignore_completion_block->statements()->Add(assignment_statement, zone());
2237 } 2355 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2301 // Make expression: flag = 0. 2419 // Make expression: flag = 0.
2302 { 2420 {
2303 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); 2421 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2304 Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition); 2422 Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition);
2305 compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy, 2423 compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy,
2306 const0, kNoSourcePosition); 2424 const0, kNoSourcePosition);
2307 } 2425 }
2308 2426
2309 // Make the comma-separated list of temp_x = x assignments. 2427 // Make the comma-separated list of temp_x = x assignments.
2310 int inner_var_proxy_pos = scanner()->location().beg_pos; 2428 int inner_var_proxy_pos = scanner()->location().beg_pos;
2311 for (int i = 0; i < names->length(); i++) { 2429 for (int i = 0; i < for_info->bound_names.length(); i++) {
2312 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); 2430 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
2313 VariableProxy* proxy = 2431 VariableProxy* proxy =
2314 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos); 2432 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
2315 Assignment* assignment = factory()->NewAssignment( 2433 Assignment* assignment = factory()->NewAssignment(
2316 Token::ASSIGN, temp_proxy, proxy, kNoSourcePosition); 2434 Token::ASSIGN, temp_proxy, proxy, kNoSourcePosition);
2317 compound_next = factory()->NewBinaryOperation( 2435 compound_next = factory()->NewBinaryOperation(
2318 Token::COMMA, compound_next, assignment, kNoSourcePosition); 2436 Token::COMMA, compound_next, assignment, kNoSourcePosition);
2319 } 2437 }
2320 2438
2321 compound_next_statement = 2439 compound_next_statement =
(...skipping 3146 matching lines...) Expand 10 before | Expand all | Expand 10 after
5468 5586
5469 return final_loop; 5587 return final_loop;
5470 } 5588 }
5471 5589
5472 #undef CHECK_OK 5590 #undef CHECK_OK
5473 #undef CHECK_OK_VOID 5591 #undef CHECK_OK_VOID
5474 #undef CHECK_FAILED 5592 #undef CHECK_FAILED
5475 5593
5476 } // namespace internal 5594 } // namespace internal
5477 } // namespace v8 5595 } // namespace v8
OLDNEW
« 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