 Chromium Code Reviews
 Chromium Code Reviews Issue 938443002:
  [es6] implement spread calls  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 938443002:
  [es6] implement spread calls  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| Index: src/preparser.h | 
| diff --git a/src/preparser.h b/src/preparser.h | 
| index 9f8fc13653a893d8c2adc7fcc2884773f2fd8f34..1ffd2ced47604d62a2df5394dc33072751aa0166 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: | 
| @@ -558,7 +563,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); | 
| @@ -670,6 +676,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_; | 
| }; | 
| @@ -766,6 +773,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_)); | 
| @@ -899,6 +910,10 @@ class PreParserExpression { | 
| ExpressionTypeField::decode(code_) == kNoTemplateTagExpression; | 
| } | 
| + bool IsSpreadExpression() const { | 
| + return TypeField::decode(code_) == kSpreadExpression; | 
| + } | 
| + | 
| PreParserExpression AsFunctionLiteral() { return *this; } | 
| bool IsBinaryOperation() const { | 
| @@ -931,7 +946,8 @@ class PreParserExpression { | 
| kExpression, | 
| kIdentifierExpression, | 
| kStringLiteralExpression, | 
| - kBinaryOperationExpression | 
| + kBinaryOperationExpression, | 
| + kSpreadExpression | 
| }; | 
| enum Parenthesization { | 
| @@ -958,8 +974,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 | 
| @@ -1160,6 +1176,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(); | 
| @@ -1176,6 +1198,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; } | 
| @@ -1482,6 +1509,16 @@ class PreParserTraits { | 
| bool name_is_strict_reserved, int pos, | 
| bool* ok); | 
| + PreParserExpressionList PrepareSpreadCallArguments( | 
| + PreParserExpression function, PreParserExpressionList list) { | 
| + return list; | 
| + } | 
| + | 
| + PreParserExpressionList PrepareSpreadCallNewArguments( | 
| + PreParserExpression function, PreParserExpressionList list) { | 
| + return list; | 
| + } | 
| + | 
| private: | 
| PreParser* pre_parser_; | 
| }; | 
| @@ -2257,17 +2294,29 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( | 
| template <class Traits> | 
| typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( | 
| - bool* ok) { | 
| + Scanner::Location* 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); | 
| 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 (result->length() > Code::kMaxArguments) { | 
| ReportMessage("too_many_arguments"); | 
| @@ -2281,6 +2330,7 @@ typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( | 
| } | 
| } | 
| Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList)); | 
| + *spread_arg_loc = spread_arg; | 
| 
arv (Not doing code reviews)
2015/02/18 15:07:06
I'm not sure why we need to return a Location for
 
caitp (gmail)
2015/02/18 15:32:08
It's a hold-over from the other patch, where the l
 | 
| return result; | 
| } | 
| @@ -2590,7 +2640,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. | 
| @@ -2600,7 +2652,14 @@ 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::PrepareSpreadCallArguments(result, args); | 
| + result = factory()->NewCallRuntime( | 
| + ast_value_factory()->spread_call_string(), NULL, args, pos); | 
| + } else { | 
| + result = factory()->NewCall(result, args, pos); | 
| + } | 
| if (fni_ != NULL) fni_->RemoveLastFunction(); | 
| break; | 
| } | 
| @@ -2671,9 +2730,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); | 
| - result = factory()->NewCallNew(result, args, new_pos); | 
| + this->ParseArguments(&spread_pos, CHECK_OK); | 
| + | 
| + if (spread_pos.IsValid()) { | 
| + args = Traits::PrepareSpreadCallNewArguments(result, args); | 
| + result = factory()->NewCallRuntime( | 
| + ast_value_factory()->spread_call_new_string(), NULL, 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; |