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

Unified Diff: src/preparser.h

Issue 919703003: WIP: Implement ES6 Spread-calls (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Flag calls as spread calls in parser, error on spread intrinsics/construct calls Created 5 years, 10 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
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index 4b526f5f1f3c6f039ae730c70b07eccfa8a20444..214478aeb61bb9342f019b1147a5a877b67ee7a2 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -553,7 +553,8 @@ class ParserBase : public Traits {
ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
bool is_static, bool* is_computed_name, bool* has_seen_constructor,
bool* ok);
- typename Traits::Type::ExpressionList ParseArguments(bool* ok);
+ typename Traits::Type::ExpressionList ParseArguments(
+ Scanner::Location* first_spread_pos, bool* ok);
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool* ok);
ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
@@ -578,6 +579,13 @@ class ParserBase : public Traits {
ExpressionT expression,
Scanner::Location location, const char* message, bool* ok);
+ ExpressionT MaybeSpread(ExpressionT expression, bool is_spread, int pos) {
+ if (is_spread) {
+ return factory()->NewSpreadOperation(scope_, expression, pos);
+ }
+ return expression;
+ }
+
// Used to validate property names in object literals and class literals
enum PropertyKind {
kAccessorProperty,
@@ -762,6 +770,11 @@ class PreParserExpression {
return PreParserExpression(TypeField::encode(kExpression));
}
+ static PreParserExpression Spread(PreParserExpression expression) {
+ DCHECK(!expression.IsSpreadExpression() || expression.is_parenthesized());
+ return PreParserExpression(TypeField::encode(kSpreadExpression));
+ }
+
static PreParserExpression FromIdentifier(PreParserIdentifier id) {
return PreParserExpression(TypeField::encode(kIdentifierExpression) |
IdentifierTypeField::encode(id.type_));
@@ -895,6 +908,10 @@ class PreParserExpression {
ExpressionTypeField::decode(code_) == kNoTemplateTagExpression;
}
+ bool IsSpreadExpression() const {
+ return TypeField::decode(code_) == kSpreadExpression;
+ }
+
PreParserExpression AsFunctionLiteral() { return *this; }
bool IsBinaryOperation() const {
@@ -927,7 +944,8 @@ class PreParserExpression {
kExpression,
kIdentifierExpression,
kStringLiteralExpression,
- kBinaryOperationExpression
+ kBinaryOperationExpression,
+ kSpreadExpression
};
enum Parenthesization {
@@ -955,7 +973,7 @@ class PreParserExpression {
}
// The first four bits are for the Type and Parenthesization.
- typedef BitField<Type, 0, 2> TypeField;
+ typedef BitField<Type, 0, 3> TypeField;
typedef BitField<Parenthesization, TypeField::kNext, 2> ParenthesizationField;
// The rest of the bits are interpreted depending on the value
@@ -1172,6 +1190,11 @@ class PreParserFactory {
return PreParserExpression::Default();
}
+ PreParserExpression NewSpreadOperation(
+ Scope* scope, PreParserExpression expression, int pos) {
+ return PreParserExpression::Spread(expression);
+ }
+
// Return the object itself as AstVisitor and implement the needed
// dummy method right in this class.
PreParserFactory* visitor() { return this; }
@@ -1479,6 +1502,8 @@ class PreParserTraits {
bool name_is_strict_reserved, int pos,
bool* ok);
+ static void MarkSpreadCall(PreParserExpression call) {}
+
private:
PreParser* pre_parser_;
};
@@ -2267,18 +2292,32 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
template <class Traits>
typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
- bool* ok) {
+ Scanner::Location* first_spread, bool* ok) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
-
+ Scanner::Location spread_loc = Scanner::Location::invalid();
typename Traits::Type::ExpressionList result =
this->NewExpressionList(4, zone_);
Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
bool done = (peek() == Token::RPAREN);
while (!done) {
+ bool is_spread = peek() == Token::ELLIPSIS;
+ bool first_spread = false;
+ int spread_pos = -1;
+ if (is_spread) {
+ spread_pos = peek_position();
+ first_spread = spread_loc.beg_pos < 0;
+ if (first_spread) {
+ spread_loc.beg_pos = spread_pos;
+ }
+ Consume(Token::ELLIPSIS);
+ }
ExpressionT argument = this->ParseAssignmentExpression(
true, CHECK_OK_CUSTOM(NullExpressionList));
- result->Add(argument, zone_);
+ if (first_spread) {
+ spread_loc.end_pos = peek_position();
+ }
+ result->Add(MaybeSpread(argument, is_spread, spread_pos), zone_);
if (result->length() > Code::kMaxArguments) {
ReportMessage("too_many_arguments");
*ok = false;
@@ -2291,6 +2330,7 @@ typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
}
}
Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList));
+ *first_spread = spread_loc;
return result;
}
@@ -2594,7 +2634,10 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
result->AsFunctionLiteral()->set_parenthesized();
}
}
- typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK);
+
+ Scanner::Location spread_pos;
+ typename Traits::Type::ExpressionList args =
+ ParseArguments(&spread_pos, CHECK_OK);
// Keep track of eval() calls since they disable all local variable
// optimizations.
@@ -2605,6 +2648,9 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
// they are actually direct calls to eval is determined at run time.
this->CheckPossibleEvalCall(result, scope_);
result = factory()->NewCall(result, args, pos);
+ if (spread_pos.IsValid()) {
+ Traits::MarkSpreadCall(result);
+ }
if (fni_ != NULL) fni_->RemoveLastFunction();
break;
}
@@ -2675,8 +2721,17 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
}
if (peek() == Token::LPAREN) {
// NewExpression with arguments.
+ Scanner::Location spread_pos;
typename Traits::Type::ExpressionList args =
- this->ParseArguments(CHECK_OK);
+ this->ParseArguments(&spread_pos, CHECK_OK);
+
+ // TODO(caitp): support spread-calls in CallNew()
+ if (spread_pos.IsValid()) {
+ Traits::ReportMessageAt(spread_pos, "spreadcall_construct");
+ *ok = false;
+ return Traits::EmptyExpression();
+ }
+
result = factory()->NewCallNew(result, args, new_pos);
// The expression can still continue with . or [ after the arguments.
result = this->ParseMemberExpressionContinuation(result, CHECK_OK);

Powered by Google App Engine
This is Rietveld 408576698