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

Unified Diff: src/preparser.h

Issue 938443002: [es6] implement spread calls (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase + clang-format Created 5 years, 8 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 1ade9a7e6ff77becf07be9fb2f7b57a49cb224f4..2b61853b0c35db347cb8d4c970d422a1ed576240 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -90,6 +90,7 @@ class ParserBase : public Traits {
allow_harmony_sloppy_(false),
allow_harmony_computed_property_names_(false),
allow_harmony_rest_params_(false),
+ allow_harmony_spreadcalls_(false),
allow_strong_mode_(false) {}
// Getters that indicate whether certain syntactical constructs are
@@ -112,6 +113,7 @@ class ParserBase : public Traits {
bool allow_harmony_rest_params() const {
return allow_harmony_rest_params_;
}
+ bool allow_harmony_spreadcalls() const { return allow_harmony_spreadcalls_; }
bool allow_strong_mode() const { return allow_strong_mode_; }
@@ -143,6 +145,9 @@ class ParserBase : public Traits {
void set_allow_harmony_rest_params(bool allow) {
allow_harmony_rest_params_ = allow;
}
+ void set_allow_harmony_spreadcalls(bool allow) {
+ allow_harmony_spreadcalls_ = allow;
+ }
void set_allow_strong_mode(bool allow) { allow_strong_mode_ = allow; }
protected:
@@ -574,7 +579,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);
@@ -686,6 +692,7 @@ class ParserBase : public Traits {
bool allow_harmony_sloppy_;
bool allow_harmony_computed_property_names_;
bool allow_harmony_rest_params_;
+ bool allow_harmony_spreadcalls_;
bool allow_strong_mode_;
};
@@ -778,6 +785,10 @@ class PreParserExpression {
return PreParserExpression(TypeField::encode(kExpression));
}
+ static PreParserExpression Spread(PreParserExpression expression) {
+ return PreParserExpression(TypeField::encode(kSpreadExpression));
+ }
+
static PreParserExpression FromIdentifier(PreParserIdentifier id) {
return PreParserExpression(TypeField::encode(kIdentifierExpression) |
IdentifierTypeField::encode(id.type_));
@@ -906,6 +917,10 @@ class PreParserExpression {
ExpressionTypeField::decode(code_) == kNoTemplateTagExpression;
}
+ bool IsSpreadExpression() const {
+ return TypeField::decode(code_) == kSpreadExpression;
+ }
+
PreParserExpression AsFunctionLiteral() { return *this; }
bool IsBinaryOperation() const {
@@ -938,7 +953,8 @@ class PreParserExpression {
kExpression,
kIdentifierExpression,
kStringLiteralExpression,
- kBinaryOperationExpression
+ kBinaryOperationExpression,
+ kSpreadExpression
};
enum Parenthesization {
@@ -964,8 +980,8 @@ class PreParserExpression {
: (IsIdentifier() && AsIdentifier().IsValidArrowParam());
}
- // The first four bits are for the Type and Parenthesization.
- typedef BitField<Type, 0, 2> TypeField;
+ // The first five bits are for the Type and Parenthesization.
+ typedef BitField<Type, 0, 3> TypeField;
typedef BitField<Parenthesization, TypeField::kNext, 2> ParenthesizationField;
// The rest of the bits are interpreted depending on the value
@@ -1166,6 +1182,12 @@ class PreParserFactory {
int pos) {
return PreParserExpression::Default();
}
+ PreParserExpression NewCallRuntime(const AstRawString* name,
+ const Runtime::Function* function,
+ PreParserExpressionList arguments,
+ int pos) {
+ return PreParserExpression::Default();
+ }
PreParserStatement NewReturnStatement(PreParserExpression expression,
int pos) {
return PreParserStatement::Default();
@@ -1182,6 +1204,10 @@ class PreParserFactory {
return PreParserExpression::Default();
}
+ PreParserExpression NewSpread(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; }
@@ -1494,6 +1520,19 @@ class PreParserTraits {
bool name_is_strict_reserved, int pos,
bool* ok);
+ PreParserExpressionList PrepareSpreadArguments(PreParserExpressionList list) {
+ return list;
+ }
+
+ inline void MaterializeUnspreadArgumentsLiterals(int count);
+
+ inline PreParserExpression SpreadCall(PreParserExpression function,
+ PreParserExpressionList args, int pos);
+
+ inline PreParserExpression SpreadCallNew(PreParserExpression function,
+ PreParserExpressionList args,
+ int pos);
+
private:
PreParser* pre_parser_;
};
@@ -1634,6 +1673,26 @@ void PreParserTraits::MaterializeTemplateCallsiteLiterals() {
}
+void PreParserTraits::MaterializeUnspreadArgumentsLiterals(int count) {
+ for (int i = 0; i < count; ++i) {
+ pre_parser_->function_state_->NextMaterializedLiteralIndex();
+ }
+}
+
+
+PreParserExpression PreParserTraits::SpreadCall(PreParserExpression function,
+ PreParserExpressionList args,
+ int pos) {
+ return pre_parser_->factory()->NewCall(function, args, pos);
+}
+
+PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function,
+ PreParserExpressionList args,
+ int pos) {
+ return pre_parser_->factory()->NewCallNew(function, args, pos);
+}
+
+
PreParserStatementList PreParser::ParseEagerFunctionBody(
PreParserIdentifier function_name, int pos, Variable* fvar,
Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
@@ -2303,18 +2362,42 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
template <class Traits>
typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
- bool* ok) {
+ Scanner::Location* first_spread_arg_loc, bool* ok) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
+ Scanner::Location spread_arg = Scanner::Location::invalid();
typename Traits::Type::ExpressionList result =
this->NewExpressionList(4, zone_);
Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
bool done = (peek() == Token::RPAREN);
+ bool was_unspread = false;
+ int unspread_sequences_count = 0;
while (!done) {
+ bool is_spread = allow_harmony_spreadcalls() && (peek() == Token::ELLIPSIS);
+ int start_pos = peek_position();
+ if (is_spread) Consume(Token::ELLIPSIS);
+
ExpressionT argument = this->ParseAssignmentExpression(
true, CHECK_OK_CUSTOM(NullExpressionList));
+ if (is_spread) {
+ if (!spread_arg.IsValid()) {
+ spread_arg.beg_pos = start_pos;
+ spread_arg.end_pos = peek_position();
+ }
+ argument = factory()->NewSpread(argument, start_pos);
+ }
result->Add(argument, zone_);
+
+ // unspread_sequences_count is the number of sequences of parameters which
+ // are not prefixed with a spread '...' operator.
+ if (is_spread) {
+ was_unspread = false;
+ } else if (!was_unspread) {
+ was_unspread = true;
+ unspread_sequences_count++;
+ }
+
if (result->length() > Code::kMaxArguments) {
ReportMessage("too_many_arguments");
*ok = false;
@@ -2331,6 +2414,15 @@ typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
*ok = false;
return this->NullExpressionList();
}
+ *first_spread_arg_loc = spread_arg;
+
+ if (spread_arg.IsValid()) {
+ // Unspread parameter sequences are translated into array literals in the
+ // parser. Ensure that the number of materialized literals matches between
+ // the parser and preparser
+ Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count);
+ }
+
return result;
}
@@ -2645,7 +2737,9 @@ 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.
@@ -2655,7 +2749,13 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
// These calls are marked as potentially direct eval calls. Whether
// 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()) {
+ args = Traits::PrepareSpreadArguments(args);
+ result = Traits::SpreadCall(result, args, pos);
+ } else {
+ result = factory()->NewCall(result, args, pos);
+ }
if (fni_ != NULL) fni_->RemoveLastFunction();
break;
}
@@ -2709,9 +2809,16 @@ 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);
- result = factory()->NewCallNew(result, args, new_pos);
+ this->ParseArguments(&spread_pos, CHECK_OK);
+
+ if (spread_pos.IsValid()) {
+ args = Traits::PrepareSpreadArguments(args);
+ result = Traits::SpreadCallNew(result, args, new_pos);
+ } else {
+ result = factory()->NewCallNew(result, args, new_pos);
+ }
// The expression can still continue with . or [ after the arguments.
result = this->ParseMemberExpressionContinuation(result, CHECK_OK);
return result;
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | test/js-perf-test/JSTests.json » ('J')

Powered by Google App Engine
This is Rietveld 408576698