OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 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_PARSING_EXPRESSION_CLASSIFIER_H | 5 #ifndef V8_PARSING_EXPRESSION_CLASSIFIER_H |
6 #define V8_PARSING_EXPRESSION_CLASSIFIER_H | 6 #define V8_PARSING_EXPRESSION_CLASSIFIER_H |
7 | 7 |
8 #include "src/messages.h" | 8 #include "src/messages.h" |
9 #include "src/parsing/scanner.h" | 9 #include "src/parsing/scanner.h" |
10 #include "src/parsing/token.h" | 10 #include "src/parsing/token.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 | 15 |
16 #define ERROR_CODES(T) \ | |
17 T(ExpressionProduction, 0) \ | |
18 T(FormalParameterInitializerProduction, 1) \ | |
19 T(BindingPatternProduction, 2) \ | |
20 T(AssignmentPatternProduction, 3) \ | |
21 T(DistinctFormalParametersProduction, 4) \ | |
22 T(StrictModeFormalParametersProduction, 5) \ | |
23 T(ArrowFormalParametersProduction, 6) \ | |
24 T(LetPatternProduction, 7) \ | |
25 T(CoverInitializedNameProduction, 8) \ | |
26 T(TailCallExpressionProduction, 9) \ | |
27 T(AsyncArrowFormalParametersProduction, 10) \ | |
28 T(AsyncBindingPatternProduction, 11) | |
29 | |
30 | |
16 template <typename Traits> | 31 template <typename Traits> |
17 class ExpressionClassifier { | 32 class ExpressionClassifier { |
18 public: | 33 public: |
34 enum ErrorKind : unsigned { | |
35 #define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE, | |
36 ERROR_CODES(DEFINE_ERROR_KIND) | |
37 #undef DEFINE_ERROR_KIND | |
38 kUnusedError = 15 // Larger than error codes; should fit in 4 bits | |
39 }; | |
40 | |
19 struct Error { | 41 struct Error { |
20 Error() | 42 V8_INLINE Error() |
21 : location(Scanner::Location::invalid()), | 43 : location(Scanner::Location::invalid()), |
22 message(MessageTemplate::kNone), | 44 message(MessageTemplate::kNone), |
45 kind(kUnusedError), | |
23 type(kSyntaxError), | 46 type(kSyntaxError), |
24 arg(nullptr) {} | 47 arg(nullptr) {} |
48 V8_INLINE explicit Error(Scanner::Location loc, | |
49 MessageTemplate::Template msg, ErrorKind k, | |
50 const char* a = nullptr, | |
51 ParseErrorType t = kSyntaxError) | |
52 : location(loc), message(msg), kind(k), type(t), arg(a) {} | |
25 | 53 |
26 Scanner::Location location; | 54 Scanner::Location location; |
27 MessageTemplate::Template message : 30; | 55 MessageTemplate::Template message : 26; |
56 unsigned kind : 4; | |
28 ParseErrorType type : 2; | 57 ParseErrorType type : 2; |
29 const char* arg; | 58 const char* arg; |
30 }; | 59 }; |
31 | 60 |
32 enum TargetProduction { | 61 enum TargetProduction : unsigned { |
33 ExpressionProduction = 1 << 0, | 62 #define DEFINE_PRODUCTION(NAME, CODE) NAME = 1 << CODE, |
34 FormalParameterInitializerProduction = 1 << 1, | 63 ERROR_CODES(DEFINE_PRODUCTION) |
35 BindingPatternProduction = 1 << 2, | 64 #undef DEFINE_PRODUCTION |
36 AssignmentPatternProduction = 1 << 3, | |
37 DistinctFormalParametersProduction = 1 << 4, | |
38 StrictModeFormalParametersProduction = 1 << 5, | |
39 ArrowFormalParametersProduction = 1 << 6, | |
40 LetPatternProduction = 1 << 7, | |
41 CoverInitializedNameProduction = 1 << 8, | |
42 TailCallExpressionProduction = 1 << 9, | |
43 AsyncArrowFormalParametersProduction = 1 << 10, | |
44 AsyncBindingPatternProduction = 1 << 11, | |
45 | 65 |
46 ExpressionProductions = | 66 ExpressionProductions = |
47 (ExpressionProduction | FormalParameterInitializerProduction | | 67 (ExpressionProduction | FormalParameterInitializerProduction | |
48 TailCallExpressionProduction), | 68 TailCallExpressionProduction), |
49 PatternProductions = | 69 PatternProductions = |
50 (BindingPatternProduction | AssignmentPatternProduction | | 70 (BindingPatternProduction | AssignmentPatternProduction | |
51 LetPatternProduction | AsyncBindingPatternProduction), | 71 LetPatternProduction | AsyncBindingPatternProduction), |
52 FormalParametersProductions = (DistinctFormalParametersProduction | | 72 FormalParametersProductions = (DistinctFormalParametersProduction | |
53 StrictModeFormalParametersProduction), | 73 StrictModeFormalParametersProduction), |
54 StandardProductions = ExpressionProductions | PatternProductions, | 74 StandardProductions = ExpressionProductions | PatternProductions, |
55 AllProductions = | 75 AllProductions = |
56 (StandardProductions | FormalParametersProductions | | 76 (StandardProductions | FormalParametersProductions | |
57 ArrowFormalParametersProduction | CoverInitializedNameProduction | | 77 ArrowFormalParametersProduction | CoverInitializedNameProduction | |
58 AsyncArrowFormalParametersProduction | AsyncBindingPatternProduction) | 78 AsyncArrowFormalParametersProduction | AsyncBindingPatternProduction) |
59 }; | 79 }; |
60 | 80 |
61 enum FunctionProperties { NonSimpleParameter = 1 << 0 }; | 81 enum FunctionProperties : unsigned { |
82 NonSimpleParameter = 1 << 0 | |
83 }; | |
62 | 84 |
63 explicit ExpressionClassifier(const Traits* t) | 85 explicit ExpressionClassifier(const Traits* t) |
64 : zone_(t->zone()), | 86 : zone_(t->zone()), |
65 non_patterns_to_rewrite_(t->GetNonPatternList()), | 87 non_patterns_to_rewrite_(t->GetNonPatternList()), |
88 reported_errors_(t->GetReportedErrorList()), | |
89 duplicate_finder_(nullptr), | |
66 invalid_productions_(0), | 90 invalid_productions_(0), |
67 function_properties_(0), | 91 function_properties_(0) { |
68 duplicate_finder_(nullptr) { | 92 reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); |
69 non_pattern_begin_ = non_patterns_to_rewrite_->length(); | 93 non_pattern_begin_ = non_patterns_to_rewrite_->length(); |
70 } | 94 } |
71 | 95 |
72 ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder) | 96 ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder) |
73 : zone_(t->zone()), | 97 : zone_(t->zone()), |
74 non_patterns_to_rewrite_(t->GetNonPatternList()), | 98 non_patterns_to_rewrite_(t->GetNonPatternList()), |
99 reported_errors_(t->GetReportedErrorList()), | |
100 duplicate_finder_(duplicate_finder), | |
75 invalid_productions_(0), | 101 invalid_productions_(0), |
76 function_properties_(0), | 102 function_properties_(0) { |
77 duplicate_finder_(duplicate_finder) { | 103 reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); |
78 non_pattern_begin_ = non_patterns_to_rewrite_->length(); | 104 non_pattern_begin_ = non_patterns_to_rewrite_->length(); |
79 } | 105 } |
80 | 106 |
81 ~ExpressionClassifier() { Discard(); } | 107 ~ExpressionClassifier() { Discard(); } |
82 | 108 |
83 bool is_valid(unsigned productions) const { | 109 V8_INLINE bool is_valid(unsigned productions) const { |
84 return (invalid_productions_ & productions) == 0; | 110 return (invalid_productions_ & productions) == 0; |
85 } | 111 } |
86 | 112 |
87 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; } | 113 V8_INLINE DuplicateFinder* duplicate_finder() const { |
114 return duplicate_finder_; | |
115 } | |
88 | 116 |
89 bool is_valid_expression() const { return is_valid(ExpressionProduction); } | 117 V8_INLINE bool is_valid_expression() const { |
118 return is_valid(ExpressionProduction); | |
119 } | |
90 | 120 |
91 bool is_valid_formal_parameter_initializer() const { | 121 V8_INLINE bool is_valid_formal_parameter_initializer() const { |
92 return is_valid(FormalParameterInitializerProduction); | 122 return is_valid(FormalParameterInitializerProduction); |
93 } | 123 } |
94 | 124 |
95 bool is_valid_binding_pattern() const { | 125 V8_INLINE bool is_valid_binding_pattern() const { |
96 return is_valid(BindingPatternProduction); | 126 return is_valid(BindingPatternProduction); |
97 } | 127 } |
98 | 128 |
99 bool is_valid_assignment_pattern() const { | 129 V8_INLINE bool is_valid_assignment_pattern() const { |
100 return is_valid(AssignmentPatternProduction); | 130 return is_valid(AssignmentPatternProduction); |
101 } | 131 } |
102 | 132 |
103 bool is_valid_arrow_formal_parameters() const { | 133 V8_INLINE bool is_valid_arrow_formal_parameters() const { |
104 return is_valid(ArrowFormalParametersProduction); | 134 return is_valid(ArrowFormalParametersProduction); |
105 } | 135 } |
106 | 136 |
107 bool is_valid_formal_parameter_list_without_duplicates() const { | 137 V8_INLINE bool is_valid_formal_parameter_list_without_duplicates() const { |
108 return is_valid(DistinctFormalParametersProduction); | 138 return is_valid(DistinctFormalParametersProduction); |
109 } | 139 } |
110 | 140 |
111 // Note: callers should also check | 141 // Note: callers should also check |
112 // is_valid_formal_parameter_list_without_duplicates(). | 142 // is_valid_formal_parameter_list_without_duplicates(). |
113 bool is_valid_strict_mode_formal_parameters() const { | 143 V8_INLINE bool is_valid_strict_mode_formal_parameters() const { |
114 return is_valid(StrictModeFormalParametersProduction); | 144 return is_valid(StrictModeFormalParametersProduction); |
115 } | 145 } |
116 | 146 |
117 bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); } | 147 V8_INLINE bool is_valid_let_pattern() const { |
148 return is_valid(LetPatternProduction); | |
149 } | |
118 | 150 |
119 bool is_valid_async_arrow_formal_parameters() const { | 151 bool is_valid_async_arrow_formal_parameters() const { |
120 return is_valid(AsyncArrowFormalParametersProduction); | 152 return is_valid(AsyncArrowFormalParametersProduction); |
121 } | 153 } |
122 | 154 |
123 bool is_valid_async_binding_pattern() const { | 155 bool is_valid_async_binding_pattern() const { |
124 return is_valid(AsyncBindingPatternProduction); | 156 return is_valid(AsyncBindingPatternProduction); |
125 } | 157 } |
126 | 158 |
127 const Error& expression_error() const { return expression_error_; } | 159 V8_INLINE const Error& expression_error() const { |
128 | 160 return reported_error(kExpressionProduction); |
129 const Error& formal_parameter_initializer_error() const { | |
130 return formal_parameter_initializer_error_; | |
131 } | 161 } |
132 | 162 |
133 const Error& binding_pattern_error() const { return binding_pattern_error_; } | 163 V8_INLINE const Error& formal_parameter_initializer_error() const { |
134 | 164 return reported_error(kFormalParameterInitializerProduction); |
135 const Error& assignment_pattern_error() const { | |
136 return assignment_pattern_error_; | |
137 } | 165 } |
138 | 166 |
139 const Error& arrow_formal_parameters_error() const { | 167 V8_INLINE const Error& binding_pattern_error() const { |
140 return arrow_formal_parameters_error_; | 168 return reported_error(kBindingPatternProduction); |
141 } | 169 } |
142 | 170 |
143 const Error& duplicate_formal_parameter_error() const { | 171 V8_INLINE const Error& assignment_pattern_error() const { |
144 return duplicate_formal_parameter_error_; | 172 return reported_error(kAssignmentPatternProduction); |
145 } | 173 } |
146 | 174 |
147 const Error& strict_mode_formal_parameter_error() const { | 175 V8_INLINE const Error& arrow_formal_parameters_error() const { |
148 return strict_mode_formal_parameter_error_; | 176 return reported_error(kArrowFormalParametersProduction); |
149 } | 177 } |
150 | 178 |
151 const Error& let_pattern_error() const { return let_pattern_error_; } | 179 V8_INLINE const Error& duplicate_formal_parameter_error() const { |
180 return reported_error(kDistinctFormalParametersProduction); | |
181 } | |
152 | 182 |
153 bool has_cover_initialized_name() const { | 183 V8_INLINE const Error& strict_mode_formal_parameter_error() const { |
184 return reported_error(kStrictModeFormalParametersProduction); | |
185 } | |
186 | |
187 V8_INLINE const Error& let_pattern_error() const { | |
188 return reported_error(kLetPatternProduction); | |
189 } | |
190 | |
191 V8_INLINE bool has_cover_initialized_name() const { | |
154 return !is_valid(CoverInitializedNameProduction); | 192 return !is_valid(CoverInitializedNameProduction); |
155 } | 193 } |
156 const Error& cover_initialized_name_error() const { | 194 |
157 return cover_initialized_name_error_; | 195 V8_INLINE const Error& cover_initialized_name_error() const { |
196 return reported_error(kCoverInitializedNameProduction); | |
158 } | 197 } |
159 | 198 |
160 bool has_tail_call_expression() const { | 199 V8_INLINE bool has_tail_call_expression() const { |
161 return !is_valid(TailCallExpressionProduction); | 200 return !is_valid(TailCallExpressionProduction); |
162 } | 201 } |
163 const Error& tail_call_expression_error() const { | 202 V8_INLINE const Error& tail_call_expression_error() const { |
164 return tail_call_expression_error_; | 203 return reported_error(kTailCallExpressionProduction); |
165 } | 204 } |
166 const Error& async_arrow_formal_parameters_error() const { | 205 V8_INLINE const Error& async_arrow_formal_parameters_error() const { |
167 return async_arrow_formal_parameters_error_; | 206 return reported_error(kAsyncArrowFormalParametersProduction); |
168 } | 207 } |
169 | 208 |
170 const Error& async_binding_pattern_error() const { | 209 V8_INLINE const Error& async_binding_pattern_error() const { |
171 return async_binding_pattern_error_; | 210 return reported_error(kAsyncBindingPatternProduction); |
172 } | 211 } |
173 | 212 |
174 bool is_simple_parameter_list() const { | 213 V8_INLINE bool is_simple_parameter_list() const { |
175 return !(function_properties_ & NonSimpleParameter); | 214 return !(function_properties_ & NonSimpleParameter); |
176 } | 215 } |
177 | 216 |
178 void RecordNonSimpleParameter() { | 217 V8_INLINE void RecordNonSimpleParameter() { |
179 function_properties_ |= NonSimpleParameter; | 218 function_properties_ |= NonSimpleParameter; |
180 } | 219 } |
181 | 220 |
182 void RecordExpressionError(const Scanner::Location& loc, | 221 void RecordExpressionError(const Scanner::Location& loc, |
183 MessageTemplate::Template message, | 222 MessageTemplate::Template message, |
184 const char* arg = nullptr) { | 223 const char* arg = nullptr) { |
185 if (!is_valid_expression()) return; | 224 if (!is_valid_expression()) return; |
186 invalid_productions_ |= ExpressionProduction; | 225 invalid_productions_ |= ExpressionProduction; |
187 expression_error_.location = loc; | 226 Add(Error(loc, message, kExpressionProduction, arg)); |
188 expression_error_.message = message; | |
189 expression_error_.arg = arg; | |
190 } | 227 } |
191 | 228 |
192 void RecordExpressionError(const Scanner::Location& loc, | 229 void RecordExpressionError(const Scanner::Location& loc, |
193 MessageTemplate::Template message, | 230 MessageTemplate::Template message, |
194 ParseErrorType type, const char* arg = nullptr) { | 231 ParseErrorType type, const char* arg = nullptr) { |
195 if (!is_valid_expression()) return; | 232 if (!is_valid_expression()) return; |
196 invalid_productions_ |= ExpressionProduction; | 233 invalid_productions_ |= ExpressionProduction; |
197 expression_error_.location = loc; | 234 Add(Error(loc, message, kExpressionProduction, arg, type)); |
198 expression_error_.message = message; | |
199 expression_error_.arg = arg; | |
200 expression_error_.type = type; | |
201 } | 235 } |
202 | 236 |
203 void RecordFormalParameterInitializerError(const Scanner::Location& loc, | 237 void RecordFormalParameterInitializerError(const Scanner::Location& loc, |
204 MessageTemplate::Template message, | 238 MessageTemplate::Template message, |
205 const char* arg = nullptr) { | 239 const char* arg = nullptr) { |
206 if (!is_valid_formal_parameter_initializer()) return; | 240 if (!is_valid_formal_parameter_initializer()) return; |
207 invalid_productions_ |= FormalParameterInitializerProduction; | 241 invalid_productions_ |= FormalParameterInitializerProduction; |
208 formal_parameter_initializer_error_.location = loc; | 242 Add(Error(loc, message, kFormalParameterInitializerProduction, arg)); |
209 formal_parameter_initializer_error_.message = message; | |
210 formal_parameter_initializer_error_.arg = arg; | |
211 } | 243 } |
212 | 244 |
213 void RecordBindingPatternError(const Scanner::Location& loc, | 245 void RecordBindingPatternError(const Scanner::Location& loc, |
214 MessageTemplate::Template message, | 246 MessageTemplate::Template message, |
215 const char* arg = nullptr) { | 247 const char* arg = nullptr) { |
216 if (!is_valid_binding_pattern()) return; | 248 if (!is_valid_binding_pattern()) return; |
217 invalid_productions_ |= BindingPatternProduction; | 249 invalid_productions_ |= BindingPatternProduction; |
218 binding_pattern_error_.location = loc; | 250 Add(Error(loc, message, kBindingPatternProduction, arg)); |
219 binding_pattern_error_.message = message; | |
220 binding_pattern_error_.arg = arg; | |
221 } | 251 } |
222 | 252 |
223 void RecordAssignmentPatternError(const Scanner::Location& loc, | 253 void RecordAssignmentPatternError(const Scanner::Location& loc, |
224 MessageTemplate::Template message, | 254 MessageTemplate::Template message, |
225 const char* arg = nullptr) { | 255 const char* arg = nullptr) { |
226 if (!is_valid_assignment_pattern()) return; | 256 if (!is_valid_assignment_pattern()) return; |
227 invalid_productions_ |= AssignmentPatternProduction; | 257 invalid_productions_ |= AssignmentPatternProduction; |
228 assignment_pattern_error_.location = loc; | 258 Add(Error(loc, message, kAssignmentPatternProduction, arg)); |
229 assignment_pattern_error_.message = message; | |
230 assignment_pattern_error_.arg = arg; | |
231 } | 259 } |
232 | 260 |
233 void RecordPatternError(const Scanner::Location& loc, | 261 void RecordPatternError(const Scanner::Location& loc, |
234 MessageTemplate::Template message, | 262 MessageTemplate::Template message, |
235 const char* arg = nullptr) { | 263 const char* arg = nullptr) { |
236 RecordBindingPatternError(loc, message, arg); | 264 RecordBindingPatternError(loc, message, arg); |
237 RecordAssignmentPatternError(loc, message, arg); | 265 RecordAssignmentPatternError(loc, message, arg); |
238 } | 266 } |
239 | 267 |
240 void RecordArrowFormalParametersError(const Scanner::Location& loc, | 268 void RecordArrowFormalParametersError(const Scanner::Location& loc, |
241 MessageTemplate::Template message, | 269 MessageTemplate::Template message, |
242 const char* arg = nullptr) { | 270 const char* arg = nullptr) { |
243 if (!is_valid_arrow_formal_parameters()) return; | 271 if (!is_valid_arrow_formal_parameters()) return; |
244 invalid_productions_ |= ArrowFormalParametersProduction; | 272 invalid_productions_ |= ArrowFormalParametersProduction; |
245 arrow_formal_parameters_error_.location = loc; | 273 Add(Error(loc, message, kArrowFormalParametersProduction, arg)); |
246 arrow_formal_parameters_error_.message = message; | |
247 arrow_formal_parameters_error_.arg = arg; | |
248 } | 274 } |
249 | 275 |
250 void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc, | 276 void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc, |
251 MessageTemplate::Template message, | 277 MessageTemplate::Template message, |
252 const char* arg = nullptr) { | 278 const char* arg = nullptr) { |
253 if (!is_valid_async_arrow_formal_parameters()) return; | 279 if (!is_valid_async_arrow_formal_parameters()) return; |
254 invalid_productions_ |= AsyncArrowFormalParametersProduction; | 280 invalid_productions_ |= AsyncArrowFormalParametersProduction; |
255 async_arrow_formal_parameters_error_.location = loc; | 281 Add(Error(loc, message, kAsyncArrowFormalParametersProduction, arg)); |
256 async_arrow_formal_parameters_error_.message = message; | |
257 async_arrow_formal_parameters_error_.arg = arg; | |
258 } | 282 } |
259 | 283 |
260 void RecordAsyncBindingPatternError(const Scanner::Location& loc, | 284 void RecordAsyncBindingPatternError(const Scanner::Location& loc, |
261 MessageTemplate::Template message, | 285 MessageTemplate::Template message, |
262 const char* arg = nullptr) { | 286 const char* arg = nullptr) { |
263 if (!is_valid_async_binding_pattern()) return; | 287 if (!is_valid_async_binding_pattern()) return; |
264 invalid_productions_ |= AsyncBindingPatternProduction; | 288 invalid_productions_ |= AsyncBindingPatternProduction; |
265 async_binding_pattern_error_.location = loc; | 289 Add(Error(loc, message, kAsyncBindingPatternProduction, arg)); |
266 async_binding_pattern_error_.message = message; | |
267 async_binding_pattern_error_.arg = arg; | |
268 } | 290 } |
269 | 291 |
270 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { | 292 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { |
271 if (!is_valid_formal_parameter_list_without_duplicates()) return; | 293 if (!is_valid_formal_parameter_list_without_duplicates()) return; |
272 invalid_productions_ |= DistinctFormalParametersProduction; | 294 invalid_productions_ |= DistinctFormalParametersProduction; |
273 duplicate_formal_parameter_error_.location = loc; | 295 Add(Error(loc, MessageTemplate::kParamDupe, |
274 duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe; | 296 kDistinctFormalParametersProduction)); |
275 duplicate_formal_parameter_error_.arg = nullptr; | |
276 } | 297 } |
277 | 298 |
278 // Record a binding that would be invalid in strict mode. Confusingly this | 299 // Record a binding that would be invalid in strict mode. Confusingly this |
279 // is not the same as StrictFormalParameterList, which simply forbids | 300 // is not the same as StrictFormalParameterList, which simply forbids |
280 // duplicate bindings. | 301 // duplicate bindings. |
281 void RecordStrictModeFormalParameterError(const Scanner::Location& loc, | 302 void RecordStrictModeFormalParameterError(const Scanner::Location& loc, |
282 MessageTemplate::Template message, | 303 MessageTemplate::Template message, |
283 const char* arg = nullptr) { | 304 const char* arg = nullptr) { |
284 if (!is_valid_strict_mode_formal_parameters()) return; | 305 if (!is_valid_strict_mode_formal_parameters()) return; |
285 invalid_productions_ |= StrictModeFormalParametersProduction; | 306 invalid_productions_ |= StrictModeFormalParametersProduction; |
286 strict_mode_formal_parameter_error_.location = loc; | 307 Add(Error(loc, message, kStrictModeFormalParametersProduction, arg)); |
287 strict_mode_formal_parameter_error_.message = message; | |
288 strict_mode_formal_parameter_error_.arg = arg; | |
289 } | 308 } |
290 | 309 |
291 void RecordLetPatternError(const Scanner::Location& loc, | 310 void RecordLetPatternError(const Scanner::Location& loc, |
292 MessageTemplate::Template message, | 311 MessageTemplate::Template message, |
293 const char* arg = nullptr) { | 312 const char* arg = nullptr) { |
294 if (!is_valid_let_pattern()) return; | 313 if (!is_valid_let_pattern()) return; |
295 invalid_productions_ |= LetPatternProduction; | 314 invalid_productions_ |= LetPatternProduction; |
296 let_pattern_error_.location = loc; | 315 Add(Error(loc, message, kLetPatternProduction, arg)); |
297 let_pattern_error_.message = message; | |
298 let_pattern_error_.arg = arg; | |
299 } | 316 } |
300 | 317 |
301 void RecordCoverInitializedNameError(const Scanner::Location& loc, | 318 void RecordCoverInitializedNameError(const Scanner::Location& loc, |
302 MessageTemplate::Template message, | 319 MessageTemplate::Template message, |
303 const char* arg = nullptr) { | 320 const char* arg = nullptr) { |
304 if (has_cover_initialized_name()) return; | 321 if (has_cover_initialized_name()) return; |
305 invalid_productions_ |= CoverInitializedNameProduction; | 322 invalid_productions_ |= CoverInitializedNameProduction; |
306 cover_initialized_name_error_.location = loc; | 323 Add(Error(loc, message, kCoverInitializedNameProduction, arg)); |
307 cover_initialized_name_error_.message = message; | |
308 cover_initialized_name_error_.arg = arg; | |
309 } | 324 } |
310 | 325 |
311 void RecordTailCallExpressionError(const Scanner::Location& loc, | 326 void RecordTailCallExpressionError(const Scanner::Location& loc, |
312 MessageTemplate::Template message, | 327 MessageTemplate::Template message, |
313 const char* arg = nullptr) { | 328 const char* arg = nullptr) { |
314 if (has_tail_call_expression()) return; | 329 if (has_tail_call_expression()) return; |
315 invalid_productions_ |= TailCallExpressionProduction; | 330 invalid_productions_ |= TailCallExpressionProduction; |
316 tail_call_expression_error_.location = loc; | 331 Add(Error(loc, message, kTailCallExpressionProduction, arg)); |
317 tail_call_expression_error_.message = message; | |
318 tail_call_expression_error_.arg = arg; | |
319 } | 332 } |
320 | 333 |
321 void ForgiveCoverInitializedNameError() { | 334 void ForgiveCoverInitializedNameError() { |
335 if (!(invalid_productions_ & CoverInitializedNameProduction)) return; | |
336 Error& e = reported_error(kCoverInitializedNameProduction); | |
337 e.kind = kUnusedError; | |
322 invalid_productions_ &= ~CoverInitializedNameProduction; | 338 invalid_productions_ &= ~CoverInitializedNameProduction; |
323 cover_initialized_name_error_ = Error(); | |
324 } | 339 } |
325 | 340 |
326 void ForgiveAssignmentPatternError() { | 341 void ForgiveAssignmentPatternError() { |
342 if (!(invalid_productions_ & AssignmentPatternProduction)) return; | |
343 Error& e = reported_error(kAssignmentPatternProduction); | |
344 e.kind = kUnusedError; | |
327 invalid_productions_ &= ~AssignmentPatternProduction; | 345 invalid_productions_ &= ~AssignmentPatternProduction; |
328 assignment_pattern_error_ = Error(); | |
329 } | 346 } |
330 | 347 |
331 void Accumulate(ExpressionClassifier* inner, | 348 void Accumulate(ExpressionClassifier* inner, |
332 unsigned productions = StandardProductions, | 349 unsigned productions = StandardProductions, |
333 bool merge_non_patterns = true) { | 350 bool merge_non_patterns = true) { |
351 DCHECK_EQ(inner->reported_errors_, reported_errors_); | |
352 DCHECK_EQ(inner->reported_errors_begin_, reported_errors_end_); | |
353 DCHECK_EQ(inner->reported_errors_end_, reported_errors_->length()); | |
334 if (merge_non_patterns) MergeNonPatterns(inner); | 354 if (merge_non_patterns) MergeNonPatterns(inner); |
335 // Propagate errors from inner, but don't overwrite already recorded | 355 // Propagate errors from inner, but don't overwrite already recorded |
336 // errors. | 356 // errors. |
337 unsigned non_arrow_inner_invalid_productions = | 357 unsigned non_arrow_inner_invalid_productions = |
338 inner->invalid_productions_ & ~ArrowFormalParametersProduction; | 358 inner->invalid_productions_ & ~ArrowFormalParametersProduction; |
339 if (non_arrow_inner_invalid_productions == 0) return; | 359 if (non_arrow_inner_invalid_productions) { |
340 unsigned non_arrow_productions = | 360 unsigned errors = non_arrow_inner_invalid_productions & productions & |
341 productions & ~ArrowFormalParametersProduction; | 361 ~invalid_productions_; |
342 unsigned errors = | 362 // The result will continue to be a valid arrow formal parameters if the |
343 non_arrow_productions & non_arrow_inner_invalid_productions; | 363 // inner expression is a valid binding pattern. |
344 errors &= ~invalid_productions_; | 364 bool copy_BP_to_AFP = false; |
345 if (errors != 0) { | 365 if (productions & ArrowFormalParametersProduction && |
346 invalid_productions_ |= errors; | 366 is_valid_arrow_formal_parameters()) { |
347 if (errors & ExpressionProduction) | 367 // Also copy function properties if expecting an arrow function |
348 expression_error_ = inner->expression_error_; | 368 // parameter. |
349 if (errors & FormalParameterInitializerProduction) | 369 function_properties_ |= inner->function_properties_; |
350 formal_parameter_initializer_error_ = | 370 if (!inner->is_valid_binding_pattern()) { |
351 inner->formal_parameter_initializer_error_; | 371 copy_BP_to_AFP = true; |
352 if (errors & BindingPatternProduction) | 372 invalid_productions_ |= ArrowFormalParametersProduction; |
353 binding_pattern_error_ = inner->binding_pattern_error_; | 373 } |
354 if (errors & AssignmentPatternProduction) | 374 } |
355 assignment_pattern_error_ = inner->assignment_pattern_error_; | 375 // Traverse the list of errors reported by the inner classifier |
356 if (errors & DistinctFormalParametersProduction) | 376 // to copy what's necessary. |
357 duplicate_formal_parameter_error_ = | 377 if (errors != 0 || copy_BP_to_AFP) { |
358 inner->duplicate_formal_parameter_error_; | 378 invalid_productions_ |= errors; |
359 if (errors & StrictModeFormalParametersProduction) | 379 int binding_pattern_index = inner->reported_errors_end_; |
360 strict_mode_formal_parameter_error_ = | 380 for (int i = inner->reported_errors_begin_; |
361 inner->strict_mode_formal_parameter_error_; | 381 i < inner->reported_errors_end_; i++) { |
362 if (errors & LetPatternProduction) | 382 int k = reported_errors_->at(i).kind; |
363 let_pattern_error_ = inner->let_pattern_error_; | 383 if (errors & (1 << k)) Copy(i); |
364 if (errors & CoverInitializedNameProduction) | 384 // Check if it's a BP error that has to be copied to an AFP error. |
365 cover_initialized_name_error_ = inner->cover_initialized_name_error_; | 385 if (k == kBindingPatternProduction && copy_BP_to_AFP) { |
366 if (errors & TailCallExpressionProduction) | 386 if (reported_errors_end_ <= i) { |
367 tail_call_expression_error_ = inner->tail_call_expression_error_; | 387 // If the BP error itself has not already been copied, |
368 if (errors & AsyncArrowFormalParametersProduction) | 388 // copy it now and change it to an AFP error. |
369 async_arrow_formal_parameters_error_ = | 389 Copy(i); |
370 inner->async_arrow_formal_parameters_error_; | 390 reported_errors_->at(reported_errors_end_-1).kind = |
371 if (errors & AsyncBindingPatternProduction) | 391 kArrowFormalParametersProduction; |
372 async_binding_pattern_error_ = inner->async_binding_pattern_error_; | 392 } else { |
373 } | 393 // Otherwise, if the BP error was already copied, keep its |
374 | 394 // position and wait until the end of the traversal. |
375 // As an exception to the above, the result continues to be a valid arrow | 395 DCHECK_EQ(reported_errors_end_, i+1); |
376 // formal parameters if the inner expression is a valid binding pattern. | 396 binding_pattern_index = i; |
377 if (productions & ArrowFormalParametersProduction && | 397 } |
378 is_valid_arrow_formal_parameters()) { | 398 } |
379 // Also copy function properties if expecting an arrow function | 399 } |
380 // parameter. | 400 // Do we still have to copy the BP error to an AFP error? |
381 function_properties_ |= inner->function_properties_; | 401 if (binding_pattern_index < inner->reported_errors_end_) { |
382 | 402 // If there's still unused space in the list of the inner |
383 if (!inner->is_valid_binding_pattern()) { | 403 // classifier, copy it there, otherwise add it to the end |
384 invalid_productions_ |= ArrowFormalParametersProduction; | 404 // of the list. |
385 arrow_formal_parameters_error_ = inner->binding_pattern_error_; | 405 if (reported_errors_end_ < inner->reported_errors_end_) |
406 Copy(binding_pattern_index); | |
407 else | |
408 Add(reported_errors_->at(binding_pattern_index)); | |
409 reported_errors_->at(reported_errors_end_-1).kind = | |
410 kArrowFormalParametersProduction; | |
411 } | |
386 } | 412 } |
387 } | 413 } |
414 reported_errors_->Rewind(reported_errors_end_); | |
415 inner->reported_errors_begin_ = inner->reported_errors_end_ = | |
416 reported_errors_end_; | |
388 } | 417 } |
389 | 418 |
390 V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; } | 419 V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; } |
391 | 420 |
392 V8_INLINE void Discard() { | 421 V8_INLINE void Discard() { |
422 if (reported_errors_end_ == reported_errors_->length()) { | |
423 reported_errors_->Rewind(reported_errors_begin_); | |
424 reported_errors_end_ = reported_errors_begin_; | |
425 } | |
426 DCHECK_EQ(reported_errors_begin_, reported_errors_end_); | |
393 DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length()); | 427 DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length()); |
394 non_patterns_to_rewrite_->Rewind(non_pattern_begin_); | 428 non_patterns_to_rewrite_->Rewind(non_pattern_begin_); |
395 } | 429 } |
396 | 430 |
397 V8_INLINE void MergeNonPatterns(ExpressionClassifier* inner) { | 431 V8_INLINE void MergeNonPatterns(ExpressionClassifier* inner) { |
398 DCHECK_LE(non_pattern_begin_, inner->non_pattern_begin_); | 432 DCHECK_LE(non_pattern_begin_, inner->non_pattern_begin_); |
399 inner->non_pattern_begin_ = inner->non_patterns_to_rewrite_->length(); | 433 inner->non_pattern_begin_ = inner->non_patterns_to_rewrite_->length(); |
400 } | 434 } |
401 | 435 |
402 private: | 436 private: |
437 V8_INLINE Error& reported_error(ErrorKind kind) const { | |
438 if (invalid_productions_ & (1 << kind)) { | |
439 for (int i = reported_errors_begin_; i < reported_errors_end_; i++) { | |
440 if (reported_errors_->at(i).kind == kind) | |
441 return reported_errors_->at(i); | |
442 } | |
443 UNREACHABLE(); | |
444 } | |
445 // We should only be looking for an error when we know that one has | |
446 // been reported. But we're not... So this is to make sure we have | |
447 // the same behaviour. | |
448 static Error none; | |
449 return none; | |
450 } | |
451 | |
452 // Adds e to the end of the list of reported errors for this classifier. | |
453 // It is expected that this classifier is the last one in the stack. | |
454 V8_INLINE void Add(const Error& e) { | |
455 DCHECK_EQ(reported_errors_end_, reported_errors_->length()); | |
456 reported_errors_->Add(e, zone_); | |
457 reported_errors_end_++; | |
458 } | |
459 | |
460 // Copies the error at position i of the list of reported errors, so that | |
461 // it becomes the last error reported for this classifier. Position i | |
462 // could be either after the existing errors of this classifier (i.e., | |
463 // in an inner classifier) or it could be an existing error (in case a | |
464 // copy is needed). | |
465 V8_INLINE void Copy(int i) { | |
466 DCHECK_LE(reported_errors_end_, i); | |
467 DCHECK_LT(i, reported_errors_->length()); | |
468 if (reported_errors_end_ != i) | |
469 reported_errors_->at(reported_errors_end_) = reported_errors_->at(i); | |
470 reported_errors_end_++; | |
471 } | |
472 | |
403 Zone* zone_; | 473 Zone* zone_; |
404 ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_; | 474 ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_; |
405 int non_pattern_begin_; | 475 ZoneList<Error>* reported_errors_; |
406 unsigned invalid_productions_; | |
407 unsigned function_properties_; | |
408 // TODO(ishell): consider using Zone[Hash]Map<TargetProduction, Error> | |
409 // here to consume less stack space during parsing. | |
410 Error expression_error_; | |
411 Error formal_parameter_initializer_error_; | |
412 Error binding_pattern_error_; | |
413 Error assignment_pattern_error_; | |
414 Error arrow_formal_parameters_error_; | |
415 Error duplicate_formal_parameter_error_; | |
416 Error strict_mode_formal_parameter_error_; | |
417 Error let_pattern_error_; | |
418 Error cover_initialized_name_error_; | |
419 Error tail_call_expression_error_; | |
420 Error async_arrow_formal_parameters_error_; | |
421 Error async_binding_pattern_error_; | |
422 DuplicateFinder* duplicate_finder_; | 476 DuplicateFinder* duplicate_finder_; |
477 uint16_t non_pattern_begin_; | |
478 unsigned invalid_productions_ : 14; | |
479 unsigned function_properties_ : 2; | |
480 uint16_t reported_errors_begin_; | |
adamk
2016/06/09 15:30:01
Can you add a comment here mentioning that these a
nickie
2016/06/10 13:19:39
Done.
| |
481 uint16_t reported_errors_end_; | |
423 }; | 482 }; |
424 | 483 |
425 | 484 |
485 #undef ERROR_CODES | |
486 | |
487 | |
426 } // namespace internal | 488 } // namespace internal |
427 } // namespace v8 | 489 } // namespace v8 |
428 | 490 |
429 #endif // V8_PARSING_EXPRESSION_CLASSIFIER_H | 491 #endif // V8_PARSING_EXPRESSION_CLASSIFIER_H |
OLD | NEW |