Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index 07e431bfc54790b0a65c081f9ea8021ab6fba84c..8f7764730257a1bc1a1ecac423fa177971a3dbc5 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -703,7 +703,12 @@ class ParserBase : public Traits { |
| bool* ok); |
| void ParseFormalParameter(FormalParametersT* parameters, |
| - ExpressionClassifier* classifier, bool* ok); |
| + ExpressionClassifier* classifier, int start_pos, |
| + bool* ok); |
| + inline void ParseFormalParameter(FormalParametersT* parameters, |
|
adamk
2015/08/28 23:26:37
Is it really worth having two versions of this met
caitp (gmail)
2015/08/28 23:58:01
Sure, this way just seemed like less work than hun
caitp (gmail)
2015/08/29 15:51:59
Method is gone, isn't needed without the AST node
|
| + ExpressionClassifier* classifier, bool* ok) { |
| + ParseFormalParameter(parameters, classifier, peek_position(), ok); |
| + } |
| void ParseFormalParameterList(FormalParametersT* parameters, |
| ExpressionClassifier* classifier, bool* ok); |
| void CheckArityRestrictions( |
| @@ -917,7 +922,10 @@ class PreParserExpression { |
| static PreParserExpression BinaryOperation(PreParserExpression left, |
| Token::Value op, |
| PreParserExpression right) { |
| - return PreParserExpression(TypeField::encode(kBinaryOperationExpression)); |
| + return PreParserExpression( |
| + TypeField::encode(kBinaryOperationExpression) | |
| + BinaryOperationTokenField::encode(op) | |
|
adamk
2015/08/28 23:26:37
This seems overly general. Can you get away with j
caitp (gmail)
2015/08/28 23:58:01
Acknowledged
|
| + HasRestField::encode(right->IsSpreadExpression())); |
| } |
| static PreParserExpression StringLiteral() { |
| @@ -972,6 +980,8 @@ class PreParserExpression { |
| return TypeField::decode(code_) == kIdentifierExpression; |
| } |
| + PreParserExpression AsVariableProxy() const { return *this; } |
|
adamk
2015/08/28 23:26:37
If you end up needing this, it seems like it shoul
caitp (gmail)
2015/08/28 23:58:01
If it only returns false for `this`, that's probab
caitp (gmail)
2015/08/29 15:51:59
It's not needed without the new AST node, so it's
|
| + |
| PreParserIdentifier AsIdentifier() const { |
| DCHECK(IsIdentifier()); |
| return PreParserIdentifier(IdentifierTypeField::decode(code_)); |
| @@ -1034,6 +1044,14 @@ class PreParserExpression { |
| return TypeField::decode(code_) == kSpreadExpression; |
| } |
| + bool HasRestParameter() const { |
| + // Preparser's way of determining if an arrow function has a rest parameter. |
| + return IsSpreadExpression() || |
| + (IsBinaryOperation() && |
| + BinaryOperationTokenField::decode(code_) == Token::COMMA && |
|
adamk
2015/08/28 23:26:37
I'm not sure that you're getting much from this to
caitp (gmail)
2015/08/28 23:58:01
It's important for making lazy parsing work with a
adamk
2015/08/29 01:01:07
I think I wasn't as clear as I could have been. I
caitp (gmail)
2015/08/29 15:51:59
Done.
|
| + HasRestField::decode(code_)); |
| + } |
| + |
| PreParserExpression AsFunctionLiteral() { return *this; } |
| bool IsBinaryOperation() const { |
| @@ -1082,6 +1100,8 @@ class PreParserExpression { |
| typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseStrongField; |
| typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 10> |
| IdentifierTypeField; |
| + typedef BitField<Token::Value, TypeField::kNext, 8> BinaryOperationTokenField; |
| + typedef BitField<bool, BinaryOperationTokenField::kNext, 1> HasRestField; |
| uint32_t code_; |
| }; |
| @@ -1225,6 +1245,10 @@ class PreParserFactory { |
| PreParserExpression NewVariableProxy(void* variable) { |
| return PreParserExpression::Default(); |
| } |
| + PreParserExpression NewRestParameter(PreParserExpression param, int index, |
| + int position) { |
| + return PreParserExpression::Default(); |
| + } |
| PreParserExpression NewProperty(PreParserExpression obj, |
| PreParserExpression key, |
| int pos) { |
| @@ -1854,6 +1878,12 @@ void PreParserTraits::ParseArrowFunctionFormalParameterList( |
| Scanner::Location* duplicate_loc, bool* ok) { |
| // TODO(wingo): Detect duplicated identifiers in paramlists. Detect parameter |
| // lists that are too long. |
| + |
| + // Accomodate array literal for rest parameter. |
| + if (params.HasRestParameter()) { |
| + ++parameters->materialized_literals_count; |
| + pre_parser_->function_state_->NextMaterializedLiteralIndex(); |
| + } |
| } |
| @@ -2862,16 +2892,19 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| scope->SetHasNonSimpleParameters(); |
| parameters.is_simple = false; |
| } |
| - checkpoint.Restore(¶meters.materialized_literals_count); |
| - scope->set_start_position(lhs_beg_pos); |
| Scanner::Location duplicate_loc = Scanner::Location::invalid(); |
| this->ParseArrowFunctionFormalParameterList(¶meters, expression, loc, |
|
adamk
2015/08/28 23:26:37
So this had to move up because it now affects mate
caitp (gmail)
2015/08/28 23:58:01
Yeah :( I tried to find a better way to do it, but
adamk
2015/08/29 01:01:07
No need for a comment, as long as a test will fail
|
| &duplicate_loc, CHECK_OK); |
| + |
| + checkpoint.Restore(¶meters.materialized_literals_count); |
| + |
| + scope->set_start_position(lhs_beg_pos); |
| if (duplicate_loc.IsValid()) { |
| arrow_formals_classifier.RecordDuplicateFormalParameterError( |
| duplicate_loc); |
| } |
| + |
| expression = this->ParseArrowFunctionLiteral( |
| parameters, arrow_formals_classifier, CHECK_OK); |
| return expression; |
| @@ -3656,8 +3689,9 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
| template <class Traits> |
| -void ParserBase<Traits>::ParseFormalParameter( |
| - FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { |
| +void ParserBase<Traits>::ParseFormalParameter(FormalParametersT* parameters, |
| + ExpressionClassifier* classifier, |
| + int start_pos, bool* ok) { |
| // FormalParameter[Yield,GeneratorParameter] : |
| // BindingElement[?Yield, ?GeneratorParameter] |
| bool is_rest = parameters->has_rest; |
| @@ -3679,6 +3713,13 @@ void ParserBase<Traits>::ParseFormalParameter( |
| classifier->RecordNonSimpleParameter(); |
| } |
| + if (is_rest) { |
| + pattern = factory()->NewRestParameter( |
| + pattern->AsVariableProxy(), |
| + function_state_->NextMaterializedLiteralIndex(), start_pos); |
| + ++parameters->materialized_literals_count; |
| + } |
| + |
| ExpressionT initializer = Traits::EmptyExpression(); |
| if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) { |
| ExpressionClassifier init_classifier; |
| @@ -3713,6 +3754,7 @@ void ParserBase<Traits>::ParseFormalParameterList( |
| DCHECK_EQ(0, parameters->Arity()); |
| + int parameter_start; |
| if (peek() != Token::RPAREN) { |
| do { |
| if (parameters->Arity() > Code::kMaxArguments) { |
| @@ -3720,9 +3762,11 @@ void ParserBase<Traits>::ParseFormalParameterList( |
| *ok = false; |
| return; |
| } |
| + parameter_start = peek_position(); |
| parameters->has_rest = |
| allow_harmony_rest_parameters() && Check(Token::ELLIPSIS); |
| - ParseFormalParameter(parameters, classifier, ok); |
| + |
| + ParseFormalParameter(parameters, classifier, parameter_start, ok); |
| if (!*ok) return; |
| } while (!parameters->has_rest && Check(Token::COMMA)); |
| @@ -3817,6 +3861,12 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
| body = this->NewStatementList(0, zone()); |
| this->SkipLazyFunctionBody(&materialized_literal_count, |
| &expected_property_count, CHECK_OK); |
| + |
| + if (formal_parameters.has_rest) { |
| + DCHECK(formal_parameters.materialized_literals_count > 0); |
|
adamk
2015/08/28 23:26:37
Would this ever be anything other than 1 in this c
caitp (gmail)
2015/08/28 23:58:01
Yes --- I believe initializers with materialized l
adamk
2015/08/29 01:01:07
Ah, I meant to say "can this ever happen without d
caitp (gmail)
2015/08/29 15:51:59
I've changed it to always add the formals material
|
| + materialized_literal_count += |
| + formal_parameters.materialized_literals_count; |
| + } |
| } else { |
| body = this->ParseEagerFunctionBody( |
| this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters, |