[destructuring] Refactor duplicate parameter name detection.
[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/v8.h"
9
10 #include "src/messages.h"
11 #include "src/scanner.h"
12 #include "src/token.h"
13
14 namespace v8 {
15 namespace internal {
16
17
18 class ExpressionClassifier {
19  public:
20   struct Error {
21     Error()
22         : location(Scanner::Location::invalid()),
23           message(MessageTemplate::kNone),
24           arg(nullptr) {}
25
26     Scanner::Location location;
27     MessageTemplate::Template message;
28     const char* arg;
29   };
30
31   enum TargetProduction {
32     ExpressionProduction = 1 << 0,
33     BindingPatternProduction = 1 << 1,
34     AssignmentPatternProduction = 1 << 2,
35     DistinctFormalParametersProduction = 1 << 3,
36     StrictModeFormalParametersProduction = 1 << 4,
37     StrongModeFormalParametersProduction = 1 << 5,
38     ArrowFormalParametersProduction = 1 << 6,
39
40     PatternProductions =
41         (BindingPatternProduction | AssignmentPatternProduction),
42     FormalParametersProductions = (DistinctFormalParametersProduction |
43                                    StrictModeFormalParametersProduction |
44                                    StrongModeFormalParametersProduction),
45     StandardProductions = ExpressionProduction | PatternProductions,
46     AllProductions = (StandardProductions | FormalParametersProductions |
47                       ArrowFormalParametersProduction)
48   };
49
50   ExpressionClassifier()
51       : invalid_productions_(0), duplicate_finder_(nullptr) {}
52
53   explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
54       : invalid_productions_(0), duplicate_finder_(duplicate_finder) {}
55
56   bool is_valid(unsigned productions) const {
57     return (invalid_productions_ & productions) == 0;
58   }
59
60   DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
61
62   bool is_valid_expression() const { return is_valid(ExpressionProduction); }
63
64   bool is_valid_binding_pattern() const {
65     return is_valid(BindingPatternProduction);
66   }
67
68   bool is_valid_assignment_pattern() const {
69     return is_valid(AssignmentPatternProduction);
70   }
71
72   bool is_valid_arrow_formal_parameters() const {
73     return is_valid(ArrowFormalParametersProduction);
74   }
75
76   bool is_valid_formal_parameter_list_without_duplicates() const {
77     return is_valid(DistinctFormalParametersProduction);
78   }
79
80   // Note: callers should also check
81   // is_valid_formal_parameter_list_without_duplicates().
82   bool is_valid_strict_mode_formal_parameters() const {
83     return is_valid(StrictModeFormalParametersProduction);
84   }
85
86   // Note: callers should also check is_valid_strict_mode_formal_parameters()
87   // and is_valid_formal_parameter_list_without_duplicates().
88   bool is_valid_strong_mode_formal_parameters() const {
89     return is_valid(StrongModeFormalParametersProduction);
90   }
91
92   const Error& expression_error() const { return expression_error_; }
93
94   const Error& binding_pattern_error() const { return binding_pattern_error_; }
95
96   const Error& assignment_pattern_error() const {
97     return assignment_pattern_error_;
98   }
99
100   const Error& arrow_formal_parameters_error() const {
101     return arrow_formal_parameters_error_;
102   }
103
104   const Error& duplicate_formal_parameter_error() const {
105     return duplicate_formal_parameter_error_;
106   }
107
108   const Error& strict_mode_formal_parameter_error() const {
109     return strict_mode_formal_parameter_error_;
110   }
111
112   const Error& strong_mode_formal_parameter_error() const {
113     return strong_mode_formal_parameter_error_;
114   }
115
116   void RecordExpressionError(const Scanner::Location& loc,
117                              MessageTemplate::Template message,
118                              const char* arg = nullptr) {
119     if (!is_valid_expression()) return;
120     invalid_productions_ |= ExpressionProduction;
121     expression_error_.location = loc;
122     class ExpressionClassifier {
123      public:
124       struct Error {
125         Error()
126             : location(Scanner::Location::invalid()),
127               message(MessageTemplate::kNone),
128               arg(nullptr) {}
129
130         Scanner::Location location;
131         MessageTemplate::Template message;
132         const char* arg;
133
134         bool HasError() const { return location.IsValid(); }
135       };
136
137       ExpressionClassifier() : duplicate_finder_(nullptr) {}
138
139       explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
140           : duplicate_finder_(duplicate_finder) {}
141
142       DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
143
144       bool is_valid_expression() const { return !expression_error_.HasError(); }
145
146       bool is_valid_binding_pattern() const {
147         return !binding_pattern_error_.HasError();
148       }
149
150       bool is_valid_assignment_pattern() const {
151         return !assignment_pattern_error_.HasError();
152       }
153
154       bool is_valid_arrow_formal_parameters() const {
155         return !arrow_formal_parameters_error_.HasError();
156       }
157
158       bool is_valid_formal_parameter_list_without_duplicates() const {
159         return !duplicate_formal_parameter_error_.HasError();
160       }
161
162       // Note: callers should also check
163       // is_valid_formal_parameter_list_without_duplicates().
164       bool is_valid_strict_mode_formal_parameters() const {
165         return !strict_mode_formal_parameter_error_.HasError();
166       }
167
168       // Note: callers should also check
169       // is_valid_strict_mode_formal_parameters()
170       // and is_valid_formal_parameter_list_without_duplicates().
171       bool is_valid_strong_mode_formal_parameters() const {
172         return !strong_mode_formal_parameter_error_.HasError();
173       }
174
175       const Error& expression_error() const { return expression_error_; }
176
177       const Error& binding_pattern_error() const {
178         return binding_pattern_error_;
179       }
180
181       const Error& assignment_pattern_error() const {
182         return assignment_pattern_error_;
183       }
184
185       const Error& arrow_formal_parameters_error() const {
186         return arrow_formal_parameters_error_;
187       }
188
189       const Error& duplicate_formal_parameter_error() const {
190         return duplicate_formal_parameter_error_;
191       }
192
193       const Error& strict_mode_formal_parameter_error() const {
194         return strict_mode_formal_parameter_error_;
195       }
196
197       const Error& strong_mode_formal_parameter_error() const {
198         return strong_mode_formal_parameter_error_;
199       }
200
201       void RecordExpressionError(const Scanner::Location& loc,
202                                  MessageTemplate::Template message,
203                                  const char* arg = nullptr) {
204         if (!is_valid_expression()) return;
205         expression_error_.location = loc;
206         expression_error_.message = message;
207         expression_error_.arg = arg;
208       }
209
210       void RecordBindingPatternError(const Scanner::Location& loc,
211                                      MessageTemplate::Template message,
212                                      const char* arg = nullptr) {
213         if (!is_valid_binding_pattern()) return;
214         binding_pattern_error_.location = loc;
215         binding_pattern_error_.message = message;
216         binding_pattern_error_.arg = arg;
217       }
218
219       void RecordAssignmentPatternError(const Scanner::Location& loc,
220                                         MessageTemplate::Template message,
221                                         const char* arg = nullptr) {
222         if (!is_valid_assignment_pattern()) return;
223         assignment_pattern_error_.location = loc;
224         assignment_pattern_error_.message = message;
225         assignment_pattern_error_.arg = arg;
226       }
227
228       void RecordArrowFormalParametersError(const Scanner::Location& loc,
229                                             MessageTemplate::Template message,
230                                             const char* arg = nullptr) {
231         if (!is_valid_arrow_formal_parameters()) return;
232         arrow_formal_parameters_error_.location = loc;
233         arrow_formal_parameters_error_.message = message;
234         arrow_formal_parameters_error_.arg = arg;
235       }
236
237       void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
238         if (!is_valid_formal_parameter_list_without_duplicates()) return;
239         duplicate_formal_parameter_error_.location = loc;
240         duplicate_formal_parameter_error_.message =
241             MessageTemplate::kStrictParamDupe;
242         duplicate_formal_parameter_error_.arg = nullptr;
243       }
244
245       // Record a binding that would be invalid in strict mode.  Confusingly
246       // this
247       // is not the same as StrictFormalParameterList, which simply forbids
248       // duplicate bindings.
249       void RecordStrictModeFormalParameterError(
250           const Scanner::Location& loc, MessageTemplate::Template message,
251           const char* arg = nullptr) {
252         if (!is_valid_strict_mode_formal_parameters()) return;
253         strict_mode_formal_parameter_error_.location = loc;
254         strict_mode_formal_parameter_error_.message = message;
255         strict_mode_formal_parameter_error_.arg = arg;
256       }
257
258       void RecordStrongModeFormalParameterError(
259           const Scanner::Location& loc, MessageTemplate::Template message,
260           const char* arg = nullptr) {
261         if (!is_valid_strong_mode_formal_parameters()) return;
262         strong_mode_formal_parameter_error_.location = loc;
263         strong_mode_formal_parameter_error_.message = message;
264         strong_mode_formal_parameter_error_.arg = arg;
265       }
266
267       enum TargetProduction {
268         ExpressionProduction = 1 << 0,
269         BindingPatternProduction = 1 << 1,
270         AssignmentPatternProduction = 1 << 2,
271         FormalParametersProduction = 1 << 3,
272         ArrowFormalParametersProduction = 1 << 4,
273         StandardProductions = (ExpressionProduction | BindingPatternProduction |
274                                AssignmentPatternProduction),
275         PatternProductions =
276             BindingPatternProduction | AssignmentPatternProduction,
277         AllProductions = (StandardProductions | FormalParametersProduction |
278                           ArrowFormalParametersProduction),
279       };
280
281       void Accumulate(const ExpressionClassifier& inner,
282                       unsigned productions = StandardProductions) {
283         if (productions & ExpressionProduction && is_valid_expression()) {
284           expression_error_ = inner.expression_error_;
285         }
286         if (productions & BindingPatternProduction &&
287             is_valid_binding_pattern()) {
288           binding_pattern_error_ = inner.binding_pattern_error_;
289         }
290         if (productions & AssignmentPatternProduction &&
291             is_valid_assignment_pattern()) {
292           assignment_pattern_error_ = inner.assignment_pattern_error_;
293         }
294         if (productions & FormalParametersProduction) {
295           if (is_valid_formal_parameter_list_without_duplicates()) {
296             duplicate_formal_parameter_error_ =
297                 inner.duplicate_formal_parameter_error_;
298           }
299           if (is_valid_strict_mode_formal_parameters()) {
300             strict_mode_formal_parameter_error_ =
301                 inner.strict_mode_formal_parameter_error_;
302           }
303           if (is_valid_strong_mode_formal_parameters()) {
304             strong_mode_formal_parameter_error_ =
305                 inner.strong_mode_formal_parameter_error_;
306           }
307         }
308         if (productions & ArrowFormalParametersProduction &&
309             is_valid_arrow_formal_parameters()) {
310           // The result continues to be a valid arrow formal parameters if the
311           // inner expression is a valid binding pattern.
312           arrow_formal_parameters_error_ = inner.binding_pattern_error_;
313         }
314       }
315
316       void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
317         Accumulate(inner, AllProductions & ~PatternProductions);
318         if (!inner.is_valid_expression()) {
319           if (is_valid_binding_pattern()) {
320             binding_pattern_error_ = inner.expression_error();
321           }
322           if (is_valid_assignment_pattern()) {
323             assignment_pattern_error_ = inner.expression_error();
324           }
325         }
326       }
327
328      private:
329       Error expression_error_;
330       Error binding_pattern_error_;
331       Error assignment_pattern_error_;
332       Error arrow_formal_parameters_error_;
333       Error duplicate_formal_parameter_error_;
334       Error strict_mode_formal_parameter_error_;
335       Error strong_mode_formal_parameter_error_;
336       DuplicateFinder* duplicate_finder_;
337     };
338     expression_error_.message = message;
339     expression_error_.arg = arg;
340   }
341
342   void RecordBindingPatternError(const Scanner::Location& loc,
343                                  MessageTemplate::Template message,
344                                  const char* arg = nullptr) {
345     if (!is_valid_binding_pattern()) return;
346     invalid_productions_ |= BindingPatternProduction;
347     binding_pattern_error_.location = loc;
348     binding_pattern_error_.message = message;
349     binding_pattern_error_.arg = arg;
350   }
351
352   void RecordAssignmentPatternError(const Scanner::Location& loc,
353                                     MessageTemplate::Template message,
354                                     const char* arg = nullptr) {
355     if (!is_valid_assignment_pattern()) return;
356     invalid_productions_ |= AssignmentPatternProduction;
357     assignment_pattern_error_.location = loc;
358     assignment_pattern_error_.message = message;
359     assignment_pattern_error_.arg = arg;
360   }
361
362   void RecordArrowFormalParametersError(const Scanner::Location& loc,
363                                         MessageTemplate::Template message,
364                                         const char* arg = nullptr) {
365     if (!is_valid_arrow_formal_parameters()) return;
366     invalid_productions_ |= ArrowFormalParametersProduction;
367     arrow_formal_parameters_error_.location = loc;
368     arrow_formal_parameters_error_.message = message;
369     arrow_formal_parameters_error_.arg = arg;
370   }
371
372   void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
373     if (!is_valid_formal_parameter_list_without_duplicates()) return;
374     invalid_productions_ |= DistinctFormalParametersProduction;
375     duplicate_formal_parameter_error_.location = loc;
376     duplicate_formal_parameter_error_.message =
377         MessageTemplate::kStrictParamDupe;
378     duplicate_formal_parameter_error_.arg = nullptr;
379   }
380
381   // Record a binding that would be invalid in strict mode.  Confusingly this
382   // is not the same as StrictFormalParameterList, which simply forbids
383   // duplicate bindings.
384   void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
385                                             MessageTemplate::Template message,
386                                             const char* arg = nullptr) {
387     if (!is_valid_strict_mode_formal_parameters()) return;
388     invalid_productions_ |= StrictModeFormalParametersProduction;
389     strict_mode_formal_parameter_error_.location = loc;
390     strict_mode_formal_parameter_error_.message = message;
391     strict_mode_formal_parameter_error_.arg = arg;
392   }
393
394   void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
395                                             MessageTemplate::Template message,
396                                             const char* arg = nullptr) {
397     if (!is_valid_strong_mode_formal_parameters()) return;
398     invalid_productions_ |= StrongModeFormalParametersProduction;
399     strong_mode_formal_parameter_error_.location = loc;
400     strong_mode_formal_parameter_error_.message = message;
401     strong_mode_formal_parameter_error_.arg = arg;
402   }
403
404   void Accumulate(const ExpressionClassifier& inner,
405                   unsigned productions = StandardProductions) {
406     // Propagate errors from inner, but don't overwrite already recorded
407     // errors.
408     unsigned non_arrow_inner_invalid_productions =
409         inner.invalid_productions_ & ~ArrowFormalParametersProduction;
410     if (non_arrow_inner_invalid_productions == 0) return;
411     unsigned non_arrow_productions =
412         productions & ~ArrowFormalParametersProduction;
413     unsigned errors =
414         non_arrow_productions & non_arrow_inner_invalid_productions;
415     errors &= ~invalid_productions_;
416     if (errors != 0) {
417       invalid_productions_ |= errors;
418       if (errors & ExpressionProduction)
419         expression_error_ = inner.expression_error_;
420       if (errors & BindingPatternProduction)
421         binding_pattern_error_ = inner.binding_pattern_error_;
422       if (errors & AssignmentPatternProduction)
423         assignment_pattern_error_ = inner.assignment_pattern_error_;
424       if (errors & DistinctFormalParametersProduction)
425         duplicate_formal_parameter_error_ =
426             inner.duplicate_formal_parameter_error_;
427       if (errors & StrictModeFormalParametersProduction)
428         strict_mode_formal_parameter_error_ =
429             inner.strict_mode_formal_parameter_error_;
430       if (errors & StrongModeFormalParametersProduction)
431         strong_mode_formal_parameter_error_ =
432             inner.strong_mode_formal_parameter_error_;
433     }
434
435     // As an exception to the above, the result continues to be a valid arrow
436     // formal parameters if the inner expression is a valid binding pattern.
437     if (productions & ArrowFormalParametersProduction &&
438         is_valid_arrow_formal_parameters() &&
439         !inner.is_valid_binding_pattern()) {
440       invalid_productions_ |= ArrowFormalParametersProduction;
441       arrow_formal_parameters_error_ = inner.binding_pattern_error_;
442     }
443   }
444
445   void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
446     Accumulate(inner, AllProductions & ~PatternProductions);
447     if (!inner.is_valid_expression()) {
448       if (is_valid_binding_pattern()) {
449         binding_pattern_error_ = inner.expression_error();
450       }
451       if (is_valid_assignment_pattern()) {
452         assignment_pattern_error_ = inner.expression_error();
453       }
454     }
455   }
456
457  private:
458   unsigned invalid_productions_;
459   Error expression_error_;
460   Error binding_pattern_error_;
461   Error assignment_pattern_error_;
462   Error arrow_formal_parameters_error_;
463   Error duplicate_formal_parameter_error_;
464   Error strict_mode_formal_parameter_error_;
465   Error strong_mode_formal_parameter_error_;
466   DuplicateFinder* duplicate_finder_;
467 };
468 }
469 }  // v8::internal
470
471 #endif  // V8_EXPRESSION_CLASSIFIER_H