[presubmit] Enable readability/namespace linter checking.
[platform/upstream/v8.git] / src / expression-classifier.h
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_EXPRESSION_CLASSIFIER_H
6 #define V8_EXPRESSION_CLASSIFIER_H
7
8 #include "src/messages.h"
9 #include "src/scanner.h"
10 #include "src/token.h"
11
12 namespace v8 {
13 namespace internal {
14
15
16 class ExpressionClassifier {
17  public:
18   struct Error {
19     Error()
20         : location(Scanner::Location::invalid()),
21           message(MessageTemplate::kNone),
22           arg(nullptr) {}
23
24     Scanner::Location location;
25     MessageTemplate::Template message;
26     const char* arg;
27   };
28
29   enum TargetProduction {
30     ExpressionProduction = 1 << 0,
31     FormalParameterInitializerProduction = 1 << 1,
32     BindingPatternProduction = 1 << 2,
33     AssignmentPatternProduction = 1 << 3,
34     DistinctFormalParametersProduction = 1 << 4,
35     StrictModeFormalParametersProduction = 1 << 5,
36     StrongModeFormalParametersProduction = 1 << 6,
37     ArrowFormalParametersProduction = 1 << 7,
38
39     ExpressionProductions =
40         (ExpressionProduction | FormalParameterInitializerProduction),
41     PatternProductions =
42         (BindingPatternProduction | AssignmentPatternProduction),
43     FormalParametersProductions = (DistinctFormalParametersProduction |
44                                    StrictModeFormalParametersProduction |
45                                    StrongModeFormalParametersProduction),
46     StandardProductions = ExpressionProductions | PatternProductions,
47     AllProductions = (StandardProductions | FormalParametersProductions |
48                       ArrowFormalParametersProduction)
49   };
50
51   enum FunctionProperties { NonSimpleParameter = 1 << 0 };
52
53   ExpressionClassifier()
54       : invalid_productions_(0),
55         function_properties_(0),
56         duplicate_finder_(nullptr) {}
57
58   explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
59       : invalid_productions_(0),
60         function_properties_(0),
61         duplicate_finder_(duplicate_finder) {}
62
63   bool is_valid(unsigned productions) const {
64     return (invalid_productions_ & productions) == 0;
65   }
66
67   DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
68
69   bool is_valid_expression() const { return is_valid(ExpressionProduction); }
70
71   bool is_valid_formal_parameter_initializer() const {
72     return is_valid(FormalParameterInitializerProduction);
73   }
74
75   bool is_valid_binding_pattern() const {
76     return is_valid(BindingPatternProduction);
77   }
78
79   bool is_valid_assignment_pattern() const {
80     return is_valid(AssignmentPatternProduction);
81   }
82
83   bool is_valid_arrow_formal_parameters() const {
84     return is_valid(ArrowFormalParametersProduction);
85   }
86
87   bool is_valid_formal_parameter_list_without_duplicates() const {
88     return is_valid(DistinctFormalParametersProduction);
89   }
90
91   // Note: callers should also check
92   // is_valid_formal_parameter_list_without_duplicates().
93   bool is_valid_strict_mode_formal_parameters() const {
94     return is_valid(StrictModeFormalParametersProduction);
95   }
96
97   // Note: callers should also check is_valid_strict_mode_formal_parameters()
98   // and is_valid_formal_parameter_list_without_duplicates().
99   bool is_valid_strong_mode_formal_parameters() const {
100     return is_valid(StrongModeFormalParametersProduction);
101   }
102
103   const Error& expression_error() const { return expression_error_; }
104
105   const Error& formal_parameter_initializer_error() const {
106     return formal_parameter_initializer_error_;
107   }
108
109   const Error& binding_pattern_error() const { return binding_pattern_error_; }
110
111   const Error& assignment_pattern_error() const {
112     return assignment_pattern_error_;
113   }
114
115   const Error& arrow_formal_parameters_error() const {
116     return arrow_formal_parameters_error_;
117   }
118
119   const Error& duplicate_formal_parameter_error() const {
120     return duplicate_formal_parameter_error_;
121   }
122
123   const Error& strict_mode_formal_parameter_error() const {
124     return strict_mode_formal_parameter_error_;
125   }
126
127   const Error& strong_mode_formal_parameter_error() const {
128     return strong_mode_formal_parameter_error_;
129   }
130
131   bool is_simple_parameter_list() const {
132     return !(function_properties_ & NonSimpleParameter);
133   }
134
135   void RecordNonSimpleParameter() {
136     function_properties_ |= NonSimpleParameter;
137   }
138
139   void RecordExpressionError(const Scanner::Location& loc,
140                              MessageTemplate::Template message,
141                              const char* arg = nullptr) {
142     if (!is_valid_expression()) return;
143     invalid_productions_ |= ExpressionProduction;
144     expression_error_.location = loc;
145     expression_error_.message = message;
146     expression_error_.arg = arg;
147   }
148
149   void RecordFormalParameterInitializerError(const Scanner::Location& loc,
150                                              MessageTemplate::Template message,
151                                              const char* arg = nullptr) {
152     if (!is_valid_formal_parameter_initializer()) return;
153     invalid_productions_ |= FormalParameterInitializerProduction;
154     formal_parameter_initializer_error_.location = loc;
155     formal_parameter_initializer_error_.message = message;
156     formal_parameter_initializer_error_.arg = arg;
157   }
158
159   void RecordBindingPatternError(const Scanner::Location& loc,
160                                  MessageTemplate::Template message,
161                                  const char* arg = nullptr) {
162     if (!is_valid_binding_pattern()) return;
163     invalid_productions_ |= BindingPatternProduction;
164     binding_pattern_error_.location = loc;
165     binding_pattern_error_.message = message;
166     binding_pattern_error_.arg = arg;
167   }
168
169   void RecordAssignmentPatternError(const Scanner::Location& loc,
170                                     MessageTemplate::Template message,
171                                     const char* arg = nullptr) {
172     if (!is_valid_assignment_pattern()) return;
173     invalid_productions_ |= AssignmentPatternProduction;
174     assignment_pattern_error_.location = loc;
175     assignment_pattern_error_.message = message;
176     assignment_pattern_error_.arg = arg;
177   }
178
179   void RecordArrowFormalParametersError(const Scanner::Location& loc,
180                                         MessageTemplate::Template message,
181                                         const char* arg = nullptr) {
182     if (!is_valid_arrow_formal_parameters()) return;
183     invalid_productions_ |= ArrowFormalParametersProduction;
184     arrow_formal_parameters_error_.location = loc;
185     arrow_formal_parameters_error_.message = message;
186     arrow_formal_parameters_error_.arg = arg;
187   }
188
189   void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
190     if (!is_valid_formal_parameter_list_without_duplicates()) return;
191     invalid_productions_ |= DistinctFormalParametersProduction;
192     duplicate_formal_parameter_error_.location = loc;
193     duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
194     duplicate_formal_parameter_error_.arg = nullptr;
195   }
196
197   // Record a binding that would be invalid in strict mode.  Confusingly this
198   // is not the same as StrictFormalParameterList, which simply forbids
199   // duplicate bindings.
200   void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
201                                             MessageTemplate::Template message,
202                                             const char* arg = nullptr) {
203     if (!is_valid_strict_mode_formal_parameters()) return;
204     invalid_productions_ |= StrictModeFormalParametersProduction;
205     strict_mode_formal_parameter_error_.location = loc;
206     strict_mode_formal_parameter_error_.message = message;
207     strict_mode_formal_parameter_error_.arg = arg;
208   }
209
210   void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
211                                             MessageTemplate::Template message,
212                                             const char* arg = nullptr) {
213     if (!is_valid_strong_mode_formal_parameters()) return;
214     invalid_productions_ |= StrongModeFormalParametersProduction;
215     strong_mode_formal_parameter_error_.location = loc;
216     strong_mode_formal_parameter_error_.message = message;
217     strong_mode_formal_parameter_error_.arg = arg;
218   }
219
220   void Accumulate(const ExpressionClassifier& inner,
221                   unsigned productions = StandardProductions) {
222     // Propagate errors from inner, but don't overwrite already recorded
223     // errors.
224     unsigned non_arrow_inner_invalid_productions =
225         inner.invalid_productions_ & ~ArrowFormalParametersProduction;
226     if (non_arrow_inner_invalid_productions == 0) return;
227     unsigned non_arrow_productions =
228         productions & ~ArrowFormalParametersProduction;
229     unsigned errors =
230         non_arrow_productions & non_arrow_inner_invalid_productions;
231     errors &= ~invalid_productions_;
232     if (errors != 0) {
233       invalid_productions_ |= errors;
234       if (errors & ExpressionProduction)
235         expression_error_ = inner.expression_error_;
236       if (errors & FormalParameterInitializerProduction)
237         formal_parameter_initializer_error_ =
238             inner.formal_parameter_initializer_error_;
239       if (errors & BindingPatternProduction)
240         binding_pattern_error_ = inner.binding_pattern_error_;
241       if (errors & AssignmentPatternProduction)
242         assignment_pattern_error_ = inner.assignment_pattern_error_;
243       if (errors & DistinctFormalParametersProduction)
244         duplicate_formal_parameter_error_ =
245             inner.duplicate_formal_parameter_error_;
246       if (errors & StrictModeFormalParametersProduction)
247         strict_mode_formal_parameter_error_ =
248             inner.strict_mode_formal_parameter_error_;
249       if (errors & StrongModeFormalParametersProduction)
250         strong_mode_formal_parameter_error_ =
251             inner.strong_mode_formal_parameter_error_;
252     }
253
254     // As an exception to the above, the result continues to be a valid arrow
255     // formal parameters if the inner expression is a valid binding pattern.
256     if (productions & ArrowFormalParametersProduction &&
257         is_valid_arrow_formal_parameters()) {
258       // Also copy function properties if expecting an arrow function
259       // parameter.
260       function_properties_ |= inner.function_properties_;
261
262       if (!inner.is_valid_binding_pattern()) {
263         invalid_productions_ |= ArrowFormalParametersProduction;
264         arrow_formal_parameters_error_ = inner.binding_pattern_error_;
265       }
266     }
267   }
268
269  private:
270   unsigned invalid_productions_;
271   unsigned function_properties_;
272   Error expression_error_;
273   Error formal_parameter_initializer_error_;
274   Error binding_pattern_error_;
275   Error assignment_pattern_error_;
276   Error arrow_formal_parameters_error_;
277   Error duplicate_formal_parameter_error_;
278   Error strict_mode_formal_parameter_error_;
279   Error strong_mode_formal_parameter_error_;
280   DuplicateFinder* duplicate_finder_;
281 };
282
283 }  // namespace internal
284 }  // namespace v8
285
286 #endif  // V8_EXPRESSION_CLASSIFIER_H