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

Side by Side Diff: src/parser.cc

Issue 1128043006: [destructuring] Adapting PatternRewriter to work in for-statements. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased Created 5 years, 7 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
« no previous file with comments | « src/parser.h ('k') | src/pattern-rewriter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
11 #include "src/bootstrapper.h" 11 #include "src/bootstrapper.h"
12 #include "src/char-predicates-inl.h" 12 #include "src/char-predicates-inl.h"
13 #include "src/codegen.h" 13 #include "src/codegen.h"
14 #include "src/compiler.h" 14 #include "src/compiler.h"
15 #include "src/messages.h" 15 #include "src/messages.h"
16 #include "src/parser.h" 16 #include "src/parser.h"
17 #include "src/pattern-rewriter.h"
18 #include "src/preparser.h" 17 #include "src/preparser.h"
19 #include "src/runtime/runtime.h" 18 #include "src/runtime/runtime.h"
20 #include "src/scanner-character-streams.h" 19 #include "src/scanner-character-streams.h"
21 #include "src/scopeinfo.h" 20 #include "src/scopeinfo.h"
22 #include "src/string-stream.h" 21 #include "src/string-stream.h"
23 22
24 namespace v8 { 23 namespace v8 {
25 namespace internal { 24 namespace internal {
26 25
27 ScriptData::ScriptData(const byte* data, int length) 26 ScriptData::ScriptData(const byte* data, int length)
(...skipping 2237 matching lines...) Expand 10 before | Expand all | Expand 10 after
2265 } 2264 }
2266 } 2265 }
2267 Expect(Token::RBRACE, CHECK_OK); 2266 Expect(Token::RBRACE, CHECK_OK);
2268 block_scope->set_end_position(scanner()->location().end_pos); 2267 block_scope->set_end_position(scanner()->location().end_pos);
2269 block_scope = block_scope->FinalizeBlockScope(); 2268 block_scope = block_scope->FinalizeBlockScope();
2270 body->set_scope(block_scope); 2269 body->set_scope(block_scope);
2271 return body; 2270 return body;
2272 } 2271 }
2273 2272
2274 2273
2274 const AstRawString* Parser::DeclarationParsingResult::SingleName() const {
2275 if (declarations.length() != 1) return nullptr;
2276 const Declaration& declaration = declarations.at(0);
2277 if (declaration.pattern->IsVariableProxy()) {
2278 return declaration.pattern->AsVariableProxy()->raw_name();
2279 }
2280 return nullptr;
2281 }
2282
2283
2284 Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
2285 ZoneList<const AstRawString*>* names, bool* ok) {
2286 Block* result =
2287 descriptor.parser->factory()->NewBlock(NULL, 1, true, descriptor.pos);
2288 for (auto declaration : declarations) {
2289 PatternRewriter::DeclareAndInitializeVariables(
2290 result, &descriptor, &declaration, names, CHECK_OK);
2291 }
2292 return result;
2293 }
2294
2295
2275 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, 2296 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
2276 ZoneList<const AstRawString*>* names, 2297 ZoneList<const AstRawString*>* names,
2277 bool* ok) { 2298 bool* ok) {
2278 // VariableStatement :: 2299 // VariableStatement ::
2279 // VariableDeclarations ';' 2300 // VariableDeclarations ';'
2280 2301
2281 const AstRawString* ignore; 2302 // The scope of a var/const declared variable anywhere inside a function
2282 Block* result = ParseVariableDeclarations( 2303 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
2283 var_context, nullptr, names, &ignore, nullptr, nullptr, CHECK_OK); 2304 // transform a source-level var/const declaration into a (Function)
2305 // Scope declaration, and rewrite the source-level initialization into an
2306 // assignment statement. We use a block to collect multiple assignments.
2307 //
2308 // We mark the block as initializer block because we don't want the
2309 // rewriter to add a '.result' assignment to such a block (to get compliant
2310 // behavior for code such as print(eval('var x = 7')), and for cosmetic
2311 // reasons when pretty-printing. Also, unless an assignment (initialization)
2312 // is inside an initializer block, it is ignored.
2313
2314 DeclarationParsingResult parsing_result;
2315 ParseVariableDeclarations(var_context, &parsing_result, CHECK_OK);
2284 ExpectSemicolon(CHECK_OK); 2316 ExpectSemicolon(CHECK_OK);
2317
2318 Block* result = parsing_result.BuildInitializationBlock(names, CHECK_OK);
2285 return result; 2319 return result;
2286 } 2320 }
2287 2321
2288 2322
2289 // If the variable declaration declares exactly one non-const 2323 void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
2290 // variable, then *out is set to that variable. In all other cases, 2324 DeclarationParsingResult* parsing_result,
2291 // *out is untouched; in particular, it is the caller's responsibility 2325 bool* ok) {
2292 // to initialize it properly. This mechanism is used for the parsing
2293 // of 'for-in' loops.
2294 Block* Parser::ParseVariableDeclarations(
2295 VariableDeclarationContext var_context, int* num_decl,
2296 ZoneList<const AstRawString*>* names, const AstRawString** out,
2297 Scanner::Location* first_initializer_loc, Scanner::Location* bindings_loc,
2298 bool* ok) {
2299 // VariableDeclarations :: 2326 // VariableDeclarations ::
2300 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] 2327 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2301 // 2328 //
2302 // The ES6 Draft Rev3 specifies the following grammar for const declarations 2329 // The ES6 Draft Rev3 specifies the following grammar for const declarations
2303 // 2330 //
2304 // ConstDeclaration :: 2331 // ConstDeclaration ::
2305 // const ConstBinding (',' ConstBinding)* ';' 2332 // const ConstBinding (',' ConstBinding)* ';'
2306 // ConstBinding :: 2333 // ConstBinding ::
2307 // Identifier '=' AssignmentExpression 2334 // Identifier '=' AssignmentExpression
2308 // 2335 //
2309 // TODO(ES6): 2336 // TODO(ES6):
2310 // ConstBinding :: 2337 // ConstBinding ::
2311 // BindingPattern '=' AssignmentExpression 2338 // BindingPattern '=' AssignmentExpression
2312 2339
2313 PatternRewriter::DeclarationDescriptor decl; 2340 parsing_result->descriptor.parser = this;
2314 decl.parser = this; 2341 parsing_result->descriptor.pos = peek_position();
2315 decl.pos = peek_position(); 2342 parsing_result->descriptor.mode = VAR;
2316 decl.mode = VAR;
2317 // True if the binding needs initialization. 'let' and 'const' declared 2343 // True if the binding needs initialization. 'let' and 'const' declared
2318 // bindings are created uninitialized by their declaration nodes and 2344 // bindings are created uninitialized by their declaration nodes and
2319 // need initialization. 'var' declared bindings are always initialized 2345 // need initialization. 'var' declared bindings are always initialized
2320 // immediately by their declaration nodes. 2346 // immediately by their declaration nodes.
2321 decl.needs_init = false; 2347 parsing_result->descriptor.needs_init = false;
2322 decl.is_const = false; 2348 parsing_result->descriptor.is_const = false;
2323 decl.init_op = Token::INIT_VAR; 2349 parsing_result->descriptor.init_op = Token::INIT_VAR;
2324 decl.names = names;
2325 if (peek() == Token::VAR) { 2350 if (peek() == Token::VAR) {
2326 if (is_strong(language_mode())) { 2351 if (is_strong(language_mode())) {
2327 Scanner::Location location = scanner()->peek_location(); 2352 Scanner::Location location = scanner()->peek_location();
2328 ReportMessageAt(location, "strong_var"); 2353 ReportMessageAt(location, "strong_var");
2329 *ok = false; 2354 *ok = false;
2330 return NULL; 2355 return;
2331 } 2356 }
2332 Consume(Token::VAR); 2357 Consume(Token::VAR);
2333 } else if (peek() == Token::CONST) { 2358 } else if (peek() == Token::CONST) {
2334 Consume(Token::CONST); 2359 Consume(Token::CONST);
2335 if (is_sloppy(language_mode())) { 2360 if (is_sloppy(language_mode())) {
2336 decl.mode = CONST_LEGACY; 2361 parsing_result->descriptor.mode = CONST_LEGACY;
2337 decl.init_op = Token::INIT_CONST_LEGACY; 2362 parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY;
2338 ++use_counts_[v8::Isolate::kLegacyConst]; 2363 ++use_counts_[v8::Isolate::kLegacyConst];
2339 } else { 2364 } else {
2340 DCHECK(var_context != kStatement); 2365 DCHECK(var_context != kStatement);
2341 decl.mode = CONST; 2366 parsing_result->descriptor.mode = CONST;
2342 decl.init_op = Token::INIT_CONST; 2367 parsing_result->descriptor.init_op = Token::INIT_CONST;
2343 } 2368 }
2344 decl.is_const = true; 2369 parsing_result->descriptor.is_const = true;
2345 decl.needs_init = true; 2370 parsing_result->descriptor.needs_init = true;
2346 } else if (peek() == Token::LET && is_strict(language_mode())) { 2371 } else if (peek() == Token::LET && is_strict(language_mode())) {
2347 Consume(Token::LET); 2372 Consume(Token::LET);
2348 DCHECK(var_context != kStatement); 2373 DCHECK(var_context != kStatement);
2349 decl.mode = LET; 2374 parsing_result->descriptor.mode = LET;
2350 decl.needs_init = true; 2375 parsing_result->descriptor.needs_init = true;
2351 decl.init_op = Token::INIT_LET; 2376 parsing_result->descriptor.init_op = Token::INIT_LET;
2352 } else { 2377 } else {
2353 UNREACHABLE(); // by current callers 2378 UNREACHABLE(); // by current callers
2354 } 2379 }
2355 2380
2356 decl.declaration_scope = DeclarationScope(decl.mode); 2381 parsing_result->descriptor.declaration_scope =
2357 decl.scope = scope_; 2382 DeclarationScope(parsing_result->descriptor.mode);
2383 parsing_result->descriptor.scope = scope_;
2358 2384
2359 2385
2360 // The scope of a var/const declared variable anywhere inside a function 2386 bool first_declaration = true;
2361 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
2362 // transform a source-level var/const declaration into a (Function)
2363 // Scope declaration, and rewrite the source-level initialization into an
2364 // assignment statement. We use a block to collect multiple assignments.
2365 //
2366 // We mark the block as initializer block because we don't want the
2367 // rewriter to add a '.result' assignment to such a block (to get compliant
2368 // behavior for code such as print(eval('var x = 7')), and for cosmetic
2369 // reasons when pretty-printing. Also, unless an assignment (initialization)
2370 // is inside an initializer block, it is ignored.
2371 //
2372 // Create new block with one expected declaration.
2373 decl.block = factory()->NewBlock(NULL, 1, true, decl.pos);
2374 int nvars = 0; // the number of variables declared
2375 int bindings_start = peek_position(); 2387 int bindings_start = peek_position();
2376 const AstRawString* first_name = NULL;
2377 bool is_for_iteration_variable; 2388 bool is_for_iteration_variable;
2378 do { 2389 do {
2379 if (fni_ != NULL) fni_->Enter(); 2390 if (fni_ != NULL) fni_->Enter();
2380 2391
2381 // Parse variable name. 2392 // Parse name.
2382 if (nvars > 0) Consume(Token::COMMA); 2393 if (!first_declaration) Consume(Token::COMMA);
2383 2394
2384 PatternRewriter pattern_rewriter; 2395 Expression* pattern;
2385 { 2396 {
2386 ExpressionClassifier pattern_classifier; 2397 ExpressionClassifier pattern_classifier;
2387 Token::Value next = peek(); 2398 Token::Value next = peek();
2388 Expression* pattern = 2399 pattern = ParsePrimaryExpression(&pattern_classifier, ok);
2389 ParsePrimaryExpression(&pattern_classifier, CHECK_OK); 2400 if (!*ok) return;
2390 ValidateBindingPattern(&pattern_classifier, CHECK_OK); 2401 ValidateBindingPattern(&pattern_classifier, ok);
2391 pattern_rewriter = PatternRewriter(&decl, pattern); 2402 if (!*ok) return;
2392 if (!allow_harmony_destructuring() && 2403 if (!allow_harmony_destructuring() && !pattern->IsVariableProxy()) {
2393 !pattern_rewriter.IsSingleVariableBinding()) {
2394 ReportUnexpectedToken(next); 2404 ReportUnexpectedToken(next);
2395 *ok = false; 2405 *ok = false;
2396 return nullptr; 2406 return;
2397 } 2407 }
2398
2399 // TODO(dslomov): unify
2400 } 2408 }
2401 2409
2402 Scanner::Location variable_loc = scanner()->location(); 2410 Scanner::Location variable_loc = scanner()->location();
2403 const bool single_name = pattern_rewriter.IsSingleVariableBinding(); 2411 const AstRawString* single_name =
2404 if (single_name) { 2412 pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name()
2405 if (!first_name) first_name = pattern_rewriter.SingleName(); 2413 : nullptr;
2406 if (fni_ != NULL) fni_->PushVariableName(pattern_rewriter.SingleName()); 2414 if (single_name != nullptr) {
2415 if (fni_ != NULL) fni_->PushVariableName(single_name);
2407 } 2416 }
2408 2417
2409 is_for_iteration_variable = 2418 is_for_iteration_variable =
2410 var_context == kForStatement && 2419 var_context == kForStatement &&
2411 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of"))); 2420 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of")));
2412 if (is_for_iteration_variable && decl.mode == CONST) { 2421 if (is_for_iteration_variable && parsing_result->descriptor.mode == CONST) {
2413 decl.needs_init = false; 2422 parsing_result->descriptor.needs_init = false;
2414 } 2423 }
2415 2424
2416 Expression* value = NULL; 2425 Expression* value = NULL;
2417 decl.pos = -1;
2418 decl.initializer_position = -1;
2419 // Harmony consts have non-optional initializers. 2426 // Harmony consts have non-optional initializers.
2420 if (peek() == Token::ASSIGN || 2427 int initializer_position = RelocInfo::kNoPosition;
2421 (decl.mode == CONST && !is_for_iteration_variable)) { 2428 if (peek() == Token::ASSIGN || (parsing_result->descriptor.mode == CONST &&
2422 Expect(Token::ASSIGN, CHECK_OK); 2429 !is_for_iteration_variable)) {
2423 decl.pos = position(); 2430 Expect(Token::ASSIGN, ok);
2431 if (!*ok) return;
2424 ExpressionClassifier classifier; 2432 ExpressionClassifier classifier;
2425 value = ParseAssignmentExpression(var_context != kForStatement, 2433 value = ParseAssignmentExpression(var_context != kForStatement,
2426 &classifier, CHECK_OK); 2434 &classifier, ok);
2427 ValidateExpression(&classifier, CHECK_OK); 2435 if (!*ok) return;
2436 ValidateExpression(&classifier, ok);
2437 if (!*ok) return;
2428 variable_loc.end_pos = scanner()->location().end_pos; 2438 variable_loc.end_pos = scanner()->location().end_pos;
2429 2439
2430 if (first_initializer_loc && !first_initializer_loc->IsValid()) { 2440 if (!parsing_result->first_initializer_loc.IsValid()) {
2431 *first_initializer_loc = variable_loc; 2441 parsing_result->first_initializer_loc = variable_loc;
2432 } 2442 }
2433 2443
2434 // Don't infer if it is "a = function(){...}();"-like expression. 2444 // Don't infer if it is "a = function(){...}();"-like expression.
2435 if (single_name) { 2445 if (single_name) {
2436 if (fni_ != NULL && value->AsCall() == NULL && 2446 if (fni_ != NULL && value->AsCall() == NULL &&
2437 value->AsCallNew() == NULL) { 2447 value->AsCallNew() == NULL) {
2438 fni_->Infer(); 2448 fni_->Infer();
2439 } else { 2449 } else {
2440 fni_->RemoveLastFunction(); 2450 fni_->RemoveLastFunction();
2441 } 2451 }
2442 } 2452 }
2443 // End position of the initializer is after the assignment expression. 2453 // End position of the initializer is after the assignment expression.
2444 decl.initializer_position = scanner()->location().end_pos; 2454 initializer_position = scanner()->location().end_pos;
2445 } else { 2455 } else {
2446 // End position of the initializer is after the variable. 2456 // End position of the initializer is after the variable.
2447 decl.initializer_position = position(); 2457 initializer_position = position();
2448 } 2458 }
2449 2459
2450 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. 2460 // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
2451 if (value == NULL && decl.needs_init) { 2461 if (value == NULL && parsing_result->descriptor.needs_init) {
2452 value = GetLiteralUndefined(position()); 2462 value = GetLiteralUndefined(position());
2453 } 2463 }
2454 2464
2455 pattern_rewriter.DeclareAndInitializeVariables(value, &nvars, CHECK_OK);
2456
2457 if (single_name && fni_ != NULL) fni_->Leave(); 2465 if (single_name && fni_ != NULL) fni_->Leave();
2466 parsing_result->declarations.Add(DeclarationParsingResult::Declaration(
2467 pattern, initializer_position, value));
2468 first_declaration = false;
2458 } while (peek() == Token::COMMA); 2469 } while (peek() == Token::COMMA);
2459 2470
2460 if (bindings_loc) { 2471 parsing_result->bindings_loc =
2461 *bindings_loc = 2472 Scanner::Location(bindings_start, scanner()->location().end_pos);
2462 Scanner::Location(bindings_start, scanner()->location().end_pos);
2463 }
2464
2465 if (num_decl) *num_decl = nvars;
2466 *out = first_name;
2467
2468 return decl.block;
2469 } 2473 }
2470 2474
2471 2475
2472 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, 2476 static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
2473 const AstRawString* label) { 2477 const AstRawString* label) {
2474 DCHECK(label != NULL); 2478 DCHECK(label != NULL);
2475 if (labels != NULL) { 2479 if (labels != NULL) {
2476 for (int i = labels->length(); i-- > 0; ) { 2480 for (int i = labels->length(); i-- > 0; ) {
2477 if (labels->at(i) == label) { 2481 if (labels->at(i) == label) {
2478 return true; 2482 return true;
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after
3225 ForStatement* outer_loop = 3229 ForStatement* outer_loop =
3226 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); 3230 factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
3227 outer_block->AddStatement(outer_loop, zone()); 3231 outer_block->AddStatement(outer_loop, zone());
3228 3232
3229 outer_block->set_scope(for_scope); 3233 outer_block->set_scope(for_scope);
3230 scope_ = inner_scope; 3234 scope_ = inner_scope;
3231 3235
3232 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false, 3236 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false,
3233 RelocInfo::kNoPosition); 3237 RelocInfo::kNoPosition);
3234 ZoneList<Variable*> inner_vars(names->length(), zone()); 3238 ZoneList<Variable*> inner_vars(names->length(), zone());
3235
3236 // For each let variable x: 3239 // For each let variable x:
3237 // make statement: let/const x = temp_x. 3240 // make statement: let/const x = temp_x.
3238 VariableMode mode = is_const ? CONST : LET; 3241 VariableMode mode = is_const ? CONST : LET;
3239 for (int i = 0; i < names->length(); i++) { 3242 for (int i = 0; i < names->length(); i++) {
3240 VariableProxy* proxy = NewUnresolved(names->at(i), mode); 3243 VariableProxy* proxy = NewUnresolved(names->at(i), mode);
3241 Declaration* declaration = factory()->NewVariableDeclaration( 3244 Declaration* declaration = factory()->NewVariableDeclaration(
3242 proxy, mode, scope_, RelocInfo::kNoPosition); 3245 proxy, mode, scope_, RelocInfo::kNoPosition);
3243 Declare(declaration, true, CHECK_OK); 3246 Declare(declaration, true, CHECK_OK);
3244 inner_vars.Add(declaration->proxy()->var(), zone()); 3247 inner_vars.Add(declaration->proxy()->var(), zone());
3245 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); 3248 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
3246 Assignment* assignment = 3249 Assignment* assignment =
3247 factory()->NewAssignment(is_const ? Token::INIT_CONST : Token::INIT_LET, 3250 factory()->NewAssignment(is_const ? Token::INIT_CONST : Token::INIT_LET,
3248 proxy, temp_proxy, RelocInfo::kNoPosition); 3251 proxy, temp_proxy, RelocInfo::kNoPosition);
3249 Statement* assignment_statement = 3252 Statement* assignment_statement =
3250 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); 3253 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3254 DCHECK(init->position() != RelocInfo::kNoPosition);
3251 proxy->var()->set_initializer_position(init->position()); 3255 proxy->var()->set_initializer_position(init->position());
3252 inner_block->AddStatement(assignment_statement, zone()); 3256 inner_block->AddStatement(assignment_statement, zone());
3253 } 3257 }
3254 3258
3255 // Make statement: if (first == 1) { first = 0; } else { next; } 3259 // Make statement: if (first == 1) { first = 0; } else { next; }
3256 if (next) { 3260 if (next) {
3257 DCHECK(first); 3261 DCHECK(first);
3258 Expression* compare = NULL; 3262 Expression* compare = NULL;
3259 // Make compare expression: first == 1. 3263 // Make compare expression: first == 1.
3260 { 3264 {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3377 3381
3378 int stmt_pos = peek_position(); 3382 int stmt_pos = peek_position();
3379 bool is_const = false; 3383 bool is_const = false;
3380 Statement* init = NULL; 3384 Statement* init = NULL;
3381 ZoneList<const AstRawString*> lexical_bindings(1, zone()); 3385 ZoneList<const AstRawString*> lexical_bindings(1, zone());
3382 3386
3383 // Create an in-between scope for let-bound iteration variables. 3387 // Create an in-between scope for let-bound iteration variables.
3384 Scope* saved_scope = scope_; 3388 Scope* saved_scope = scope_;
3385 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); 3389 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3386 scope_ = for_scope; 3390 scope_ = for_scope;
3387
3388 Expect(Token::FOR, CHECK_OK); 3391 Expect(Token::FOR, CHECK_OK);
3389 Expect(Token::LPAREN, CHECK_OK); 3392 Expect(Token::LPAREN, CHECK_OK);
3390 for_scope->set_start_position(scanner()->location().beg_pos); 3393 for_scope->set_start_position(scanner()->location().beg_pos);
3391 bool is_let_identifier_expression = false; 3394 bool is_let_identifier_expression = false;
3395 DeclarationParsingResult parsing_result;
3392 if (peek() != Token::SEMICOLON) { 3396 if (peek() != Token::SEMICOLON) {
3393 if (peek() == Token::VAR || 3397 if (peek() == Token::VAR ||
3394 (peek() == Token::CONST && is_sloppy(language_mode()))) { 3398 (peek() == Token::CONST && is_sloppy(language_mode()))) {
3395 const AstRawString* name = NULL; 3399 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
3396 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); 3400 Block* variable_statement =
3397 Scanner::Location bindings_loc = Scanner::Location::invalid(); 3401 parsing_result.BuildInitializationBlock(nullptr, CHECK_OK);
3398 int num_decl; 3402
3399 Block* variable_statement = ParseVariableDeclarations( 3403 int num_decl = parsing_result.declarations.length();
3400 kForStatement, &num_decl, nullptr, &name, &first_initializer_loc,
3401 &bindings_loc, CHECK_OK);
3402 bool accept_IN = num_decl >= 1; 3404 bool accept_IN = num_decl >= 1;
3403 bool accept_OF = true; 3405 bool accept_OF = true;
3404 ForEachStatement::VisitMode mode; 3406 ForEachStatement::VisitMode mode;
3405 int each_beg_pos = scanner()->location().beg_pos; 3407 int each_beg_pos = scanner()->location().beg_pos;
3406 int each_end_pos = scanner()->location().end_pos; 3408 int each_end_pos = scanner()->location().end_pos;
3407 3409
3408 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { 3410 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
3409 if (!*ok) return nullptr; 3411 if (!*ok) return nullptr;
3410 if (num_decl != 1) { 3412 if (num_decl != 1) {
3411 const char* loop_type = 3413 const char* loop_type =
3412 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; 3414 mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
3413 ParserTraits::ReportMessageAt( 3415 ParserTraits::ReportMessageAt(parsing_result.bindings_loc,
3414 bindings_loc, "for_inof_loop_multi_bindings", loop_type); 3416 "for_inof_loop_multi_bindings",
3417 loop_type);
3415 *ok = false; 3418 *ok = false;
3416 return nullptr; 3419 return nullptr;
3417 } 3420 }
3418 if (first_initializer_loc.IsValid() && 3421 if (parsing_result.first_initializer_loc.IsValid() &&
3419 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { 3422 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
3420 if (mode == ForEachStatement::ITERATE) { 3423 if (mode == ForEachStatement::ITERATE) {
3421 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); 3424 ReportMessageAt(parsing_result.first_initializer_loc,
3425 "for_of_loop_initializer");
3422 } else { 3426 } else {
3423 // TODO(caitp): This should be an error in sloppy mode too. 3427 // TODO(caitp): This should be an error in sloppy mode too.
3424 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); 3428 ReportMessageAt(parsing_result.first_initializer_loc,
3429 "for_in_loop_initializer");
3425 } 3430 }
3426 *ok = false; 3431 *ok = false;
3427 return nullptr; 3432 return nullptr;
3428 } 3433 }
3429 ForEachStatement* loop = 3434 ForEachStatement* loop =
3430 factory()->NewForEachStatement(mode, labels, stmt_pos); 3435 factory()->NewForEachStatement(mode, labels, stmt_pos);
3431 Target target(&this->target_stack_, loop); 3436 Target target(&this->target_stack_, loop);
3432 3437
3433 Expression* enumerable = ParseExpression(true, CHECK_OK); 3438 Expression* enumerable = ParseExpression(true, CHECK_OK);
3434 Expect(Token::RPAREN, CHECK_OK); 3439 Expect(Token::RPAREN, CHECK_OK);
3435 3440
3436 VariableProxy* each = 3441 VariableProxy* each = scope_->NewUnresolved(
3437 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); 3442 factory(), parsing_result.SingleName(), each_beg_pos, each_end_pos);
3438 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3443 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3439 InitializeForEachStatement(loop, each, enumerable, body); 3444 InitializeForEachStatement(loop, each, enumerable, body);
3440 Block* result = 3445 Block* result =
3441 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); 3446 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3442 result->AddStatement(variable_statement, zone()); 3447 result->AddStatement(variable_statement, zone());
3443 result->AddStatement(loop, zone()); 3448 result->AddStatement(loop, zone());
3444 scope_ = saved_scope; 3449 scope_ = saved_scope;
3445 for_scope->set_end_position(scanner()->location().end_pos); 3450 for_scope->set_end_position(scanner()->location().end_pos);
3446 for_scope = for_scope->FinalizeBlockScope(); 3451 for_scope = for_scope->FinalizeBlockScope();
3447 DCHECK(for_scope == NULL); 3452 DCHECK(for_scope == NULL);
3448 // Parsed for-in loop w/ variable/const declaration. 3453 // Parsed for-in loop w/ variable/const declaration.
3449 return result; 3454 return result;
3450 } else { 3455 } else {
3451 init = variable_statement; 3456 init = variable_statement;
3452 } 3457 }
3453 } else if ((peek() == Token::LET || peek() == Token::CONST) && 3458 } else if ((peek() == Token::LET || peek() == Token::CONST) &&
3454 is_strict(language_mode())) { 3459 is_strict(language_mode())) {
3455 is_const = peek() == Token::CONST; 3460 is_const = peek() == Token::CONST;
3456 const AstRawString* name = NULL; 3461 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
3457 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); 3462 DCHECK(parsing_result.descriptor.pos != RelocInfo::kNoPosition);
3458 Scanner::Location bindings_loc = Scanner::Location::invalid(); 3463 Block* variable_statement =
3459 int num_decl; 3464 parsing_result.BuildInitializationBlock(&lexical_bindings, CHECK_OK);
3460 Block* variable_statement = ParseVariableDeclarations( 3465
3461 kForStatement, &num_decl, &lexical_bindings, &name, 3466 int num_decl = parsing_result.declarations.length();
3462 &first_initializer_loc, &bindings_loc, CHECK_OK);
3463 bool accept_IN = num_decl >= 1; 3467 bool accept_IN = num_decl >= 1;
3464 bool accept_OF = true; 3468 bool accept_OF = true;
3465 ForEachStatement::VisitMode mode; 3469 ForEachStatement::VisitMode mode;
3466 int each_beg_pos = scanner()->location().beg_pos; 3470 int each_beg_pos = scanner()->location().beg_pos;
3467 int each_end_pos = scanner()->location().end_pos; 3471 int each_end_pos = scanner()->location().end_pos;
3468 3472
3469 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { 3473 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) {
3470 if (!*ok) return nullptr; 3474 if (!*ok) return nullptr;
3471 if (num_decl != 1) { 3475 if (num_decl != 1) {
3472 const char* loop_type = 3476 const char* loop_type =
3473 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; 3477 mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
3474 ParserTraits::ReportMessageAt( 3478 ParserTraits::ReportMessageAt(parsing_result.bindings_loc,
3475 bindings_loc, "for_inof_loop_multi_bindings", loop_type); 3479 "for_inof_loop_multi_bindings",
3480 loop_type);
3476 *ok = false; 3481 *ok = false;
3477 return nullptr; 3482 return nullptr;
3478 } 3483 }
3479 if (first_initializer_loc.IsValid() && 3484 if (parsing_result.first_initializer_loc.IsValid() &&
3480 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { 3485 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
3481 if (mode == ForEachStatement::ITERATE) { 3486 if (mode == ForEachStatement::ITERATE) {
3482 ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); 3487 ReportMessageAt(parsing_result.first_initializer_loc,
3488 "for_of_loop_initializer");
3483 } else { 3489 } else {
3484 ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); 3490 ReportMessageAt(parsing_result.first_initializer_loc,
3491 "for_in_loop_initializer");
3485 } 3492 }
3486 *ok = false; 3493 *ok = false;
3487 return nullptr; 3494 return nullptr;
3488 } 3495 }
3489 // Rewrite a for-in statement of the form 3496 // Rewrite a for-in statement of the form
3490 // 3497 //
3491 // for (let/const x in e) b 3498 // for (let/const x in e) b
3492 // 3499 //
3493 // into 3500 // into
3494 // 3501 //
(...skipping 13 matching lines...) Expand all
3508 ForEachStatement* loop = 3515 ForEachStatement* loop =
3509 factory()->NewForEachStatement(mode, labels, stmt_pos); 3516 factory()->NewForEachStatement(mode, labels, stmt_pos);
3510 Target target(&this->target_stack_, loop); 3517 Target target(&this->target_stack_, loop);
3511 3518
3512 // The expression does not see the loop variable. 3519 // The expression does not see the loop variable.
3513 scope_ = saved_scope; 3520 scope_ = saved_scope;
3514 Expression* enumerable = ParseExpression(true, CHECK_OK); 3521 Expression* enumerable = ParseExpression(true, CHECK_OK);
3515 scope_ = for_scope; 3522 scope_ = for_scope;
3516 Expect(Token::RPAREN, CHECK_OK); 3523 Expect(Token::RPAREN, CHECK_OK);
3517 3524
3518 VariableProxy* each = 3525 VariableProxy* each = scope_->NewUnresolved(
3519 scope_->NewUnresolved(factory(), name, each_beg_pos, each_end_pos); 3526 factory(), parsing_result.SingleName(), each_end_pos);
3520 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3527 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3521 Block* body_block = 3528 Block* body_block =
3522 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); 3529 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3523 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; 3530 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN;
3524 Assignment* assignment = factory()->NewAssignment( 3531 Assignment* assignment = factory()->NewAssignment(
3525 init_op, each, temp_proxy, RelocInfo::kNoPosition); 3532 init_op, each, temp_proxy, RelocInfo::kNoPosition);
3526 Statement* assignment_statement = factory()->NewExpressionStatement( 3533 Statement* assignment_statement = factory()->NewExpressionStatement(
3527 assignment, RelocInfo::kNoPosition); 3534 assignment, RelocInfo::kNoPosition);
3528 body_block->AddStatement(variable_statement, zone()); 3535 body_block->AddStatement(variable_statement, zone());
3529 body_block->AddStatement(assignment_statement, zone()); 3536 body_block->AddStatement(assignment_statement, zone());
(...skipping 2211 matching lines...) Expand 10 before | Expand all | Expand 10 after
5741 5748
5742 Expression* Parser::SpreadCallNew(Expression* function, 5749 Expression* Parser::SpreadCallNew(Expression* function,
5743 ZoneList<v8::internal::Expression*>* args, 5750 ZoneList<v8::internal::Expression*>* args,
5744 int pos) { 5751 int pos) {
5745 args->InsertAt(0, function, zone()); 5752 args->InsertAt(0, function, zone());
5746 5753
5747 return factory()->NewCallRuntime( 5754 return factory()->NewCallRuntime(
5748 ast_value_factory()->reflect_construct_string(), NULL, args, pos); 5755 ast_value_factory()->reflect_construct_string(), NULL, args, pos);
5749 } 5756 }
5750 } } // namespace v8::internal 5757 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/pattern-rewriter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698