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

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

Powered by Google App Engine
This is Rietveld 408576698