OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
7 | 7 |
8 #include "src/bailout-reason.h" | 8 #include "src/bailout-reason.h" |
9 #include "src/expression-classifier.h" | 9 #include "src/expression-classifier.h" |
10 #include "src/func-name-inferrer.h" | 10 #include "src/func-name-inferrer.h" |
(...skipping 1630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 static bool IsTaggedTemplate(const PreParserExpression tag) { | 1641 static bool IsTaggedTemplate(const PreParserExpression tag) { |
1642 return !tag.IsNoTemplateTag(); | 1642 return !tag.IsNoTemplateTag(); |
1643 } | 1643 } |
1644 | 1644 |
1645 void AddFormalParameter( | 1645 void AddFormalParameter( |
1646 PreParserFormalParameters* parameters, PreParserExpression pattern, | 1646 PreParserFormalParameters* parameters, PreParserExpression pattern, |
1647 PreParserExpression initializer, bool is_rest) { | 1647 PreParserExpression initializer, bool is_rest) { |
1648 ++parameters->arity; | 1648 ++parameters->arity; |
1649 } | 1649 } |
1650 void DeclareFormalParameter(Scope* scope, PreParserIdentifier parameter, | 1650 void DeclareFormalParameter(Scope* scope, PreParserIdentifier parameter, |
1651 bool is_simple, | 1651 ExpressionClassifier* classifier) { |
1652 ExpressionClassifier* classifier) {} | 1652 if (!classifier->is_simple_parameter_list()) { |
| 1653 scope->SetHasNonSimpleParameters(); |
| 1654 } |
| 1655 } |
1653 | 1656 |
1654 void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} | 1657 void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} |
1655 | 1658 |
1656 // Temporary glue; these functions will move to ParserBase. | 1659 // Temporary glue; these functions will move to ParserBase. |
1657 PreParserExpression ParseV8Intrinsic(bool* ok); | 1660 PreParserExpression ParseV8Intrinsic(bool* ok); |
1658 PreParserExpression ParseFunctionLiteral( | 1661 PreParserExpression ParseFunctionLiteral( |
1659 PreParserIdentifier name, Scanner::Location function_name_location, | 1662 PreParserIdentifier name, Scanner::Location function_name_location, |
1660 FunctionNameValidity function_name_validity, FunctionKind kind, | 1663 FunctionNameValidity function_name_validity, FunctionKind kind, |
1661 int function_token_position, FunctionLiteral::FunctionType type, | 1664 int function_token_position, FunctionLiteral::FunctionType type, |
1662 FunctionLiteral::ArityRestriction arity_restriction, | 1665 FunctionLiteral::ArityRestriction arity_restriction, |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1740 | 1743 |
1741 // Parses a single function literal, from the opening parentheses before | 1744 // Parses a single function literal, from the opening parentheses before |
1742 // parameters to the closing brace after the body. | 1745 // parameters to the closing brace after the body. |
1743 // Returns a FunctionEntry describing the body of the function in enough | 1746 // Returns a FunctionEntry describing the body of the function in enough |
1744 // detail that it can be lazily compiled. | 1747 // detail that it can be lazily compiled. |
1745 // The scanner is expected to have matched the "function" or "function*" | 1748 // The scanner is expected to have matched the "function" or "function*" |
1746 // keyword and parameters, and have consumed the initial '{'. | 1749 // keyword and parameters, and have consumed the initial '{'. |
1747 // At return, unless an error occurred, the scanner is positioned before the | 1750 // At return, unless an error occurred, the scanner is positioned before the |
1748 // the final '}'. | 1751 // the final '}'. |
1749 PreParseResult PreParseLazyFunction( | 1752 PreParseResult PreParseLazyFunction( |
1750 LanguageMode language_mode, FunctionKind kind, ParserRecorder* log, | 1753 LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters, |
1751 Scanner::BookmarkScope* bookmark = nullptr); | 1754 ParserRecorder* log, Scanner::BookmarkScope* bookmark = nullptr); |
1752 | 1755 |
1753 private: | 1756 private: |
1754 friend class PreParserTraits; | 1757 friend class PreParserTraits; |
1755 | 1758 |
1756 static const int kLazyParseTrialLimit = 200; | 1759 static const int kLazyParseTrialLimit = 200; |
1757 | 1760 |
1758 // These types form an algebra over syntactic categories that is just | 1761 // These types form an algebra over syntactic categories that is just |
1759 // rich enough to let us recognize and propagate the constructs that | 1762 // rich enough to let us recognize and propagate the constructs that |
1760 // are either being counted in the preparser data, or is important | 1763 // are either being counted in the preparser data, or is important |
1761 // to throw the correct syntax error exceptions. | 1764 // to throw the correct syntax error exceptions. |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2276 MessageTemplate::kUnexpectedToken, | 2279 MessageTemplate::kUnexpectedToken, |
2277 Token::String(Token::RPAREN)); | 2280 Token::String(Token::RPAREN)); |
2278 result = factory()->NewEmptyParentheses(beg_pos); | 2281 result = factory()->NewEmptyParentheses(beg_pos); |
2279 } else if (allow_harmony_rest_parameters() && Check(Token::ELLIPSIS)) { | 2282 } else if (allow_harmony_rest_parameters() && Check(Token::ELLIPSIS)) { |
2280 // (...x)=>x. The continuation that looks for the => is in | 2283 // (...x)=>x. The continuation that looks for the => is in |
2281 // ParseAssignmentExpression. | 2284 // ParseAssignmentExpression. |
2282 int ellipsis_pos = scanner()->location().beg_pos; | 2285 int ellipsis_pos = scanner()->location().beg_pos; |
2283 classifier->RecordExpressionError(scanner()->location(), | 2286 classifier->RecordExpressionError(scanner()->location(), |
2284 MessageTemplate::kUnexpectedToken, | 2287 MessageTemplate::kUnexpectedToken, |
2285 Token::String(Token::ELLIPSIS)); | 2288 Token::String(Token::ELLIPSIS)); |
| 2289 classifier->RecordNonSimpleParameter(); |
2286 Scanner::Location expr_loc = scanner()->peek_location(); | 2290 Scanner::Location expr_loc = scanner()->peek_location(); |
2287 Token::Value tok = peek(); | 2291 Token::Value tok = peek(); |
2288 result = this->ParseAssignmentExpression(true, classifier, CHECK_OK); | 2292 result = this->ParseAssignmentExpression(true, classifier, CHECK_OK); |
2289 // Patterns are not allowed as rest parameters. There is no way we can | 2293 // Patterns are not allowed as rest parameters. There is no way we can |
2290 // succeed so go ahead and use the convenient ReportUnexpectedToken | 2294 // succeed so go ahead and use the convenient ReportUnexpectedToken |
2291 // interface. | 2295 // interface. |
2292 if (!Traits::IsIdentifier(result)) { | 2296 if (!Traits::IsIdentifier(result)) { |
2293 ReportUnexpectedTokenAt(expr_loc, tok); | 2297 ReportUnexpectedTokenAt(expr_loc, tok); |
2294 *ok = false; | 2298 *ok = false; |
2295 return this->EmptyExpression(); | 2299 return this->EmptyExpression(); |
2296 } | 2300 } |
2297 result = factory()->NewSpread(result, ellipsis_pos); | 2301 result = factory()->NewSpread(result, ellipsis_pos); |
| 2302 |
2298 if (peek() == Token::COMMA) { | 2303 if (peek() == Token::COMMA) { |
2299 ReportMessageAt(scanner()->peek_location(), | 2304 ReportMessageAt(scanner()->peek_location(), |
2300 MessageTemplate::kParamAfterRest); | 2305 MessageTemplate::kParamAfterRest); |
2301 *ok = false; | 2306 *ok = false; |
2302 return this->EmptyExpression(); | 2307 return this->EmptyExpression(); |
2303 } | 2308 } |
2304 Expect(Token::RPAREN, CHECK_OK); | 2309 Expect(Token::RPAREN, CHECK_OK); |
2305 } else { | 2310 } else { |
2306 // Heuristically try to detect immediately called functions before | 2311 // Heuristically try to detect immediately called functions before |
2307 // seeing the call parentheses. | 2312 // seeing the call parentheses. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2378 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { | 2383 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { |
2379 // Expression :: | 2384 // Expression :: |
2380 // AssignmentExpression | 2385 // AssignmentExpression |
2381 // Expression ',' AssignmentExpression | 2386 // Expression ',' AssignmentExpression |
2382 | 2387 |
2383 ExpressionClassifier binding_classifier; | 2388 ExpressionClassifier binding_classifier; |
2384 ExpressionT result = | 2389 ExpressionT result = |
2385 this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); | 2390 this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); |
2386 classifier->Accumulate(binding_classifier, | 2391 classifier->Accumulate(binding_classifier, |
2387 ExpressionClassifier::AllProductions); | 2392 ExpressionClassifier::AllProductions); |
| 2393 bool is_simple_parameter_list = this->IsIdentifier(result); |
2388 bool seen_rest = false; | 2394 bool seen_rest = false; |
2389 while (peek() == Token::COMMA) { | 2395 while (peek() == Token::COMMA) { |
2390 if (seen_rest) { | 2396 if (seen_rest) { |
2391 // At this point the production can't possibly be valid, but we don't know | 2397 // At this point the production can't possibly be valid, but we don't know |
2392 // which error to signal. | 2398 // which error to signal. |
2393 classifier->RecordArrowFormalParametersError( | 2399 classifier->RecordArrowFormalParametersError( |
2394 scanner()->peek_location(), MessageTemplate::kParamAfterRest); | 2400 scanner()->peek_location(), MessageTemplate::kParamAfterRest); |
2395 } | 2401 } |
2396 Consume(Token::COMMA); | 2402 Consume(Token::COMMA); |
2397 bool is_rest = false; | 2403 bool is_rest = false; |
2398 if (allow_harmony_rest_parameters() && peek() == Token::ELLIPSIS) { | 2404 if (allow_harmony_rest_parameters() && peek() == Token::ELLIPSIS) { |
2399 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only | 2405 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only |
2400 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a | 2406 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a |
2401 // valid expression or binding pattern. | 2407 // valid expression or binding pattern. |
2402 ExpressionUnexpectedToken(classifier); | 2408 ExpressionUnexpectedToken(classifier); |
2403 BindingPatternUnexpectedToken(classifier); | 2409 BindingPatternUnexpectedToken(classifier); |
2404 Consume(Token::ELLIPSIS); | 2410 Consume(Token::ELLIPSIS); |
2405 seen_rest = is_rest = true; | 2411 seen_rest = is_rest = true; |
2406 } | 2412 } |
2407 int pos = position(); | 2413 int pos = position(); |
2408 ExpressionT right = this->ParseAssignmentExpression( | 2414 ExpressionT right = this->ParseAssignmentExpression( |
2409 accept_IN, &binding_classifier, CHECK_OK); | 2415 accept_IN, &binding_classifier, CHECK_OK); |
2410 if (is_rest) right = factory()->NewSpread(right, pos); | 2416 if (is_rest) right = factory()->NewSpread(right, pos); |
| 2417 is_simple_parameter_list = |
| 2418 is_simple_parameter_list && this->IsIdentifier(right); |
2411 classifier->Accumulate(binding_classifier, | 2419 classifier->Accumulate(binding_classifier, |
2412 ExpressionClassifier::AllProductions); | 2420 ExpressionClassifier::AllProductions); |
2413 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); | 2421 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); |
2414 } | 2422 } |
| 2423 if (!is_simple_parameter_list || seen_rest) { |
| 2424 classifier->RecordNonSimpleParameter(); |
| 2425 } |
2415 return result; | 2426 return result; |
2416 } | 2427 } |
2417 | 2428 |
2418 | 2429 |
2419 template <class Traits> | 2430 template <class Traits> |
2420 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( | 2431 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
2421 ExpressionClassifier* classifier, bool* ok) { | 2432 ExpressionClassifier* classifier, bool* ok) { |
2422 // ArrayLiteral :: | 2433 // ArrayLiteral :: |
2423 // '[' Expression? (',' Expression?)* ']' | 2434 // '[' Expression? (',' Expression?)* ']' |
2424 | 2435 |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2832 | 2843 |
2833 if (fni_ != NULL) fni_->Enter(); | 2844 if (fni_ != NULL) fni_->Enter(); |
2834 ParserBase<Traits>::Checkpoint checkpoint(this); | 2845 ParserBase<Traits>::Checkpoint checkpoint(this); |
2835 ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder()); | 2846 ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder()); |
2836 bool parenthesized_formals = peek() == Token::LPAREN; | 2847 bool parenthesized_formals = peek() == Token::LPAREN; |
2837 if (!parenthesized_formals) { | 2848 if (!parenthesized_formals) { |
2838 ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier); | 2849 ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier); |
2839 } | 2850 } |
2840 ExpressionT expression = this->ParseConditionalExpression( | 2851 ExpressionT expression = this->ParseConditionalExpression( |
2841 accept_IN, &arrow_formals_classifier, CHECK_OK); | 2852 accept_IN, &arrow_formals_classifier, CHECK_OK); |
2842 | |
2843 if (allow_harmony_arrow_functions() && peek() == Token::ARROW) { | 2853 if (allow_harmony_arrow_functions() && peek() == Token::ARROW) { |
2844 BindingPatternUnexpectedToken(classifier); | 2854 BindingPatternUnexpectedToken(classifier); |
2845 ValidateArrowFormalParameters(&arrow_formals_classifier, expression, | 2855 ValidateArrowFormalParameters(&arrow_formals_classifier, expression, |
2846 parenthesized_formals, CHECK_OK); | 2856 parenthesized_formals, CHECK_OK); |
2847 Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos); | 2857 Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos); |
2848 Scope* scope = | 2858 Scope* scope = |
2849 this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); | 2859 this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); |
2850 FormalParametersT parameters(scope); | 2860 FormalParametersT parameters(scope); |
| 2861 if (!arrow_formals_classifier.is_simple_parameter_list()) { |
| 2862 scope->SetHasNonSimpleParameters(); |
| 2863 parameters.is_simple = false; |
| 2864 } |
2851 checkpoint.Restore(¶meters.materialized_literals_count); | 2865 checkpoint.Restore(¶meters.materialized_literals_count); |
2852 | 2866 |
2853 scope->set_start_position(lhs_beg_pos); | 2867 scope->set_start_position(lhs_beg_pos); |
2854 Scanner::Location duplicate_loc = Scanner::Location::invalid(); | 2868 Scanner::Location duplicate_loc = Scanner::Location::invalid(); |
2855 this->ParseArrowFunctionFormalParameterList(¶meters, expression, loc, | 2869 this->ParseArrowFunctionFormalParameterList(¶meters, expression, loc, |
2856 &duplicate_loc, CHECK_OK); | 2870 &duplicate_loc, CHECK_OK); |
2857 if (duplicate_loc.IsValid()) { | 2871 if (duplicate_loc.IsValid()) { |
2858 arrow_formals_classifier.RecordDuplicateFormalParameterError( | 2872 arrow_formals_classifier.RecordDuplicateFormalParameterError( |
2859 duplicate_loc); | 2873 duplicate_loc); |
2860 } | 2874 } |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3655 ValidateBindingPattern(classifier, ok); | 3669 ValidateBindingPattern(classifier, ok); |
3656 if (!*ok) return; | 3670 if (!*ok) return; |
3657 | 3671 |
3658 if (!Traits::IsIdentifier(pattern)) { | 3672 if (!Traits::IsIdentifier(pattern)) { |
3659 if (is_rest || !allow_harmony_destructuring()) { | 3673 if (is_rest || !allow_harmony_destructuring()) { |
3660 ReportUnexpectedToken(next); | 3674 ReportUnexpectedToken(next); |
3661 *ok = false; | 3675 *ok = false; |
3662 return; | 3676 return; |
3663 } | 3677 } |
3664 parameters->is_simple = false; | 3678 parameters->is_simple = false; |
| 3679 classifier->RecordNonSimpleParameter(); |
3665 } | 3680 } |
3666 | 3681 |
3667 ExpressionT initializer = Traits::EmptyExpression(); | 3682 ExpressionT initializer = Traits::EmptyExpression(); |
3668 if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) { | 3683 if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) { |
3669 ExpressionClassifier init_classifier; | 3684 ExpressionClassifier init_classifier; |
3670 initializer = ParseAssignmentExpression(true, &init_classifier, ok); | 3685 initializer = ParseAssignmentExpression(true, &init_classifier, ok); |
3671 if (!*ok) return; | 3686 if (!*ok) return; |
3672 ValidateExpression(&init_classifier, ok); | 3687 ValidateExpression(&init_classifier, ok); |
3673 if (!*ok) return; | 3688 if (!*ok) return; |
3674 parameters->is_simple = false; | 3689 parameters->is_simple = false; |
| 3690 classifier->RecordNonSimpleParameter(); |
3675 } | 3691 } |
3676 | 3692 |
3677 Traits::AddFormalParameter(parameters, pattern, initializer, is_rest); | 3693 Traits::AddFormalParameter(parameters, pattern, initializer, is_rest); |
3678 } | 3694 } |
3679 | 3695 |
3680 | 3696 |
3681 template <class Traits> | 3697 template <class Traits> |
3682 void ParserBase<Traits>::ParseFormalParameterList( | 3698 void ParserBase<Traits>::ParseFormalParameterList( |
3683 FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { | 3699 FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { |
3684 // FormalParameters[Yield,GeneratorParameter] : | 3700 // FormalParameters[Yield,GeneratorParameter] : |
(...skipping 20 matching lines...) Expand all Loading... |
3705 return; | 3721 return; |
3706 } | 3722 } |
3707 parameters->has_rest = | 3723 parameters->has_rest = |
3708 allow_harmony_rest_parameters() && Check(Token::ELLIPSIS); | 3724 allow_harmony_rest_parameters() && Check(Token::ELLIPSIS); |
3709 ParseFormalParameter(parameters, classifier, ok); | 3725 ParseFormalParameter(parameters, classifier, ok); |
3710 if (!*ok) return; | 3726 if (!*ok) return; |
3711 } while (!parameters->has_rest && Check(Token::COMMA)); | 3727 } while (!parameters->has_rest && Check(Token::COMMA)); |
3712 | 3728 |
3713 if (parameters->has_rest) { | 3729 if (parameters->has_rest) { |
3714 parameters->is_simple = false; | 3730 parameters->is_simple = false; |
| 3731 classifier->RecordNonSimpleParameter(); |
3715 if (peek() == Token::COMMA) { | 3732 if (peek() == Token::COMMA) { |
3716 ReportMessageAt(scanner()->peek_location(), | 3733 ReportMessageAt(scanner()->peek_location(), |
3717 MessageTemplate::kParamAfterRest); | 3734 MessageTemplate::kParamAfterRest); |
3718 *ok = false; | 3735 *ok = false; |
3719 return; | 3736 return; |
3720 } | 3737 } |
3721 } | 3738 } |
3722 } | 3739 } |
3723 | 3740 |
3724 for (int i = 0; i < parameters->Arity(); ++i) { | 3741 for (int i = 0; i < parameters->Arity(); ++i) { |
3725 auto parameter = parameters->at(i); | 3742 auto parameter = parameters->at(i); |
3726 Traits::DeclareFormalParameter( | 3743 Traits::DeclareFormalParameter(parameters->scope, parameter, classifier); |
3727 parameters->scope, parameter, parameters->is_simple, classifier); | |
3728 } | 3744 } |
3729 } | 3745 } |
3730 | 3746 |
3731 | 3747 |
3732 template <class Traits> | 3748 template <class Traits> |
3733 void ParserBase<Traits>::CheckArityRestrictions( | 3749 void ParserBase<Traits>::CheckArityRestrictions( |
3734 int param_count, FunctionLiteral::ArityRestriction arity_restriction, | 3750 int param_count, FunctionLiteral::ArityRestriction arity_restriction, |
3735 bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) { | 3751 bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) { |
3736 switch (arity_restriction) { | 3752 switch (arity_restriction) { |
3737 case FunctionLiteral::GETTER_ARITY: | 3753 case FunctionLiteral::GETTER_ARITY: |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4060 *ok = false; | 4076 *ok = false; |
4061 return; | 4077 return; |
4062 } | 4078 } |
4063 has_seen_constructor_ = true; | 4079 has_seen_constructor_ = true; |
4064 return; | 4080 return; |
4065 } | 4081 } |
4066 } | 4082 } |
4067 } } // v8::internal | 4083 } } // v8::internal |
4068 | 4084 |
4069 #endif // V8_PREPARSER_H | 4085 #endif // V8_PREPARSER_H |
OLD | NEW |