Bug 1220564 - Remove legacy generator comprehensions. (r=Waldo)

This commit is contained in:
Shu-yu Guo 2016-01-06 16:02:15 -08:00
parent 69567444e9
commit 573d343e70
5 changed files with 16 additions and 158 deletions

View File

@ -2977,10 +2977,8 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
builder.unaryExpression(op, expr, &pn->pn_pos, dst);
}
#if JS_HAS_GENERATOR_EXPRS
case PNK_GENEXP:
return generatorExpression(pn->generatorExpr(), dst);
#endif
case PNK_NEW:
case PNK_TAGGED_TEMPLATE:

View File

@ -839,7 +839,6 @@ class ParseNode
/* Return true if this node appears in a Directive Prologue. */
bool isDirectivePrologueMember() const { return pn_prologue; }
#ifdef JS_HAS_GENERATOR_EXPRS
ParseNode* generatorExpr() const {
MOZ_ASSERT(isKind(PNK_GENEXP));
ParseNode* callee = this->pn_head;
@ -849,7 +848,6 @@ class ParseNode
body->last()->isKind(PNK_COMPREHENSIONFOR));
return body->last();
}
#endif
inline void markAsAssigned();

View File

@ -6397,7 +6397,7 @@ Parser<ParseHandler>::yieldExpression(InHandling inHandling)
case LegacyGenerator:
{
// We are in a legacy generator: a function that has already seen a
// yield, or in a legacy generator comprehension.
// yield.
MOZ_ASSERT(pc->sc->isFunctionBox());
pc->lastYieldOffset = begin;
@ -8467,12 +8467,8 @@ Parser<SyntaxParseHandler>::legacyArrayComprehension(Node array)
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKind,
unsigned begin, Node innerExpr)
Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin)
{
MOZ_ASSERT(comprehensionKind == LegacyGenerator || comprehensionKind == StarGenerator);
MOZ_ASSERT(!!innerExpr == (comprehensionKind == LegacyGenerator));
Node genfn = handler.newFunctionDefinition();
if (!genfn)
return null();
@ -8484,21 +8480,19 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
// already been created by js::StartOffThreadParseScript, so cx will not
// be necessary.
RootedObject proto(context);
if (comprehensionKind == StarGenerator) {
JSContext* cx = context->maybeJSContext();
proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, context->global());
if (!proto)
return null();
}
JSContext* cx = context->maybeJSContext();
proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, context->global());
if (!proto)
return null();
RootedFunction fun(context, newFunction(/* atom = */ nullptr, Expression,
comprehensionKind, proto));
StarGenerator, proto));
if (!fun)
return null();
// Create box for fun->object early to root it.
Directives directives(/* strict = */ outerpc->sc->strict());
FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, comprehensionKind);
FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, StarGenerator);
if (!genFunbox)
return null();
@ -8519,7 +8513,6 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
if (outerpc->sc->isFunctionBox())
genFunbox->funCxFlags = outerpc->sc->asFunctionBox()->funCxFlags;
MOZ_ASSERT(genFunbox->generatorKind() == comprehensionKind);
handler.setBlockId(genfn, genpc.bodyid);
Node generator = newName(context->names().dotGenerator);
@ -8532,21 +8525,11 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
if (!body)
return null();
Node comp;
if (comprehensionKind == StarGenerator) {
comp = comprehension(StarGenerator);
if (!comp)
return null();
} else {
MOZ_ASSERT(comprehensionKind == LegacyGenerator);
comp = legacyComprehensionTail(innerExpr, outerpc->blockid(), LegacyGenerator,
outerpc, LegacyComprehensionHeadBlockScopeDepth(outerpc));
if (!comp)
return null();
}
Node comp = comprehension(StarGenerator);
if (!comp)
return null();
if (comprehensionKind == StarGenerator)
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
handler.setBeginPosition(comp, begin);
handler.setEndPosition(comp, pos().end);
@ -8576,49 +8559,6 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
return genfn;
}
#if JS_HAS_GENERATOR_EXPRS
/*
* Starting from a |for| keyword after an expression, parse the comprehension
* tail completing this generator expression. Wrap the expression |expr| in a
* generator function that is immediately called to evaluate to the generator
* iterator that is the value of this legacy generator expression.
*
* |expr| must be the expression before the |for| keyword; we return an
* application of a generator function that includes the |for| loops and
* |if| guards, with |expr| as the operand of a |yield| expression as the
* innermost loop body.
*
* Unlike Python, we do not evaluate the expression to the right of the first
* |in| in the chain of |for| heads. Instead, a generator expression is merely
* sugar for a generator function expression and its application.
*/
template <>
ParseNode*
Parser<FullParseHandler>::legacyGeneratorExpr(ParseNode* expr)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
// Make a new node for the desugared generator function.
ParseNode* genfn = generatorComprehensionLambda(LegacyGenerator, expr->pn_pos.begin, expr);
if (!genfn)
return null();
// Our result is a call expression that invokes the anonymous generator
// function object.
return handler.newList(PNK_GENEXP, genfn, JSOP_CALL);
}
template <>
SyntaxParseHandler::Node
Parser<SyntaxParseHandler>::legacyGeneratorExpr(Node kid)
{
JS_ALWAYS_FALSE(abortIfSyntaxParser());
return SyntaxParseHandler::NodeFailure;
}
#endif /* JS_HAS_GENERATOR_EXPRS */
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind)
@ -8815,7 +8755,7 @@ Parser<ParseHandler>::generatorComprehension(uint32_t begin)
if (!abortIfSyntaxParser())
return null();
Node genfn = generatorComprehensionLambda(StarGenerator, begin, null());
Node genfn = generatorComprehensionLambda(begin);
if (!genfn)
return null();
@ -8857,9 +8797,6 @@ Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, Node listNode, b
return true;
}
uint32_t startYieldOffset = pc->lastYieldOffset;
bool arg0 = true;
while (true) {
bool spread = false;
uint32_t begin = 0;
@ -8889,34 +8826,6 @@ Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, Node listNode, b
return false;
}
}
#if JS_HAS_GENERATOR_EXPRS
if (!spread) {
if (!tokenStream.matchToken(&matched, TOK_FOR))
return false;
if (matched) {
if (pc->lastYieldOffset != startYieldOffset) {
reportWithOffset(ParseError, false, pc->lastYieldOffset,
JSMSG_BAD_GENEXP_BODY, js_yield_str);
return false;
}
argNode = legacyGeneratorExpr(argNode);
if (!argNode)
return false;
if (!arg0) {
report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX);
return false;
}
TokenKind tt;
if (!tokenStream.peekToken(&tt))
return false;
if (tt == TOK_COMMA) {
report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX);
return false;
}
}
}
#endif
arg0 = false;
handler.addList(listNode, argNode);
@ -9890,58 +9799,13 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
}
}
// Legacy generator comprehensions can appear anywhere an expression is
// enclosed in parentheses, even if those parentheses are part of statement
// syntax or a function call:
//
// if (_)
// while (_) {}
// do {} while (_)
// switch (_) {}
// with (_) {}
// foo(_) // must be first and only argument
//
// This is not the case for also-nonstandard ES6-era generator comprehensions.
// Those must be enclosed in PrimaryExpression parentheses.
//
// sum(x*x for (x in y)); // ok
// sum(for (x of y) x*x); // SyntaxError: needs more parens
//
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
uint32_t begin = pos().begin;
uint32_t startYieldOffset = pc->lastYieldOffset;
Node pn = expr(inHandling, yieldHandling, tripledotHandling, PredictInvoked);
if (!pn)
return null();
#if JS_HAS_GENERATOR_EXPRS
bool matched;
if (!tokenStream.matchToken(&matched, TOK_FOR))
return null();
if (matched) {
if (pc->lastYieldOffset != startYieldOffset) {
reportWithOffset(ParseError, false, pc->lastYieldOffset,
JSMSG_BAD_GENEXP_BODY, js_yield_str);
return null();
}
if (handler.isUnparenthesizedCommaExpression(pn)) {
report(ParseError, false, null(), JSMSG_BAD_GENERATOR_SYNTAX);
return null();
}
pn = legacyGeneratorExpr(pn);
if (!pn)
return null();
handler.setBeginPosition(pn, begin);
}
#endif /* JS_HAS_GENERATOR_EXPRS */
return pn;
return expr(inHandling, yieldHandling, tripledotHandling, PredictInvoked);
}
template <typename ParseHandler>

View File

@ -799,9 +799,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
ParseContext<ParseHandler>* outerpc,
unsigned innerBlockScopeDepth);
Node legacyArrayComprehension(Node array);
Node generatorComprehensionLambda(GeneratorKind comprehensionKind, unsigned begin,
Node innerStmt);
Node legacyGeneratorExpr(Node kid);
Node generatorComprehensionLambda(unsigned begin);
Node comprehensionFor(GeneratorKind comprehensionKind);
Node comprehensionIf(GeneratorKind comprehensionKind);
Node comprehensionTail(GeneratorKind comprehensionKind);

View File

@ -22,7 +22,7 @@
#define JS_HAS_GENERATORS 1 /* (no longer used) */
#define JS_HAS_BLOCK_SCOPE 1 /* (no longer used) */
#define JS_HAS_DESTRUCTURING 2 /* (no longer used) */
#define JS_HAS_GENERATOR_EXPRS 1 /* has (expr for (lhs in iterable)) */
#define JS_HAS_GENERATOR_EXPRS 1 /* (no longer used) */
#define JS_HAS_EXPR_CLOSURES 1 /* has function (formals) listexpr */
/* (no longer used) */