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

Side by Side Diff: src/parser.cc

Issue 1361403003: Implement ES6 completion semantics (--harmony-completion). (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address comments. Created 5 years, 2 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/parser.h" 5 #include "src/parser.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/ast-literal-reindexer.h" 9 #include "src/ast-literal-reindexer.h"
10 #include "src/bailout-reason.h" 10 #include "src/bailout-reason.h"
(...skipping 3315 matching lines...) Expand 10 before | Expand all | Expand 10 after
3326 } else { 3326 } else {
3327 stmt->Initialize(each, subject, body); 3327 stmt->Initialize(each, subject, body);
3328 } 3328 }
3329 } 3329 }
3330 3330
3331 3331
3332 Statement* Parser::DesugarLexicalBindingsInForStatement( 3332 Statement* Parser::DesugarLexicalBindingsInForStatement(
3333 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, 3333 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names,
3334 ForStatement* loop, Statement* init, Expression* cond, Statement* next, 3334 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
3335 Statement* body, bool* ok) { 3335 Statement* body, bool* ok) {
3336 // ES6 13.6.3.4 specifies that on each loop iteration the let variables are 3336 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
3337 // copied into a new environment. After copying, the "next" statement of the 3337 // copied into a new environment. Moreover, the "next" statement must be
3338 // loop is executed to update the loop variables. The loop condition is 3338 // evaluated not in the environment of the just completed iteration but in
3339 // checked and the loop body is executed. 3339 // that of the upcoming one. We achieve this with the following desugaring.
3340 // Extra care is needed to preserve the completion value of the original loop.
3340 // 3341 //
3341 // We rewrite a for statement of the form 3342 // We are given a for statement of the form
3342 // 3343 //
3343 // labels: for (let/const x = i; cond; next) body 3344 // labels: for (let/const x = i; cond; next) body
3344 // 3345 //
3345 // into 3346 // and rewrite it as follows. Here we write {{ ... }} for blocks whose
rossberg 2015/10/07 12:28:46 Nit: ...for "init-blocks", whose...
neis 2015/10/08 12:57:24 Done.
3347 // completion value is ignored.
3346 // 3348 //
3347 // { 3349 // {
3348 // let/const x = i; 3350 // let/const x = i;
3349 // temp_x = x; 3351 // temp_x = x;
3350 // first = 1; 3352 // first = 1;
3351 // undefined; 3353 // undefined;
3352 // outer: for (;;) { 3354 // outer: for (;;) {
3353 // { // This block's only function is to ensure that the statements it 3355 // let/const x = temp_x;
3354 // // contains do not affect the normal completion value. This is 3356 // {{ if (first == 1) {
3355 // // accomplished by setting its ignore_completion_value bit. 3357 // first = 0;
3356 // // No new lexical scope is introduced, so lexically scoped variables 3358 // } else {
3357 // // declared here will be scoped to the outer for loop. 3359 // next;
3358 // let/const x = temp_x; 3360 // }
3359 // if (first == 1) { 3361 // flag = 1;
3360 // first = 0; 3362 // if (!cond) break;
3361 // } else { 3363 // }}
3362 // next; 3364 // labels: for (; flag == 1; flag = 0, temp_x = x) {
3363 // } 3365 // body
3364 // flag = 1;
3365 // } 3366 // }
3366 // labels: for (; flag == 1; flag = 0, temp_x = x) { 3367 // {{ if (flag == 1) // Body used break.
3367 // if (cond) { 3368 // break;
3368 // body 3369 // }}
3369 // } else {
3370 // break outer;
3371 // }
3372 // }
3373 // if (flag == 1) {
3374 // break;
3375 // }
3376 // } 3370 // }
3377 // } 3371 // }
3378 3372
3379 DCHECK(names->length() > 0); 3373 DCHECK(names->length() > 0);
3380 Scope* for_scope = scope_; 3374 Scope* for_scope = scope_;
3381 ZoneList<Variable*> temps(names->length(), zone()); 3375 ZoneList<Variable*> temps(names->length(), zone());
3382 3376
3383 Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false, 3377 Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false,
3384 RelocInfo::kNoPosition); 3378 RelocInfo::kNoPosition);
3385 3379
3386 // Add statement: let/const x = i. 3380 // Add statement: let/const x = i.
3387 outer_block->statements()->Add(init, zone()); 3381 outer_block->statements()->Add(init, zone());
3388 3382
3389 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); 3383 const AstRawString* temp_name = ast_value_factory()->dot_for_string();
3390 3384
3391 // For each lexical variable x: 3385 // For each lexical variable x:
3392 // make statement: temp_x = x. 3386 // make statement: temp_x = x.
3393 for (int i = 0; i < names->length(); i++) { 3387 for (int i = 0; i < names->length(); i++) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3430 ForStatement* outer_loop = 3424 ForStatement* outer_loop =
3431 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); 3425 factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
3432 outer_block->statements()->Add(outer_loop, zone()); 3426 outer_block->statements()->Add(outer_loop, zone());
3433 3427
3434 outer_block->set_scope(for_scope); 3428 outer_block->set_scope(for_scope);
3435 scope_ = inner_scope; 3429 scope_ = inner_scope;
3436 3430
3437 Block* inner_block = 3431 Block* inner_block =
3438 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); 3432 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3439 Block* ignore_completion_block = factory()->NewBlock( 3433 Block* ignore_completion_block = factory()->NewBlock(
3440 NULL, names->length() + 2, true, RelocInfo::kNoPosition); 3434 NULL, names->length() + 3, true, RelocInfo::kNoPosition);
3441 ZoneList<Variable*> inner_vars(names->length(), zone()); 3435 ZoneList<Variable*> inner_vars(names->length(), zone());
3442 // For each let variable x: 3436 // For each let variable x:
3443 // make statement: let/const x = temp_x. 3437 // make statement: let/const x = temp_x.
3444 VariableMode mode = is_const ? CONST : LET; 3438 VariableMode mode = is_const ? CONST : LET;
3445 for (int i = 0; i < names->length(); i++) { 3439 for (int i = 0; i < names->length(); i++) {
3446 VariableProxy* proxy = NewUnresolved(names->at(i), mode); 3440 VariableProxy* proxy = NewUnresolved(names->at(i), mode);
3447 Declaration* declaration = factory()->NewVariableDeclaration( 3441 Declaration* declaration = factory()->NewVariableDeclaration(
3448 proxy, mode, scope_, RelocInfo::kNoPosition); 3442 proxy, mode, scope_, RelocInfo::kNoPosition);
3449 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); 3443 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
3450 inner_vars.Add(declaration->proxy()->var(), zone()); 3444 inner_vars.Add(declaration->proxy()->var(), zone());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3489 // Make statement: flag = 1. 3483 // Make statement: flag = 1.
3490 { 3484 {
3491 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); 3485 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3492 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); 3486 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3493 Assignment* assignment = factory()->NewAssignment( 3487 Assignment* assignment = factory()->NewAssignment(
3494 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition); 3488 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
3495 Statement* assignment_statement = 3489 Statement* assignment_statement =
3496 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); 3490 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3497 ignore_completion_block->statements()->Add(assignment_statement, zone()); 3491 ignore_completion_block->statements()->Add(assignment_statement, zone());
3498 } 3492 }
3493
3494 // Make statement: if (!cond) break.
3495 if (cond) {
3496 Statement* stop =
3497 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3498 Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3499 ignore_completion_block->statements()->Add(
3500 factory()->NewIfStatement(cond, noop, stop, cond->position()), zone());
3501 }
3502
3499 inner_block->statements()->Add(ignore_completion_block, zone()); 3503 inner_block->statements()->Add(ignore_completion_block, zone());
3500 // Make cond expression for main loop: flag == 1. 3504 // Make cond expression for main loop: flag == 1.
3501 Expression* flag_cond = NULL; 3505 Expression* flag_cond = NULL;
3502 { 3506 {
3503 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); 3507 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3504 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); 3508 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3505 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, 3509 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
3506 RelocInfo::kNoPosition); 3510 RelocInfo::kNoPosition);
3507 } 3511 }
3508 3512
(...skipping 18 matching lines...) Expand all
3527 Assignment* assignment = factory()->NewAssignment( 3531 Assignment* assignment = factory()->NewAssignment(
3528 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); 3532 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3529 compound_next = factory()->NewBinaryOperation( 3533 compound_next = factory()->NewBinaryOperation(
3530 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition); 3534 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition);
3531 } 3535 }
3532 3536
3533 compound_next_statement = factory()->NewExpressionStatement( 3537 compound_next_statement = factory()->NewExpressionStatement(
3534 compound_next, RelocInfo::kNoPosition); 3538 compound_next, RelocInfo::kNoPosition);
3535 } 3539 }
3536 3540
3537 // Make statement: if (cond) { body; } else { break outer; }
3538 Statement* body_or_stop = body;
3539 if (cond) {
3540 Statement* stop =
3541 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3542 body_or_stop =
3543 factory()->NewIfStatement(cond, body, stop, cond->position());
3544 }
3545
3546 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x) 3541 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
3547 // Note that we re-use the original loop node, which retains its labels 3542 // Note that we re-use the original loop node, which retains its labels
3548 // and ensures that any break or continue statements in body point to 3543 // and ensures that any break or continue statements in body point to
3549 // the right place. 3544 // the right place.
3550 loop->Initialize(NULL, flag_cond, compound_next_statement, body_or_stop); 3545 loop->Initialize(NULL, flag_cond, compound_next_statement, body);
3551 inner_block->statements()->Add(loop, zone()); 3546 inner_block->statements()->Add(loop, zone());
3552 3547
3553 // Make statement: if (flag == 1) { break; } 3548 // Make statement: {{if (flag == 1) break;}}
3554 { 3549 {
3555 Expression* compare = NULL; 3550 Expression* compare = NULL;
3556 // Make compare expresion: flag == 1. 3551 // Make compare expresion: flag == 1.
3557 { 3552 {
3558 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); 3553 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3559 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); 3554 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3560 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, 3555 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
3561 RelocInfo::kNoPosition); 3556 RelocInfo::kNoPosition);
3562 } 3557 }
3563 Statement* stop = 3558 Statement* stop =
3564 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); 3559 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3565 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); 3560 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3566 Statement* if_flag_break = 3561 Statement* if_flag_break =
3567 factory()->NewIfStatement(compare, stop, empty, RelocInfo::kNoPosition); 3562 factory()->NewIfStatement(compare, stop, empty, RelocInfo::kNoPosition);
3568 inner_block->statements()->Add(if_flag_break, zone()); 3563 Block* ignore_completion_block =
3564 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
3565 ignore_completion_block->statements()->Add(if_flag_break, zone());
3566 inner_block->statements()->Add(ignore_completion_block, zone());
3569 } 3567 }
3570 3568
3571 inner_scope->set_end_position(scanner()->location().end_pos); 3569 inner_scope->set_end_position(scanner()->location().end_pos);
3572 inner_block->set_scope(inner_scope); 3570 inner_block->set_scope(inner_scope);
3573 scope_ = for_scope; 3571 scope_ = for_scope;
3574 3572
3575 outer_loop->Initialize(NULL, NULL, NULL, inner_block); 3573 outer_loop->Initialize(NULL, NULL, NULL, inner_block);
3576 return outer_block; 3574 return outer_block;
3577 } 3575 }
3578 3576
(...skipping 2740 matching lines...) Expand 10 before | Expand all | Expand 10 after
6319 6317
6320 Expression* Parser::SpreadCallNew(Expression* function, 6318 Expression* Parser::SpreadCallNew(Expression* function,
6321 ZoneList<v8::internal::Expression*>* args, 6319 ZoneList<v8::internal::Expression*>* args,
6322 int pos) { 6320 int pos) {
6323 args->InsertAt(0, function, zone()); 6321 args->InsertAt(0, function, zone());
6324 6322
6325 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); 6323 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
6326 } 6324 }
6327 } // namespace internal 6325 } // namespace internal
6328 } // namespace v8 6326 } // namespace v8
OLDNEW
« no previous file with comments | « src/flag-definitions.h ('k') | src/rewriter.cc » ('j') | test/mjsunit/harmony/completion.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698