Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index 41b3a31f0e1169068eaf2968fe55b67fc3904ee4..f38564adc6f4e434257281260a55aa970eac8172 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 |
| @@ -117,6 +118,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_; } |
| @@ -157,6 +159,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_)); |
| @@ -911,6 +922,10 @@ class PreParserExpression { |
| ExpressionTypeField::decode(code_) == kNoTemplateTagExpression; |
| } |
| + bool IsSpreadExpression() const { |
| + return TypeField::decode(code_) == kSpreadExpression; |
| + } |
| + |
| PreParserExpression AsFunctionLiteral() { return *this; } |
| bool IsBinaryOperation() const { |
| @@ -943,7 +958,8 @@ class PreParserExpression { |
| kExpression, |
| kIdentifierExpression, |
| kStringLiteralExpression, |
| - kBinaryOperationExpression |
| + kBinaryOperationExpression, |
| + kSpreadExpression |
| }; |
| enum Parenthesization { |
| @@ -970,8 +986,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 |
| @@ -1172,6 +1188,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(); |
| @@ -1188,6 +1210,11 @@ class PreParserFactory { |
| return PreParserExpression::Default(); |
| } |
| + PreParserExpression NewSpreadOperation(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; } |
| @@ -1500,6 +1527,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_; |
| }; |
| @@ -1639,6 +1679,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) { |
| @@ -2285,18 +2345,40 @@ 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; |
|
rossberg
2015/02/25 14:28:18
A brief comment explaining what this actually coun
caitp (gmail)
2015/02/25 14:49:08
That's right --- will add a comment
|
| 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()->NewSpreadOperation(argument, start_pos); |
| + } |
| result->Add(argument, zone_); |
| + |
| + 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; |
| @@ -2309,6 +2391,12 @@ typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( |
| } |
| } |
| Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList)); |
| + *first_spread_arg_loc = spread_arg; |
| + |
| + if (spread_arg.IsValid()) { |
| + Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count); |
| + } |
| + |
| return result; |
| } |
| @@ -2623,7 +2711,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. |
| @@ -2633,7 +2723,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; |
| } |
| @@ -2704,9 +2800,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; |