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_PARSING_EXPRESSION_CLASSIFIER_H 6 #define V8_PARSING_EXPRESSION_CLASSIFIER_H 7 8 #include "src/messages.h" 9 #include "src/parsing/scanner.h" 10 #include "src/parsing/token.h" 11 12 namespace v8 { 13 namespace internal { 14 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 31 template <typename Traits> 32 class ExpressionClassifier { 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 41 struct Error { ErrorError42 V8_INLINE Error() 43 : location(Scanner::Location::invalid()), 44 message(MessageTemplate::kNone), 45 kind(kUnusedError), 46 type(kSyntaxError), 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) locationError52 : location(loc), message(msg), kind(k), type(t), arg(a) {} 53 54 Scanner::Location location; 55 MessageTemplate::Template message : 26; 56 unsigned kind : 4; 57 ParseErrorType type : 2; 58 const char* arg; 59 }; 60 61 enum TargetProduction : unsigned { 62 #define DEFINE_PRODUCTION(NAME, CODE) NAME = 1 << CODE, 63 ERROR_CODES(DEFINE_PRODUCTION) 64 #undef DEFINE_PRODUCTION 65 66 ExpressionProductions = 67 (ExpressionProduction | FormalParameterInitializerProduction | 68 TailCallExpressionProduction), 69 PatternProductions = 70 (BindingPatternProduction | AssignmentPatternProduction | 71 LetPatternProduction | AsyncBindingPatternProduction), 72 FormalParametersProductions = (DistinctFormalParametersProduction | 73 StrictModeFormalParametersProduction), 74 StandardProductions = ExpressionProductions | PatternProductions, 75 AllProductions = 76 (StandardProductions | FormalParametersProductions | 77 ArrowFormalParametersProduction | CoverInitializedNameProduction | 78 AsyncArrowFormalParametersProduction | AsyncBindingPatternProduction) 79 }; 80 81 enum FunctionProperties : unsigned { 82 NonSimpleParameter = 1 << 0 83 }; 84 ExpressionClassifier(const Traits * t)85 explicit ExpressionClassifier(const Traits* t) 86 : zone_(t->zone()), 87 non_patterns_to_rewrite_(t->GetNonPatternList()), 88 reported_errors_(t->GetReportedErrorList()), 89 duplicate_finder_(nullptr), 90 invalid_productions_(0), 91 function_properties_(0) { 92 reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); 93 non_pattern_begin_ = non_patterns_to_rewrite_->length(); 94 } 95 ExpressionClassifier(const Traits * t,DuplicateFinder * duplicate_finder)96 ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder) 97 : zone_(t->zone()), 98 non_patterns_to_rewrite_(t->GetNonPatternList()), 99 reported_errors_(t->GetReportedErrorList()), 100 duplicate_finder_(duplicate_finder), 101 invalid_productions_(0), 102 function_properties_(0) { 103 reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); 104 non_pattern_begin_ = non_patterns_to_rewrite_->length(); 105 } 106 ~ExpressionClassifier()107 ~ExpressionClassifier() { Discard(); } 108 is_valid(unsigned productions)109 V8_INLINE bool is_valid(unsigned productions) const { 110 return (invalid_productions_ & productions) == 0; 111 } 112 duplicate_finder()113 V8_INLINE DuplicateFinder* duplicate_finder() const { 114 return duplicate_finder_; 115 } 116 is_valid_expression()117 V8_INLINE bool is_valid_expression() const { 118 return is_valid(ExpressionProduction); 119 } 120 is_valid_formal_parameter_initializer()121 V8_INLINE bool is_valid_formal_parameter_initializer() const { 122 return is_valid(FormalParameterInitializerProduction); 123 } 124 is_valid_binding_pattern()125 V8_INLINE bool is_valid_binding_pattern() const { 126 return is_valid(BindingPatternProduction); 127 } 128 is_valid_assignment_pattern()129 V8_INLINE bool is_valid_assignment_pattern() const { 130 return is_valid(AssignmentPatternProduction); 131 } 132 is_valid_arrow_formal_parameters()133 V8_INLINE bool is_valid_arrow_formal_parameters() const { 134 return is_valid(ArrowFormalParametersProduction); 135 } 136 is_valid_formal_parameter_list_without_duplicates()137 V8_INLINE bool is_valid_formal_parameter_list_without_duplicates() const { 138 return is_valid(DistinctFormalParametersProduction); 139 } 140 141 // Note: callers should also check 142 // is_valid_formal_parameter_list_without_duplicates(). is_valid_strict_mode_formal_parameters()143 V8_INLINE bool is_valid_strict_mode_formal_parameters() const { 144 return is_valid(StrictModeFormalParametersProduction); 145 } 146 is_valid_let_pattern()147 V8_INLINE bool is_valid_let_pattern() const { 148 return is_valid(LetPatternProduction); 149 } 150 is_valid_async_arrow_formal_parameters()151 bool is_valid_async_arrow_formal_parameters() const { 152 return is_valid(AsyncArrowFormalParametersProduction); 153 } 154 is_valid_async_binding_pattern()155 bool is_valid_async_binding_pattern() const { 156 return is_valid(AsyncBindingPatternProduction); 157 } 158 expression_error()159 V8_INLINE const Error& expression_error() const { 160 return reported_error(kExpressionProduction); 161 } 162 formal_parameter_initializer_error()163 V8_INLINE const Error& formal_parameter_initializer_error() const { 164 return reported_error(kFormalParameterInitializerProduction); 165 } 166 binding_pattern_error()167 V8_INLINE const Error& binding_pattern_error() const { 168 return reported_error(kBindingPatternProduction); 169 } 170 assignment_pattern_error()171 V8_INLINE const Error& assignment_pattern_error() const { 172 return reported_error(kAssignmentPatternProduction); 173 } 174 arrow_formal_parameters_error()175 V8_INLINE const Error& arrow_formal_parameters_error() const { 176 return reported_error(kArrowFormalParametersProduction); 177 } 178 duplicate_formal_parameter_error()179 V8_INLINE const Error& duplicate_formal_parameter_error() const { 180 return reported_error(kDistinctFormalParametersProduction); 181 } 182 strict_mode_formal_parameter_error()183 V8_INLINE const Error& strict_mode_formal_parameter_error() const { 184 return reported_error(kStrictModeFormalParametersProduction); 185 } 186 let_pattern_error()187 V8_INLINE const Error& let_pattern_error() const { 188 return reported_error(kLetPatternProduction); 189 } 190 has_cover_initialized_name()191 V8_INLINE bool has_cover_initialized_name() const { 192 return !is_valid(CoverInitializedNameProduction); 193 } 194 cover_initialized_name_error()195 V8_INLINE const Error& cover_initialized_name_error() const { 196 return reported_error(kCoverInitializedNameProduction); 197 } 198 has_tail_call_expression()199 V8_INLINE bool has_tail_call_expression() const { 200 return !is_valid(TailCallExpressionProduction); 201 } tail_call_expression_error()202 V8_INLINE const Error& tail_call_expression_error() const { 203 return reported_error(kTailCallExpressionProduction); 204 } async_arrow_formal_parameters_error()205 V8_INLINE const Error& async_arrow_formal_parameters_error() const { 206 return reported_error(kAsyncArrowFormalParametersProduction); 207 } 208 async_binding_pattern_error()209 V8_INLINE const Error& async_binding_pattern_error() const { 210 return reported_error(kAsyncBindingPatternProduction); 211 } 212 is_simple_parameter_list()213 V8_INLINE bool is_simple_parameter_list() const { 214 return !(function_properties_ & NonSimpleParameter); 215 } 216 RecordNonSimpleParameter()217 V8_INLINE void RecordNonSimpleParameter() { 218 function_properties_ |= NonSimpleParameter; 219 } 220 221 void RecordExpressionError(const Scanner::Location& loc, 222 MessageTemplate::Template message, 223 const char* arg = nullptr) { 224 if (!is_valid_expression()) return; 225 invalid_productions_ |= ExpressionProduction; 226 Add(Error(loc, message, kExpressionProduction, arg)); 227 } 228 229 void RecordExpressionError(const Scanner::Location& loc, 230 MessageTemplate::Template message, 231 ParseErrorType type, const char* arg = nullptr) { 232 if (!is_valid_expression()) return; 233 invalid_productions_ |= ExpressionProduction; 234 Add(Error(loc, message, kExpressionProduction, arg, type)); 235 } 236 237 void RecordFormalParameterInitializerError(const Scanner::Location& loc, 238 MessageTemplate::Template message, 239 const char* arg = nullptr) { 240 if (!is_valid_formal_parameter_initializer()) return; 241 invalid_productions_ |= FormalParameterInitializerProduction; 242 Add(Error(loc, message, kFormalParameterInitializerProduction, arg)); 243 } 244 245 void RecordBindingPatternError(const Scanner::Location& loc, 246 MessageTemplate::Template message, 247 const char* arg = nullptr) { 248 if (!is_valid_binding_pattern()) return; 249 invalid_productions_ |= BindingPatternProduction; 250 Add(Error(loc, message, kBindingPatternProduction, arg)); 251 } 252 253 void RecordAssignmentPatternError(const Scanner::Location& loc, 254 MessageTemplate::Template message, 255 const char* arg = nullptr) { 256 if (!is_valid_assignment_pattern()) return; 257 invalid_productions_ |= AssignmentPatternProduction; 258 Add(Error(loc, message, kAssignmentPatternProduction, arg)); 259 } 260 261 void RecordPatternError(const Scanner::Location& loc, 262 MessageTemplate::Template message, 263 const char* arg = nullptr) { 264 RecordBindingPatternError(loc, message, arg); 265 RecordAssignmentPatternError(loc, message, arg); 266 } 267 268 void RecordArrowFormalParametersError(const Scanner::Location& loc, 269 MessageTemplate::Template message, 270 const char* arg = nullptr) { 271 if (!is_valid_arrow_formal_parameters()) return; 272 invalid_productions_ |= ArrowFormalParametersProduction; 273 Add(Error(loc, message, kArrowFormalParametersProduction, arg)); 274 } 275 276 void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc, 277 MessageTemplate::Template message, 278 const char* arg = nullptr) { 279 if (!is_valid_async_arrow_formal_parameters()) return; 280 invalid_productions_ |= AsyncArrowFormalParametersProduction; 281 Add(Error(loc, message, kAsyncArrowFormalParametersProduction, arg)); 282 } 283 284 void RecordAsyncBindingPatternError(const Scanner::Location& loc, 285 MessageTemplate::Template message, 286 const char* arg = nullptr) { 287 if (!is_valid_async_binding_pattern()) return; 288 invalid_productions_ |= AsyncBindingPatternProduction; 289 Add(Error(loc, message, kAsyncBindingPatternProduction, arg)); 290 } 291 RecordDuplicateFormalParameterError(const Scanner::Location & loc)292 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { 293 if (!is_valid_formal_parameter_list_without_duplicates()) return; 294 invalid_productions_ |= DistinctFormalParametersProduction; 295 Add(Error(loc, MessageTemplate::kParamDupe, 296 kDistinctFormalParametersProduction)); 297 } 298 299 // Record a binding that would be invalid in strict mode. Confusingly this 300 // is not the same as StrictFormalParameterList, which simply forbids 301 // duplicate bindings. 302 void RecordStrictModeFormalParameterError(const Scanner::Location& loc, 303 MessageTemplate::Template message, 304 const char* arg = nullptr) { 305 if (!is_valid_strict_mode_formal_parameters()) return; 306 invalid_productions_ |= StrictModeFormalParametersProduction; 307 Add(Error(loc, message, kStrictModeFormalParametersProduction, arg)); 308 } 309 310 void RecordLetPatternError(const Scanner::Location& loc, 311 MessageTemplate::Template message, 312 const char* arg = nullptr) { 313 if (!is_valid_let_pattern()) return; 314 invalid_productions_ |= LetPatternProduction; 315 Add(Error(loc, message, kLetPatternProduction, arg)); 316 } 317 318 void RecordCoverInitializedNameError(const Scanner::Location& loc, 319 MessageTemplate::Template message, 320 const char* arg = nullptr) { 321 if (has_cover_initialized_name()) return; 322 invalid_productions_ |= CoverInitializedNameProduction; 323 Add(Error(loc, message, kCoverInitializedNameProduction, arg)); 324 } 325 326 void RecordTailCallExpressionError(const Scanner::Location& loc, 327 MessageTemplate::Template message, 328 const char* arg = nullptr) { 329 if (has_tail_call_expression()) return; 330 invalid_productions_ |= TailCallExpressionProduction; 331 Add(Error(loc, message, kTailCallExpressionProduction, arg)); 332 } 333 ForgiveCoverInitializedNameError()334 void ForgiveCoverInitializedNameError() { 335 if (!(invalid_productions_ & CoverInitializedNameProduction)) return; 336 Error& e = reported_error(kCoverInitializedNameProduction); 337 e.kind = kUnusedError; 338 invalid_productions_ &= ~CoverInitializedNameProduction; 339 } 340 ForgiveAssignmentPatternError()341 void ForgiveAssignmentPatternError() { 342 if (!(invalid_productions_ & AssignmentPatternProduction)) return; 343 Error& e = reported_error(kAssignmentPatternProduction); 344 e.kind = kUnusedError; 345 invalid_productions_ &= ~AssignmentPatternProduction; 346 } 347 348 void Accumulate(ExpressionClassifier* inner, 349 unsigned productions = StandardProductions, 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()); 354 if (merge_non_patterns) MergeNonPatterns(inner); 355 // Propagate errors from inner, but don't overwrite already recorded 356 // errors. 357 unsigned non_arrow_inner_invalid_productions = 358 inner->invalid_productions_ & ~ArrowFormalParametersProduction; 359 if (non_arrow_inner_invalid_productions) { 360 unsigned errors = non_arrow_inner_invalid_productions & productions & 361 ~invalid_productions_; 362 // The result will continue to be a valid arrow formal parameters if the 363 // inner expression is a valid binding pattern. 364 bool copy_BP_to_AFP = false; 365 if (productions & ArrowFormalParametersProduction && 366 is_valid_arrow_formal_parameters()) { 367 // Also copy function properties if expecting an arrow function 368 // parameter. 369 function_properties_ |= inner->function_properties_; 370 if (!inner->is_valid_binding_pattern()) { 371 copy_BP_to_AFP = true; 372 invalid_productions_ |= ArrowFormalParametersProduction; 373 } 374 } 375 // Traverse the list of errors reported by the inner classifier 376 // to copy what's necessary. 377 if (errors != 0 || copy_BP_to_AFP) { 378 invalid_productions_ |= errors; 379 int binding_pattern_index = inner->reported_errors_end_; 380 for (int i = inner->reported_errors_begin_; 381 i < inner->reported_errors_end_; i++) { 382 int k = reported_errors_->at(i).kind; 383 if (errors & (1 << k)) Copy(i); 384 // Check if it's a BP error that has to be copied to an AFP error. 385 if (k == kBindingPatternProduction && copy_BP_to_AFP) { 386 if (reported_errors_end_ <= i) { 387 // If the BP error itself has not already been copied, 388 // copy it now and change it to an AFP error. 389 Copy(i); 390 reported_errors_->at(reported_errors_end_-1).kind = 391 kArrowFormalParametersProduction; 392 } else { 393 // Otherwise, if the BP error was already copied, keep its 394 // position and wait until the end of the traversal. 395 DCHECK_EQ(reported_errors_end_, i+1); 396 binding_pattern_index = i; 397 } 398 } 399 } 400 // Do we still have to copy the BP error to an AFP error? 401 if (binding_pattern_index < inner->reported_errors_end_) { 402 // If there's still unused space in the list of the inner 403 // classifier, copy it there, otherwise add it to the end 404 // of the list. 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 } 412 } 413 } 414 reported_errors_->Rewind(reported_errors_end_); 415 inner->reported_errors_begin_ = inner->reported_errors_end_ = 416 reported_errors_end_; 417 } 418 GetNonPatternBegin()419 V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; } 420 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_); 427 DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length()); 428 non_patterns_to_rewrite_->Rewind(non_pattern_begin_); 429 } 430 MergeNonPatterns(ExpressionClassifier * inner)431 V8_INLINE void MergeNonPatterns(ExpressionClassifier* inner) { 432 DCHECK_LE(non_pattern_begin_, inner->non_pattern_begin_); 433 inner->non_pattern_begin_ = inner->non_patterns_to_rewrite_->length(); 434 } 435 436 private: reported_error(ErrorKind kind)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. Add(const Error & e)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). Copy(int i)465 V8_INLINE void Copy(int i) { 466 DCHECK_LT(i, reported_errors_->length()); 467 if (reported_errors_end_ != i) 468 reported_errors_->at(reported_errors_end_) = reported_errors_->at(i); 469 reported_errors_end_++; 470 } 471 472 Zone* zone_; 473 ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_; 474 ZoneList<Error>* reported_errors_; 475 DuplicateFinder* duplicate_finder_; 476 // The uint16_t for non_pattern_begin_ will not be enough in the case, 477 // e.g., of an array literal containing more than 64K inner array 478 // literals with spreads, as in: 479 // var N=65536; eval("var x=[];" + "[" + "[...x],".repeat(N) + "].length"); 480 // An implementation limit error in ParserBase::AddNonPatternForRewriting 481 // will be triggered in this case. 482 uint16_t non_pattern_begin_; 483 unsigned invalid_productions_ : 14; 484 unsigned function_properties_ : 2; 485 // The uint16_t for reported_errors_begin_ and reported_errors_end_ will 486 // not be enough in the case of a long series of expressions using nested 487 // classifiers, e.g., a long sequence of assignments, as in: 488 // literals with spreads, as in: 489 // var N=65536; eval("var x;" + "x=".repeat(N) + "42"); 490 // This should not be a problem, as such things currently fail with a 491 // stack overflow while parsing. 492 uint16_t reported_errors_begin_; 493 uint16_t reported_errors_end_; 494 }; 495 496 497 #undef ERROR_CODES 498 499 500 } // namespace internal 501 } // namespace v8 502 503 #endif // V8_PARSING_EXPRESSION_CLASSIFIER_H 504