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

Unified 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: Proper rebase. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/flag-definitions.h ('k') | src/rewriter.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 9113e8c7a4e3ba46b936b38d1f4627ff0c426cf4..7cf81c4f0569b0d770bf6751cc3f26a814a2a9aa 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -3339,16 +3339,18 @@ 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
- // 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.
+ // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
+ // copied into a new environment. Moreover, the "next" statement must be
+ // evaluated not in the environment of the just completed iteration but in
+ // that of the upcoming one. We achieve this with the following desugaring.
+ // Extra care is needed to preserve the completion value of the original loop.
//
- // We rewrite a for statement of the form
+ // We are given a for statement of the form
//
// labels: for (let/const x = i; cond; next) body
//
- // into
+ // and rewrite it as follows. Here we write {{ ... }} for init-blocks, ie.,
+ // blocks whose ignore_completion_value_ flag is set.
//
// {
// let/const x = i;
@@ -3356,29 +3358,21 @@ 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;
- // }
+ // let/const x = temp_x;
+ // {{ 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;
+ // }}
// }
// }
@@ -3386,7 +3380,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
Scope* for_scope = scope_;
ZoneList<Variable*> temps(names->length(), zone());
- Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false,
+ Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false,
RelocInfo::kNoPosition);
// Add statement: let/const x = i.
@@ -3443,7 +3437,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.
@@ -3502,6 +3496,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;
@@ -3540,23 +3544,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.
@@ -3571,7 +3566,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);
« no previous file with comments | « src/flag-definitions.h ('k') | src/rewriter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698