OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |