Chromium Code Reviews| 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 |