Bug 725702: support for of loops in Reflect.parse r=dherman

This commit is contained in:
Benjamin Peterson 2012-07-18 18:14:15 -04:00
parent ae53abdf98
commit 0f84266c79
3 changed files with 50 additions and 14 deletions

View File

@ -48,6 +48,7 @@ ASTDEF(AST_WHILE_STMT, "WhileStatement", "whileStatem
ASTDEF(AST_DO_STMT, "DoWhileStatement", "doWhileStatement")
ASTDEF(AST_FOR_STMT, "ForStatement", "forStatement")
ASTDEF(AST_FOR_IN_STMT, "ForInStatement", "forInStatement")
ASTDEF(AST_FOR_OF_STMT, "ForOfStatement", "forOfStatement")
ASTDEF(AST_BREAK_STMT, "BreakStatement", "breakStatement")
ASTDEF(AST_CONTINUE_STMT, "ContinueStatement", "continueStatement")
ASTDEF(AST_WITH_STMT, "WithStatement", "withStatement")

View File

@ -496,6 +496,9 @@ class NodeBuilder
bool forInStatement(Value var, Value expr, Value stmt,
bool isForEach, TokenPos *pos, Value *dst);
bool forOfStatement(Value var, Value expr, Value stmt, TokenPos *pos, Value *dst);
bool withStatement(Value expr, Value stmt, TokenPos *pos, Value *dst);
bool whileStatement(Value test, Value stmt, TokenPos *pos, Value *dst);
@ -839,6 +842,20 @@ NodeBuilder::forInStatement(Value var, Value expr, Value stmt, bool isForEach,
dst);
}
bool
NodeBuilder::forOfStatement(Value var, Value expr, Value stmt, TokenPos *pos, Value *dst)
{
Value cb = callbacks[AST_FOR_OF_STMT];
if (!cb.isNull())
return callback(cb, var, expr, stmt, pos, dst);
return newNode(AST_FOR_OF_STMT, pos,
"left", var,
"right", expr,
"body", stmt,
dst);
}
bool
NodeBuilder::withStatement(Value expr, Value stmt, TokenPos *pos, Value *dst)
{
@ -1612,6 +1629,7 @@ class ASTSerializer
}
bool forInit(ParseNode *pn, Value *dst);
bool forOfOrIn(ParseNode *loop, ParseNode *head, Value var, Value stmt, Value *dst);
bool statement(ParseNode *pn, Value *dst);
bool blockStatement(ParseNode *pn, Value *dst);
bool switchStatement(ParseNode *pn, Value *dst);
@ -2072,6 +2090,19 @@ ASTSerializer::forInit(ParseNode *pn, Value *dst)
: expression(pn, dst);
}
bool
ASTSerializer::forOfOrIn(ParseNode *loop, ParseNode *head, Value var, Value stmt, Value *dst)
{
Value expr;
bool isForEach = loop->pn_iflags & JSITER_FOREACH;
bool isForOf = loop->pn_iflags & JSITER_FOR_OF;
JS_ASSERT(!isForOf || !isForEach);
return expression(head->pn_kid3, &expr) &&
(isForOf ? builder.forOfStatement(var, expr, stmt, &loop->pn_pos, dst) :
builder.forInStatement(var, expr, stmt, isForEach, &loop->pn_pos, dst));
}
bool
ASTSerializer::statement(ParseNode *pn, Value *dst)
{
@ -2153,18 +2184,14 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
if (!statement(pn->pn_right, &stmt))
return false;
bool isForEach = pn->pn_iflags & JSITER_FOREACH;
if (head->isKind(PNK_FORIN)) {
Value var, expr;
Value var;
return (!head->pn_kid1
? pattern(head->pn_kid2, NULL, &var)
: head->pn_kid1->isKind(PNK_LEXICALSCOPE)
? variableDeclaration(head->pn_kid1->pn_expr, true, &var)
: variableDeclaration(head->pn_kid1, false, &var)) &&
expression(head->pn_kid3, &expr) &&
builder.forInStatement(var, expr, stmt, isForEach, &pn->pn_pos, dst);
? variableDeclaration(head->pn_kid1->pn_expr, true, &var)
: variableDeclaration(head->pn_kid1, false, &var)) &&
forOfOrIn(pn, head, var, stmt, dst);
}
Value init, test, update;
@ -2192,13 +2219,9 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
ParseNode *head = loop->pn_left;
JS_ASSERT(head->isKind(PNK_FORIN));
bool isForEach = loop->pn_iflags & JSITER_FOREACH;
Value stmt;
Value expr, stmt;
return expression(head->pn_kid3, &expr) &&
statement(loop->pn_right, &stmt) &&
builder.forInStatement(var, expr, stmt, isForEach, &pn->pn_pos, dst);
return statement(loop->pn_right, &stmt) && forOfOrIn(loop, head, var, stmt, dst);
}
case PNK_BREAK:

View File

@ -47,6 +47,7 @@ function ident(name) Pattern({ type: "Identifier", name: name })
function dotExpr(obj, id) Pattern({ type: "MemberExpression", computed: false, object: obj, property: id })
function memExpr(obj, id) Pattern({ type: "MemberExpression", computed: true, object: obj, property: id })
function forStmt(init, test, update, body) Pattern({ type: "ForStatement", init: init, test: test, update: update, body: body })
function forOfStmt(lhs, rhs, body) Pattern({ type: "ForOfStatement", left: lhs, right: rhs, body: body })
function forInStmt(lhs, rhs, body) Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: false })
function forEachInStmt(lhs, rhs, body) Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: true })
function breakStmt(lab) Pattern({ type: "BreakStatement", label: lab })
@ -648,6 +649,12 @@ assertStmt("for ({a:x,b:y,c:z} in foo);", forInStmt(axbycz, ident("foo"), emptyS
assertStmt("for (var [x,y,z] in foo);", forInStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for (let [x,y,z] in foo);", forInStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for ([x,y,z] in foo);", forInStmt(xyz, ident("foo"), emptyStmt));
assertStmt("for (var {a:x,b:y,c:z} of foo);", forOfStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for (let {a:x,b:y,c:z} of foo);", forOfStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for ({a:x,b:y,c:z} of foo);", forOfStmt(axbycz, ident("foo"), emptyStmt));
assertStmt("for (var [x,y,z] of foo);", forOfStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for (let [x,y,z] of foo);", forOfStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for ([x,y,z] of foo);", forOfStmt(xyz, ident("foo"), emptyStmt));
assertStmt("for each (var {a:x,b:y,c:z} in foo);", forEachInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for each (let {a:x,b:y,c:z} in foo);", forEachInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
assertStmt("for each ({a:x,b:y,c:z} in foo);", forEachInStmt(axbycz, ident("foo"), emptyStmt));
@ -657,6 +664,9 @@ assertStmt("for each ([x,y,z] in foo);", forEachInStmt(xyz, ident("foo"), emptyS
assertError("for (const x in foo);", SyntaxError);
assertError("for (const {a:x,b:y,c:z} in foo);", SyntaxError);
assertError("for (const [x,y,z] in foo);", SyntaxError);
assertError("for (const x of foo);", SyntaxError);
assertError("for (const {a:x,b:y,c:z} of foo);", SyntaxError);
assertError("for (const [x,y,z] of foo);", SyntaxError);
assertError("for each (const x in foo);", SyntaxError);
assertError("for each (const {a:x,b:y,c:z} in foo);", SyntaxError);
assertError("for each (const [x,y,z] in foo);", SyntaxError);
@ -665,6 +675,8 @@ assertError("for each (const [x,y,z] in foo);", SyntaxError);
assertStmt("for (var {a:x,b:y,c:z} = 22 in foo);", forInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for (var [x,y,z] = 22 in foo);", forInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for (var {a:x,b:y,c:z} = 22 of foo);", forOfStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for (var [x,y,z] = 22 of foo);", forOfStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for each (var {a:x,b:y,c:z} = 22 in foo);", forEachInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for each (var [x,y,z] = 22 in foo);", forEachInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
assertError("for (x = 22 in foo);", SyntaxError);