OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 <cmath> | 5 #include <cmath> |
6 | 6 |
7 #include "src/allocation.h" | 7 #include "src/allocation.h" |
8 #include "src/base/logging.h" | 8 #include "src/base/logging.h" |
9 #include "src/conversions-inl.h" | 9 #include "src/conversions-inl.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 *ok = false; | 157 *ok = false; |
158 return Statement::Default(); | 158 return Statement::Default(); |
159 } | 159 } |
160 } | 160 } |
161 // PreParser is not able to parse "export default" yet (since PreParser is | 161 // PreParser is not able to parse "export default" yet (since PreParser is |
162 // at the moment only used for functions, and it cannot occur | 162 // at the moment only used for functions, and it cannot occur |
163 // there). TODO(marja): update this when it is. | 163 // there). TODO(marja): update this when it is. |
164 return ParseHoistableDeclaration(pos, flags, nullptr, false, ok); | 164 return ParseHoistableDeclaration(pos, flags, nullptr, false, ok); |
165 } | 165 } |
166 | 166 |
167 PreParser::Statement PreParser::ParseForStatement( | |
168 ZoneList<const AstRawString*>* labels, bool* ok) { | |
169 // ForStatement :: | |
170 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | |
171 | |
172 // Create an in-between scope for let-bound iteration variables. | |
173 bool has_lexical = false; | |
174 | |
175 BlockState block_state(&scope_state_); | |
176 Expect(Token::FOR, CHECK_OK); | |
177 Expect(Token::LPAREN, CHECK_OK); | |
178 if (peek() != Token::SEMICOLON) { | |
179 ForEachStatement::VisitMode mode; | |
180 if (peek() == Token::VAR || peek() == Token::CONST || | |
181 (peek() == Token::LET && IsNextLetKeyword())) { | |
182 DeclarationParsingResult parsing_result; | |
183 | |
184 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr, | |
185 CHECK_OK); | |
186 if (parsing_result.descriptor.mode == CONST || | |
187 parsing_result.descriptor.mode == LET) { | |
188 has_lexical = true; | |
189 } | |
190 if (CheckInOrOf(&mode)) { | |
191 if (!*ok) return Statement::Default(); | |
192 if (parsing_result.declarations.length() != 1) { | |
193 ReportMessageAt(parsing_result.bindings_loc, | |
194 MessageTemplate::kForInOfLoopMultiBindings, | |
195 ForEachStatement::VisitModeString(mode)); | |
196 *ok = false; | |
197 return Statement::Default(); | |
198 } | |
199 bool is_binding_pattern = | |
200 parsing_result.declarations[0].pattern.IsObjectLiteral() || | |
201 parsing_result.declarations[0].pattern.IsArrayLiteral(); | |
202 if (parsing_result.first_initializer_loc.IsValid() && | |
203 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || | |
204 has_lexical || is_binding_pattern || allow_harmony_for_in())) { | |
205 // Only increment the use count if we would have let this through | |
206 // without the flag. | |
207 if (use_counts_ != nullptr && allow_harmony_for_in()) { | |
208 ++use_counts_[v8::Isolate::kForInInitializer]; | |
209 } | |
210 ReportMessageAt(parsing_result.first_initializer_loc, | |
211 MessageTemplate::kForInOfLoopInitializer, | |
212 ForEachStatement::VisitModeString(mode)); | |
213 *ok = false; | |
214 return Statement::Default(); | |
215 } | |
216 | |
217 if (mode == ForEachStatement::ITERATE) { | |
218 ExpressionClassifier classifier(this); | |
219 ParseAssignmentExpression(true, CHECK_OK); | |
220 RewriteNonPattern(CHECK_OK); | |
221 } else { | |
222 ParseExpression(true, CHECK_OK); | |
223 } | |
224 | |
225 Expect(Token::RPAREN, CHECK_OK); | |
226 { | |
227 ReturnExprScope no_tail_calls(function_state_, | |
228 ReturnExprContext::kInsideForInOfBody); | |
229 ParseScopedStatement(nullptr, true, CHECK_OK); | |
230 } | |
231 return Statement::Default(); | |
232 } | |
233 } else { | |
234 int lhs_beg_pos = peek_position(); | |
235 ExpressionClassifier classifier(this); | |
236 Expression lhs = ParseExpressionCoverGrammar(false, CHECK_OK); | |
237 int lhs_end_pos = scanner()->location().end_pos; | |
238 bool is_for_each = CheckInOrOf(&mode); | |
239 bool is_destructuring = is_for_each && | |
240 (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()); | |
241 | |
242 if (is_destructuring) { | |
243 ValidateAssignmentPattern(CHECK_OK); | |
244 } else { | |
245 ValidateExpression(CHECK_OK); | |
246 } | |
247 | |
248 if (is_for_each) { | |
249 if (!is_destructuring) { | |
250 lhs = CheckAndRewriteReferenceExpression( | |
251 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor, | |
252 kSyntaxError, CHECK_OK); | |
253 } | |
254 | |
255 if (mode == ForEachStatement::ITERATE) { | |
256 ExpressionClassifier classifier(this); | |
257 ParseAssignmentExpression(true, CHECK_OK); | |
258 RewriteNonPattern(CHECK_OK); | |
259 } else { | |
260 ParseExpression(true, CHECK_OK); | |
261 } | |
262 | |
263 Expect(Token::RPAREN, CHECK_OK); | |
264 { | |
265 BlockState block_state(&scope_state_); | |
266 ParseScopedStatement(nullptr, true, CHECK_OK); | |
267 } | |
268 return Statement::Default(); | |
269 } | |
270 } | |
271 } | |
272 | |
273 // Parsed initializer at this point. | |
274 Expect(Token::SEMICOLON, CHECK_OK); | |
275 | |
276 // If there are let bindings, then condition and the next statement of the | |
277 // for loop must be parsed in a new scope. | |
278 Scope* inner_scope = scope(); | |
279 // TODO(verwaest): Allocate this through a ScopeState as well. | |
280 if (has_lexical) inner_scope = NewScopeWithParent(inner_scope, BLOCK_SCOPE); | |
281 | |
282 { | |
283 BlockState block_state(&scope_state_, inner_scope); | |
284 | |
285 if (peek() != Token::SEMICOLON) { | |
286 ParseExpression(true, CHECK_OK); | |
287 } | |
288 Expect(Token::SEMICOLON, CHECK_OK); | |
289 | |
290 if (peek() != Token::RPAREN) { | |
291 ParseExpression(true, CHECK_OK); | |
292 } | |
293 Expect(Token::RPAREN, CHECK_OK); | |
294 | |
295 ParseScopedStatement(nullptr, true, ok); | |
296 } | |
297 return Statement::Default(); | |
298 } | |
299 | |
300 | |
301 // Redefinition of CHECK_OK for parsing expressions. | 167 // Redefinition of CHECK_OK for parsing expressions. |
302 #undef CHECK_OK | 168 #undef CHECK_OK |
303 #define CHECK_OK CHECK_OK_VALUE(Expression::Default()) | 169 #define CHECK_OK CHECK_OK_VALUE(Expression::Default()) |
304 | 170 |
305 PreParser::Expression PreParser::ParseFunctionLiteral( | 171 PreParser::Expression PreParser::ParseFunctionLiteral( |
306 Identifier function_name, Scanner::Location function_name_location, | 172 Identifier function_name, Scanner::Location function_name_location, |
307 FunctionNameValidity function_name_validity, FunctionKind kind, | 173 FunctionNameValidity function_name_validity, FunctionKind kind, |
308 int function_token_pos, FunctionLiteral::FunctionType function_type, | 174 int function_token_pos, FunctionLiteral::FunctionType function_type, |
309 LanguageMode language_mode, bool* ok) { | 175 LanguageMode language_mode, bool* ok) { |
310 // Function :: | 176 // Function :: |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 | 339 |
474 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); | 340 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); |
475 } | 341 } |
476 | 342 |
477 #undef CHECK_OK | 343 #undef CHECK_OK |
478 #undef CHECK_OK_CUSTOM | 344 #undef CHECK_OK_CUSTOM |
479 | 345 |
480 | 346 |
481 } // namespace internal | 347 } // namespace internal |
482 } // namespace v8 | 348 } // namespace v8 |
OLD | NEW |