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); |
2860 bool is_simple = arrow_formals_classifier.is_simple_parameter_list(); | |
rossberg
2015/08/24 13:11:08
Nit: avoid the extra variable by storing to parame
conradw
2015/08/25 11:31:20
Done.
| |
2861 if (!is_simple) scope->SetHasNonSimpleParameters(); | |
2850 FormalParametersT parameters(scope); | 2862 FormalParametersT parameters(scope); |
2863 parameters.is_simple = is_simple; | |
2851 checkpoint.Restore(¶meters.materialized_literals_count); | 2864 checkpoint.Restore(¶meters.materialized_literals_count); |
2852 | 2865 |
2853 scope->set_start_position(lhs_beg_pos); | 2866 scope->set_start_position(lhs_beg_pos); |
2854 Scanner::Location duplicate_loc = Scanner::Location::invalid(); | 2867 Scanner::Location duplicate_loc = Scanner::Location::invalid(); |
2855 this->ParseArrowFunctionFormalParameterList(¶meters, expression, loc, | 2868 this->ParseArrowFunctionFormalParameterList(¶meters, expression, loc, |
2856 &duplicate_loc, CHECK_OK); | 2869 &duplicate_loc, CHECK_OK); |
2857 if (duplicate_loc.IsValid()) { | 2870 if (duplicate_loc.IsValid()) { |
2858 arrow_formals_classifier.RecordDuplicateFormalParameterError( | 2871 arrow_formals_classifier.RecordDuplicateFormalParameterError( |
2859 duplicate_loc); | 2872 duplicate_loc); |
2860 } | 2873 } |
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3654 ValidateBindingPattern(classifier, ok); | 3667 ValidateBindingPattern(classifier, ok); |
3655 if (!*ok) return; | 3668 if (!*ok) return; |
3656 | 3669 |
3657 if (!Traits::IsIdentifier(pattern)) { | 3670 if (!Traits::IsIdentifier(pattern)) { |
3658 if (is_rest || !allow_harmony_destructuring()) { | 3671 if (is_rest || !allow_harmony_destructuring()) { |
3659 ReportUnexpectedToken(next); | 3672 ReportUnexpectedToken(next); |
3660 *ok = false; | 3673 *ok = false; |
3661 return; | 3674 return; |
3662 } | 3675 } |
3663 parameters->is_simple = false; | 3676 parameters->is_simple = false; |
3677 classifier->RecordNonSimpleParameter(); | |
3664 } | 3678 } |
3665 | 3679 |
3666 ExpressionT initializer = Traits::EmptyExpression(); | 3680 ExpressionT initializer = Traits::EmptyExpression(); |
3667 if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) { | 3681 if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) { |
3668 ExpressionClassifier init_classifier; | 3682 ExpressionClassifier init_classifier; |
3669 initializer = ParseAssignmentExpression(true, &init_classifier, ok); | 3683 initializer = ParseAssignmentExpression(true, &init_classifier, ok); |
3670 if (!*ok) return; | 3684 if (!*ok) return; |
3671 ValidateExpression(&init_classifier, ok); | 3685 ValidateExpression(&init_classifier, ok); |
3672 if (!*ok) return; | 3686 if (!*ok) return; |
3673 parameters->is_simple = false; | 3687 parameters->is_simple = false; |
3688 classifier->RecordNonSimpleParameter(); | |
3674 } | 3689 } |
3675 | 3690 |
3676 Traits::AddFormalParameter(parameters, pattern, initializer, is_rest); | 3691 Traits::AddFormalParameter(parameters, pattern, initializer, is_rest); |
3677 } | 3692 } |
3678 | 3693 |
3679 | 3694 |
3680 template <class Traits> | 3695 template <class Traits> |
3681 void ParserBase<Traits>::ParseFormalParameterList( | 3696 void ParserBase<Traits>::ParseFormalParameterList( |
3682 FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { | 3697 FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { |
3683 // FormalParameters[Yield,GeneratorParameter] : | 3698 // FormalParameters[Yield,GeneratorParameter] : |
(...skipping 20 matching lines...) Expand all Loading... | |
3704 return; | 3719 return; |
3705 } | 3720 } |
3706 parameters->has_rest = | 3721 parameters->has_rest = |
3707 allow_harmony_rest_parameters() && Check(Token::ELLIPSIS); | 3722 allow_harmony_rest_parameters() && Check(Token::ELLIPSIS); |
3708 ParseFormalParameter(parameters, classifier, ok); | 3723 ParseFormalParameter(parameters, classifier, ok); |
3709 if (!*ok) return; | 3724 if (!*ok) return; |
3710 } while (!parameters->has_rest && Check(Token::COMMA)); | 3725 } while (!parameters->has_rest && Check(Token::COMMA)); |
3711 | 3726 |
3712 if (parameters->has_rest) { | 3727 if (parameters->has_rest) { |
3713 parameters->is_simple = false; | 3728 parameters->is_simple = false; |
3729 classifier->RecordNonSimpleParameter(); | |
3714 if (peek() == Token::COMMA) { | 3730 if (peek() == Token::COMMA) { |
3715 ReportMessageAt(scanner()->peek_location(), | 3731 ReportMessageAt(scanner()->peek_location(), |
3716 MessageTemplate::kParamAfterRest); | 3732 MessageTemplate::kParamAfterRest); |
3717 *ok = false; | 3733 *ok = false; |
3718 return; | 3734 return; |
3719 } | 3735 } |
3720 } | 3736 } |
3721 } | 3737 } |
3722 | 3738 |
3723 for (int i = 0; i < parameters->Arity(); ++i) { | 3739 for (int i = 0; i < parameters->Arity(); ++i) { |
3724 auto parameter = parameters->at(i); | 3740 auto parameter = parameters->at(i); |
3725 Traits::DeclareFormalParameter( | 3741 Traits::DeclareFormalParameter(parameters->scope, parameter, classifier); |
3726 parameters->scope, parameter, parameters->is_simple, classifier); | |
3727 } | 3742 } |
3728 } | 3743 } |
3729 | 3744 |
3730 | 3745 |
3731 template <class Traits> | 3746 template <class Traits> |
3732 void ParserBase<Traits>::CheckArityRestrictions( | 3747 void ParserBase<Traits>::CheckArityRestrictions( |
3733 int param_count, FunctionLiteral::ArityRestriction arity_restriction, | 3748 int param_count, FunctionLiteral::ArityRestriction arity_restriction, |
3734 bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) { | 3749 bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) { |
3735 switch (arity_restriction) { | 3750 switch (arity_restriction) { |
3736 case FunctionLiteral::GETTER_ARITY: | 3751 case FunctionLiteral::GETTER_ARITY: |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4059 *ok = false; | 4074 *ok = false; |
4060 return; | 4075 return; |
4061 } | 4076 } |
4062 has_seen_constructor_ = true; | 4077 has_seen_constructor_ = true; |
4063 return; | 4078 return; |
4064 } | 4079 } |
4065 } | 4080 } |
4066 } } // v8::internal | 4081 } } // v8::internal |
4067 | 4082 |
4068 #endif // V8_PREPARSER_H | 4083 #endif // V8_PREPARSER_H |
OLD | NEW |