Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index f122d9aa5e4b57ff1459cfa48e060c666bd407ff..c1408048cb3dda1f45b58fdf98a59f1a5e7ddfdc 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -3333,7 +3333,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
| Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, |
| ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
| Statement* body, bool* ok) { |
| - // ES6 13.6.3.4 specifies that on each loop iteration the let variables are |
| + // ES6 13.7.4.8 specifies that on each loop iteration the let variables are |
| // copied into a new environment. After copying, the "next" statement of the |
| // loop is executed to update the loop variables. The loop condition is |
| // checked and the loop body is executed. |
| @@ -3350,31 +3350,27 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
| // first = 1; |
| // undefined; |
| // outer: for (;;) { |
| - // { // This block's only function is to ensure that the statements it |
| - // // contains do not affect the normal completion value. This is |
| - // // accomplished by setting its ignore_completion_value bit. |
| - // // No new lexical scope is introduced, so lexically scoped variables |
| - // // declared here will be scoped to the outer for loop. |
| - // let/const x = temp_x; |
| - // if (first == 1) { |
| - // first = 0; |
| - // } else { |
| - // next; |
| - // } |
| - // flag = 1; |
| - // } |
| + // {{ // No new lexical scope is introduced, so lexically scoped |
| + // // variables declared here will be scoped to the outer for loop. |
| + // let/const x = temp_x; |
|
rossberg
2015/10/05 11:33:00
Can you just move this declaration out of the bloc
neis
2015/10/07 11:58:40
Done.
|
| + // if (first == 1) { |
| + // first = 0; |
| + // } else { |
| + // next; |
| + // } |
| + // flag = 1; |
| + // if (!cond) break; |
| + // }} |
| // labels: for (; flag == 1; flag = 0, temp_x = x) { |
| - // if (cond) { |
| - // body |
| - // } else { |
| - // break outer; |
| - // } |
| - // } |
| - // if (flag == 1) { |
| - // break; |
| + // body |
| // } |
| + // {{ if (flag == 1) // Body used break. |
| + // break; |
| + // }} |
| // } |
| // } |
| + // |
| + // We write {{ ... }} for blocks whose completion value is ignored. |
|
rossberg
2015/10/05 11:33:00
Nit: move this comment to the top, since it's easy
neis
2015/10/07 11:58:40
Done.
|
| DCHECK(names->length() > 0); |
| Scope* for_scope = scope_; |
| @@ -3437,7 +3433,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
| Block* inner_block = |
| factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
| Block* ignore_completion_block = factory()->NewBlock( |
| - NULL, names->length() + 2, true, RelocInfo::kNoPosition); |
| + NULL, names->length() + 3, true, RelocInfo::kNoPosition); |
| ZoneList<Variable*> inner_vars(names->length(), zone()); |
| // For each let variable x: |
| // make statement: let/const x = temp_x. |
| @@ -3496,6 +3492,16 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
| factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| ignore_completion_block->statements()->Add(assignment_statement, zone()); |
| } |
| + |
| + // Make statement: if (!cond) break. |
| + if (cond) { |
| + Statement* stop = |
| + factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); |
| + Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
| + ignore_completion_block->statements()->Add( |
| + factory()->NewIfStatement(cond, noop, stop, cond->position()), zone()); |
| + } |
| + |
| inner_block->statements()->Add(ignore_completion_block, zone()); |
| // Make cond expression for main loop: flag == 1. |
| Expression* flag_cond = NULL; |
| @@ -3534,23 +3540,14 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
| compound_next, RelocInfo::kNoPosition); |
| } |
| - // Make statement: if (cond) { body; } else { break outer; } |
| - Statement* body_or_stop = body; |
| - if (cond) { |
| - Statement* stop = |
| - factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); |
| - body_or_stop = |
| - factory()->NewIfStatement(cond, body, stop, cond->position()); |
| - } |
| - |
| // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x) |
| // Note that we re-use the original loop node, which retains its labels |
| // and ensures that any break or continue statements in body point to |
| // the right place. |
| - loop->Initialize(NULL, flag_cond, compound_next_statement, body_or_stop); |
| + loop->Initialize(NULL, flag_cond, compound_next_statement, body); |
| inner_block->statements()->Add(loop, zone()); |
| - // Make statement: if (flag == 1) { break; } |
| + // Make statement: {{if (flag == 1) break;}} |
| { |
| Expression* compare = NULL; |
| // Make compare expresion: flag == 1. |
| @@ -3565,7 +3562,10 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
| Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
| Statement* if_flag_break = |
| factory()->NewIfStatement(compare, stop, empty, RelocInfo::kNoPosition); |
| - inner_block->statements()->Add(if_flag_break, zone()); |
| + Block* ignore_completion_block = |
| + factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); |
| + ignore_completion_block->statements()->Add(if_flag_break, zone()); |
| + inner_block->statements()->Add(ignore_completion_block, zone()); |
| } |
| inner_scope->set_end_position(scanner()->location().end_pos); |