Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: src/preparser.h

Issue 1170153003: [destructuring] Refactor duplicate parameter name detection. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/bailout-reason.h" 10 #include "src/bailout-reason.h"
11 #include "src/expression-classifier.h"
11 #include "src/func-name-inferrer.h" 12 #include "src/func-name-inferrer.h"
12 #include "src/hashmap.h" 13 #include "src/hashmap.h"
13 #include "src/messages.h" 14 #include "src/messages.h"
14 #include "src/scanner.h" 15 #include "src/scanner.h"
15 #include "src/scopes.h" 16 #include "src/scopes.h"
16 #include "src/token.h" 17 #include "src/token.h"
17 18
18 namespace v8 { 19 namespace v8 {
19 namespace internal { 20 namespace internal {
20 21
21
22 // Common base class shared between parser and pre-parser. Traits encapsulate 22 // Common base class shared between parser and pre-parser. Traits encapsulate
23 // the differences between Parser and PreParser: 23 // the differences between Parser and PreParser:
24 24
25 // - Return types: For example, Parser functions return Expression* and 25 // - Return types: For example, Parser functions return Expression* and
26 // PreParser functions return PreParserExpression. 26 // PreParser functions return PreParserExpression.
27 27
28 // - Creating parse tree nodes: Parser generates an AST during the recursive 28 // - Creating parse tree nodes: Parser generates an AST during the recursive
29 // descent. PreParser doesn't create a tree. Instead, it passes around minimal 29 // descent. PreParser doesn't create a tree. Instead, it passes around minimal
30 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain 30 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain
31 // just enough data for the upper layer functions. PreParserFactory is 31 // just enough data for the upper layer functions. PreParserFactory is
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 void ReportMessageAt(Scanner::Location location, 539 void ReportMessageAt(Scanner::Location location,
540 MessageTemplate::Template message, 540 MessageTemplate::Template message,
541 ParseErrorType error_type = kSyntaxError) { 541 ParseErrorType error_type = kSyntaxError) {
542 Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0), 542 Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0),
543 error_type); 543 error_type);
544 } 544 }
545 545
546 void ReportUnexpectedToken(Token::Value token); 546 void ReportUnexpectedToken(Token::Value token);
547 void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token); 547 void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token);
548 548
549 class ExpressionClassifier {
550 public:
551 struct Error {
552 Error()
553 : location(Scanner::Location::invalid()),
554 message(MessageTemplate::kNone),
555 arg(nullptr) {}
556 549
557 Scanner::Location location; 550 void ReportClassifierError(const ExpressionClassifier::Error& error) {
558 MessageTemplate::Template message;
559 const char* arg;
560
561 bool HasError() const { return location.IsValid(); }
562 };
563
564 ExpressionClassifier() {}
565
566 bool is_valid_expression() const { return !expression_error_.HasError(); }
567
568 bool is_valid_binding_pattern() const {
569 return !binding_pattern_error_.HasError();
570 }
571
572 bool is_valid_assignment_pattern() const {
573 return !assignment_pattern_error_.HasError();
574 }
575
576 bool is_valid_arrow_formal_parameters() const {
577 return !arrow_formal_parameters_error_.HasError();
578 }
579
580 bool is_valid_formal_parameter_list_without_duplicates() const {
581 return !duplicate_formal_parameter_error_.HasError();
582 }
583
584 // Note: callers should also check
585 // is_valid_formal_parameter_list_without_duplicates().
586 bool is_valid_strict_mode_formal_parameters() const {
587 return !strict_mode_formal_parameter_error_.HasError();
588 }
589
590 // Note: callers should also check is_valid_strict_mode_formal_parameters()
591 // and is_valid_formal_parameter_list_without_duplicates().
592 bool is_valid_strong_mode_formal_parameters() const {
593 return !strong_mode_formal_parameter_error_.HasError();
594 }
595
596 const Error& expression_error() const { return expression_error_; }
597
598 const Error& binding_pattern_error() const {
599 return binding_pattern_error_;
600 }
601
602 const Error& assignment_pattern_error() const {
603 return assignment_pattern_error_;
604 }
605
606 const Error& arrow_formal_parameters_error() const {
607 return arrow_formal_parameters_error_;
608 }
609
610 const Error& duplicate_formal_parameter_error() const {
611 return duplicate_formal_parameter_error_;
612 }
613
614 const Error& strict_mode_formal_parameter_error() const {
615 return strict_mode_formal_parameter_error_;
616 }
617
618 const Error& strong_mode_formal_parameter_error() const {
619 return strong_mode_formal_parameter_error_;
620 }
621
622 void RecordExpressionError(const Scanner::Location& loc,
623 MessageTemplate::Template message,
624 const char* arg = nullptr) {
625 if (!is_valid_expression()) return;
626 expression_error_.location = loc;
627 expression_error_.message = message;
628 expression_error_.arg = arg;
629 }
630
631 void RecordBindingPatternError(const Scanner::Location& loc,
632 MessageTemplate::Template message,
633 const char* arg = nullptr) {
634 if (!is_valid_binding_pattern()) return;
635 binding_pattern_error_.location = loc;
636 binding_pattern_error_.message = message;
637 binding_pattern_error_.arg = arg;
638 }
639
640 void RecordAssignmentPatternError(const Scanner::Location& loc,
641 MessageTemplate::Template message,
642 const char* arg = nullptr) {
643 if (!is_valid_assignment_pattern()) return;
644 assignment_pattern_error_.location = loc;
645 assignment_pattern_error_.message = message;
646 assignment_pattern_error_.arg = arg;
647 }
648
649 void RecordArrowFormalParametersError(const Scanner::Location& loc,
650 MessageTemplate::Template message,
651 const char* arg = nullptr) {
652 if (!is_valid_arrow_formal_parameters()) return;
653 arrow_formal_parameters_error_.location = loc;
654 arrow_formal_parameters_error_.message = message;
655 arrow_formal_parameters_error_.arg = arg;
656 }
657
658 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
659 if (!is_valid_formal_parameter_list_without_duplicates()) return;
660 duplicate_formal_parameter_error_.location = loc;
661 duplicate_formal_parameter_error_.message =
662 MessageTemplate::kStrictParamDupe;
663 duplicate_formal_parameter_error_.arg = nullptr;
664 }
665
666 // Record a binding that would be invalid in strict mode. Confusingly this
667 // is not the same as StrictFormalParameterList, which simply forbids
668 // duplicate bindings.
669 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
670 MessageTemplate::Template message,
671 const char* arg = nullptr) {
672 if (!is_valid_strict_mode_formal_parameters()) return;
673 strict_mode_formal_parameter_error_.location = loc;
674 strict_mode_formal_parameter_error_.message = message;
675 strict_mode_formal_parameter_error_.arg = arg;
676 }
677
678 void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
679 MessageTemplate::Template message,
680 const char* arg = nullptr) {
681 if (!is_valid_strong_mode_formal_parameters()) return;
682 strong_mode_formal_parameter_error_.location = loc;
683 strong_mode_formal_parameter_error_.message = message;
684 strong_mode_formal_parameter_error_.arg = arg;
685 }
686
687 enum TargetProduction {
688 ExpressionProduction = 1 << 0,
689 BindingPatternProduction = 1 << 1,
690 AssignmentPatternProduction = 1 << 2,
691 FormalParametersProduction = 1 << 3,
692 ArrowFormalParametersProduction = 1 << 4,
693 StandardProductions = (ExpressionProduction | BindingPatternProduction |
694 AssignmentPatternProduction),
695 PatternProductions =
696 BindingPatternProduction | AssignmentPatternProduction,
697 AllProductions = (StandardProductions | FormalParametersProduction |
698 ArrowFormalParametersProduction),
699 };
700
701 void Accumulate(const ExpressionClassifier& inner,
702 unsigned productions = StandardProductions) {
703 if (productions & ExpressionProduction && is_valid_expression()) {
704 expression_error_ = inner.expression_error_;
705 }
706 if (productions & BindingPatternProduction &&
707 is_valid_binding_pattern()) {
708 binding_pattern_error_ = inner.binding_pattern_error_;
709 }
710 if (productions & AssignmentPatternProduction &&
711 is_valid_assignment_pattern()) {
712 assignment_pattern_error_ = inner.assignment_pattern_error_;
713 }
714 if (productions & FormalParametersProduction) {
715 if (is_valid_formal_parameter_list_without_duplicates()) {
716 duplicate_formal_parameter_error_ =
717 inner.duplicate_formal_parameter_error_;
718 }
719 if (is_valid_strict_mode_formal_parameters()) {
720 strict_mode_formal_parameter_error_ =
721 inner.strict_mode_formal_parameter_error_;
722 }
723 if (is_valid_strong_mode_formal_parameters()) {
724 strong_mode_formal_parameter_error_ =
725 inner.strong_mode_formal_parameter_error_;
726 }
727 }
728 if (productions & ArrowFormalParametersProduction &&
729 is_valid_arrow_formal_parameters()) {
730 // The result continues to be a valid arrow formal parameters if the
731 // inner expression is a valid binding pattern.
732 arrow_formal_parameters_error_ = inner.binding_pattern_error_;
733 }
734 }
735
736 void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
737 Accumulate(inner, AllProductions & ~PatternProductions);
738 if (!inner.is_valid_expression()) {
739 if (is_valid_binding_pattern()) {
740 binding_pattern_error_ = inner.expression_error();
741 }
742 if (is_valid_assignment_pattern()) {
743 assignment_pattern_error_ = inner.expression_error();
744 }
745 }
746 }
747
748 private:
749 Error expression_error_;
750 Error binding_pattern_error_;
751 Error assignment_pattern_error_;
752 Error arrow_formal_parameters_error_;
753 Error duplicate_formal_parameter_error_;
754 Error strict_mode_formal_parameter_error_;
755 Error strong_mode_formal_parameter_error_;
756 };
757
758 void ReportClassifierError(
759 const typename ExpressionClassifier::Error& error) {
760 Traits::ReportMessageAt(error.location, error.message, error.arg, 551 Traits::ReportMessageAt(error.location, error.message, error.arg,
761 kSyntaxError); 552 kSyntaxError);
762 } 553 }
763 554
764 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) { 555 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) {
765 if (!classifier->is_valid_expression()) { 556 if (!classifier->is_valid_expression()) {
766 ReportClassifierError(classifier->expression_error()); 557 ReportClassifierError(classifier->expression_error());
767 *ok = false; 558 *ok = false;
768 } 559 }
769 } 560 }
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 typedef PreParserIdentifier Identifier; 1310 typedef PreParserIdentifier Identifier;
1520 typedef PreParserExpression Expression; 1311 typedef PreParserExpression Expression;
1521 typedef PreParserExpression YieldExpression; 1312 typedef PreParserExpression YieldExpression;
1522 typedef PreParserExpression FunctionLiteral; 1313 typedef PreParserExpression FunctionLiteral;
1523 typedef PreParserExpression ClassLiteral; 1314 typedef PreParserExpression ClassLiteral;
1524 typedef PreParserExpression ObjectLiteralProperty; 1315 typedef PreParserExpression ObjectLiteralProperty;
1525 typedef PreParserExpression Literal; 1316 typedef PreParserExpression Literal;
1526 typedef PreParserExpressionList ExpressionList; 1317 typedef PreParserExpressionList ExpressionList;
1527 typedef PreParserExpressionList PropertyList; 1318 typedef PreParserExpressionList PropertyList;
1528 typedef PreParserIdentifier FormalParameter; 1319 typedef PreParserIdentifier FormalParameter;
1529 typedef DuplicateFinder FormalParameterScope; 1320 typedef void* FormalParameterScope;
1530 typedef PreParserStatementList StatementList; 1321 typedef PreParserStatementList StatementList;
1531 1322
1532 // For constructing objects returned by the traversing functions. 1323 // For constructing objects returned by the traversing functions.
1533 typedef PreParserFactory Factory; 1324 typedef PreParserFactory Factory;
1534 }; 1325 };
1535 1326
1536 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} 1327 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
1537 1328
1538 // Helper functions for recursive descent. 1329 // Helper functions for recursive descent.
1539 static bool IsEval(PreParserIdentifier identifier) { 1330 static bool IsEval(PreParserIdentifier identifier) {
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 return EmptyExpression(); 1583 return EmptyExpression();
1793 } 1584 }
1794 inline void MaterializeTemplateCallsiteLiterals(); 1585 inline void MaterializeTemplateCallsiteLiterals();
1795 PreParserExpression NoTemplateTag() { 1586 PreParserExpression NoTemplateTag() {
1796 return PreParserExpression::NoTemplateTag(); 1587 return PreParserExpression::NoTemplateTag();
1797 } 1588 }
1798 static bool IsTaggedTemplate(const PreParserExpression tag) { 1589 static bool IsTaggedTemplate(const PreParserExpression tag) {
1799 return !tag.IsNoTemplateTag(); 1590 return !tag.IsNoTemplateTag();
1800 } 1591 }
1801 1592
1802 V8_INLINE bool DeclareFormalParameter(DuplicateFinder* scope, 1593 void DeclareFormalParameter(void* scope, PreParserIdentifier param,
arv (Not doing code reviews) 2015/06/09 14:17:47 FormalParameterScope scope
Dmitry Lomov (no reviews) 2015/06/09 14:38:30 I did one better and removed that trait completely
1803 PreParserIdentifier param, 1594 ExpressionClassifier* classifier, bool is_rest) {}
1804 bool is_rest);
1805 1595
1806 void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} 1596 void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {}
1807 1597
1808 // Temporary glue; these functions will move to ParserBase. 1598 // Temporary glue; these functions will move to ParserBase.
1809 PreParserExpression ParseV8Intrinsic(bool* ok); 1599 PreParserExpression ParseV8Intrinsic(bool* ok);
1810 PreParserExpression ParseFunctionLiteral( 1600 PreParserExpression ParseFunctionLiteral(
1811 PreParserIdentifier name, Scanner::Location function_name_location, 1601 PreParserIdentifier name, Scanner::Location function_name_location,
1812 bool name_is_strict_reserved, FunctionKind kind, 1602 bool name_is_strict_reserved, FunctionKind kind,
1813 int function_token_position, FunctionLiteral::FunctionType type, 1603 int function_token_position, FunctionLiteral::FunctionType type,
1814 FunctionLiteral::ArityRestriction arity_restriction, bool* ok); 1604 FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1988 return pre_parser_->factory()->NewCall(function, args, pos); 1778 return pre_parser_->factory()->NewCall(function, args, pos);
1989 } 1779 }
1990 1780
1991 PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function, 1781 PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function,
1992 PreParserExpressionList args, 1782 PreParserExpressionList args,
1993 int pos) { 1783 int pos) {
1994 return pre_parser_->factory()->NewCallNew(function, args, pos); 1784 return pre_parser_->factory()->NewCallNew(function, args, pos);
1995 } 1785 }
1996 1786
1997 1787
1998 bool PreParserTraits::DeclareFormalParameter(
1999 DuplicateFinder* duplicate_finder, PreParserIdentifier current_identifier,
2000 bool is_rest) {
2001 return pre_parser_->scanner()->FindSymbol(duplicate_finder, 1) != 0;
2002 }
2003
2004
2005 void PreParserTraits::ParseArrowFunctionFormalParameters( 1788 void PreParserTraits::ParseArrowFunctionFormalParameters(
2006 Scope* scope, PreParserExpression params, 1789 Scope* scope, PreParserExpression params,
2007 const Scanner::Location& params_loc, bool* is_rest, 1790 const Scanner::Location& params_loc, bool* is_rest,
2008 Scanner::Location* duplicate_loc, bool* ok) { 1791 Scanner::Location* duplicate_loc, bool* ok) {
2009 // TODO(wingo): Detect duplicated identifiers in paramlists. Detect parameter 1792 // TODO(wingo): Detect duplicated identifiers in paramlists. Detect parameter
2010 // lists that are too long. 1793 // lists that are too long.
2011 } 1794 }
2012 1795
2013 1796
2014 PreParserStatementList PreParser::ParseEagerFunctionBody( 1797 PreParserStatementList PreParser::ParseEagerFunctionBody(
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2167 classifier->RecordStrongModeFormalParameterError( 1950 classifier->RecordStrongModeFormalParameterError(
2168 scanner()->location(), MessageTemplate::kStrongUndefined); 1951 scanner()->location(), MessageTemplate::kStrongUndefined);
2169 if (is_strong(language_mode())) { 1952 if (is_strong(language_mode())) {
2170 // TODO(dslomov): allow 'undefined' in nested patterns. 1953 // TODO(dslomov): allow 'undefined' in nested patterns.
2171 classifier->RecordBindingPatternError( 1954 classifier->RecordBindingPatternError(
2172 scanner()->location(), MessageTemplate::kStrongUndefined); 1955 scanner()->location(), MessageTemplate::kStrongUndefined);
2173 classifier->RecordAssignmentPatternError( 1956 classifier->RecordAssignmentPatternError(
2174 scanner()->location(), MessageTemplate::kStrongUndefined); 1957 scanner()->location(), MessageTemplate::kStrongUndefined);
2175 } 1958 }
2176 } 1959 }
1960
1961 if (classifier->duplicate_finder() != nullptr &&
1962 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
1963 classifier->RecordDuplicateFormalParameterError(scanner()->location());
1964 }
2177 return name; 1965 return name;
2178 } else if (is_sloppy(language_mode()) && 1966 } else if (is_sloppy(language_mode()) &&
2179 (next == Token::FUTURE_STRICT_RESERVED_WORD || 1967 (next == Token::FUTURE_STRICT_RESERVED_WORD ||
2180 next == Token::LET || next == Token::STATIC || 1968 next == Token::LET || next == Token::STATIC ||
2181 (next == Token::YIELD && !is_generator()))) { 1969 (next == Token::YIELD && !is_generator()))) {
2182 classifier->RecordStrictModeFormalParameterError( 1970 classifier->RecordStrictModeFormalParameterError(
2183 scanner()->location(), MessageTemplate::kUnexpectedStrictReserved); 1971 scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
2184 return this->GetSymbol(scanner()); 1972 return this->GetSymbol(scanner());
2185 } else { 1973 } else {
2186 this->ReportUnexpectedToken(next); 1974 this->ReportUnexpectedToken(next);
(...skipping 1479 matching lines...) Expand 10 before | Expand all | Expand 10 after
3666 template <class Traits> 3454 template <class Traits>
3667 void ParserBase<Traits>::ParseFormalParameter(FormalParameterScopeT* scope, 3455 void ParserBase<Traits>::ParseFormalParameter(FormalParameterScopeT* scope,
3668 bool is_rest, 3456 bool is_rest,
3669 ExpressionClassifier* classifier, 3457 ExpressionClassifier* classifier,
3670 bool* ok) { 3458 bool* ok) {
3671 // FormalParameter[Yield,GeneratorParameter] : 3459 // FormalParameter[Yield,GeneratorParameter] :
3672 // BindingElement[?Yield, ?GeneratorParameter] 3460 // BindingElement[?Yield, ?GeneratorParameter]
3673 IdentifierT name = ParseAndClassifyIdentifier(classifier, ok); 3461 IdentifierT name = ParseAndClassifyIdentifier(classifier, ok);
3674 if (!*ok) return; 3462 if (!*ok) return;
3675 3463
3676 bool was_declared = Traits::DeclareFormalParameter(scope, name, is_rest); 3464 Traits::DeclareFormalParameter(scope, name, classifier, is_rest);
3677 if (was_declared) {
3678 classifier->RecordDuplicateFormalParameterError(scanner()->location());
3679 }
3680 } 3465 }
3681 3466
3682 3467
3683 template <class Traits> 3468 template <class Traits>
3684 int ParserBase<Traits>::ParseFormalParameterList( 3469 int ParserBase<Traits>::ParseFormalParameterList(
3685 FormalParameterScopeT* scope, bool* is_rest, 3470 FormalParameterScopeT* scope, bool* is_rest,
3686 ExpressionClassifier* classifier, bool* ok) { 3471 ExpressionClassifier* classifier, bool* ok) {
3687 // FormalParameters[Yield,GeneratorParameter] : 3472 // FormalParameters[Yield,GeneratorParameter] :
3688 // [empty] 3473 // [empty]
3689 // FormalParameterList[?Yield, ?GeneratorParameter] 3474 // FormalParameterList[?Yield, ?GeneratorParameter]
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
4033 *ok = false; 3818 *ok = false;
4034 return; 3819 return;
4035 } 3820 }
4036 has_seen_constructor_ = true; 3821 has_seen_constructor_ = true;
4037 return; 3822 return;
4038 } 3823 }
4039 } 3824 }
4040 } } // v8::internal 3825 } } // v8::internal
4041 3826
4042 #endif // V8_PREPARSER_H 3827 #endif // V8_PREPARSER_H
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698