Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 31 | template <typename Traits> |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 32 | class ExpressionClassifier { |
| 33 | public: |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 41 | struct Error { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 42 | V8_INLINE Error() |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 43 | : location(Scanner::Location::invalid()), |
| 44 | message(MessageTemplate::kNone), |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 45 | kind(kUnusedError), |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 46 | type(kSyntaxError), |
| 47 | arg(nullptr) {} |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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) {} |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 53 | |
| 54 | Scanner::Location location; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 55 | MessageTemplate::Template message : 26; |
| 56 | unsigned kind : 4; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 57 | ParseErrorType type : 2; |
| 58 | const char* arg; |
| 59 | }; |
| 60 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 61 | enum TargetProduction : unsigned { |
| 62 | #define DEFINE_PRODUCTION(NAME, CODE) NAME = 1 << CODE, |
| 63 | ERROR_CODES(DEFINE_PRODUCTION) |
| 64 | #undef DEFINE_PRODUCTION |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 65 | |
| 66 | ExpressionProductions = |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 67 | (ExpressionProduction | FormalParameterInitializerProduction | |
| 68 | TailCallExpressionProduction), |
| 69 | PatternProductions = |
| 70 | (BindingPatternProduction | AssignmentPatternProduction | |
| 71 | LetPatternProduction | AsyncBindingPatternProduction), |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 72 | FormalParametersProductions = (DistinctFormalParametersProduction | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 73 | StrictModeFormalParametersProduction), |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 74 | StandardProductions = ExpressionProductions | PatternProductions, |
| 75 | AllProductions = |
| 76 | (StandardProductions | FormalParametersProductions | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 77 | ArrowFormalParametersProduction | CoverInitializedNameProduction | |
| 78 | AsyncArrowFormalParametersProduction | AsyncBindingPatternProduction) |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 79 | }; |
| 80 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 81 | enum FunctionProperties : unsigned { |
| 82 | NonSimpleParameter = 1 << 0 |
| 83 | }; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 84 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 85 | explicit ExpressionClassifier(const Traits* t) |
| 86 | : zone_(t->zone()), |
| 87 | non_patterns_to_rewrite_(t->GetNonPatternList()), |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 88 | reported_errors_(t->GetReportedErrorList()), |
| 89 | duplicate_finder_(nullptr), |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 90 | invalid_productions_(0), |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 91 | function_properties_(0) { |
| 92 | reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 93 | non_pattern_begin_ = non_patterns_to_rewrite_->length(); |
| 94 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 95 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 96 | ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder) |
| 97 | : zone_(t->zone()), |
| 98 | non_patterns_to_rewrite_(t->GetNonPatternList()), |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 99 | reported_errors_(t->GetReportedErrorList()), |
| 100 | duplicate_finder_(duplicate_finder), |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 101 | invalid_productions_(0), |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 102 | function_properties_(0) { |
| 103 | reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 104 | non_pattern_begin_ = non_patterns_to_rewrite_->length(); |
| 105 | } |
| 106 | |
| 107 | ~ExpressionClassifier() { Discard(); } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 108 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 109 | V8_INLINE bool is_valid(unsigned productions) const { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 110 | return (invalid_productions_ & productions) == 0; |
| 111 | } |
| 112 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 113 | V8_INLINE DuplicateFinder* duplicate_finder() const { |
| 114 | return duplicate_finder_; |
| 115 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 116 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 117 | V8_INLINE bool is_valid_expression() const { |
| 118 | return is_valid(ExpressionProduction); |
| 119 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 120 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 121 | V8_INLINE bool is_valid_formal_parameter_initializer() const { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 122 | return is_valid(FormalParameterInitializerProduction); |
| 123 | } |
| 124 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 125 | V8_INLINE bool is_valid_binding_pattern() const { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 126 | return is_valid(BindingPatternProduction); |
| 127 | } |
| 128 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 129 | V8_INLINE bool is_valid_assignment_pattern() const { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 130 | return is_valid(AssignmentPatternProduction); |
| 131 | } |
| 132 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 133 | V8_INLINE bool is_valid_arrow_formal_parameters() const { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 134 | return is_valid(ArrowFormalParametersProduction); |
| 135 | } |
| 136 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 137 | V8_INLINE bool is_valid_formal_parameter_list_without_duplicates() const { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 138 | return is_valid(DistinctFormalParametersProduction); |
| 139 | } |
| 140 | |
| 141 | // Note: callers should also check |
| 142 | // is_valid_formal_parameter_list_without_duplicates(). |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 143 | V8_INLINE bool is_valid_strict_mode_formal_parameters() const { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 144 | return is_valid(StrictModeFormalParametersProduction); |
| 145 | } |
| 146 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 147 | V8_INLINE bool is_valid_let_pattern() const { |
| 148 | return is_valid(LetPatternProduction); |
| 149 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 150 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 151 | bool is_valid_async_arrow_formal_parameters() const { |
| 152 | return is_valid(AsyncArrowFormalParametersProduction); |
| 153 | } |
| 154 | |
| 155 | bool is_valid_async_binding_pattern() const { |
| 156 | return is_valid(AsyncBindingPatternProduction); |
| 157 | } |
| 158 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 159 | V8_INLINE const Error& expression_error() const { |
| 160 | return reported_error(kExpressionProduction); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 161 | } |
| 162 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 163 | V8_INLINE const Error& formal_parameter_initializer_error() const { |
| 164 | return reported_error(kFormalParameterInitializerProduction); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 165 | } |
| 166 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 167 | V8_INLINE const Error& binding_pattern_error() const { |
| 168 | return reported_error(kBindingPatternProduction); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 169 | } |
| 170 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 171 | V8_INLINE const Error& assignment_pattern_error() const { |
| 172 | return reported_error(kAssignmentPatternProduction); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 173 | } |
| 174 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 175 | V8_INLINE const Error& arrow_formal_parameters_error() const { |
| 176 | return reported_error(kArrowFormalParametersProduction); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 177 | } |
| 178 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 179 | V8_INLINE const Error& duplicate_formal_parameter_error() const { |
| 180 | return reported_error(kDistinctFormalParametersProduction); |
| 181 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 182 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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 { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 192 | return !is_valid(CoverInitializedNameProduction); |
| 193 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 194 | |
| 195 | V8_INLINE const Error& cover_initialized_name_error() const { |
| 196 | return reported_error(kCoverInitializedNameProduction); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 197 | } |
| 198 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 199 | V8_INLINE bool has_tail_call_expression() const { |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 200 | return !is_valid(TailCallExpressionProduction); |
| 201 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 202 | V8_INLINE const Error& tail_call_expression_error() const { |
| 203 | return reported_error(kTailCallExpressionProduction); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 204 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 205 | V8_INLINE const Error& async_arrow_formal_parameters_error() const { |
| 206 | return reported_error(kAsyncArrowFormalParametersProduction); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 207 | } |
| 208 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 209 | V8_INLINE const Error& async_binding_pattern_error() const { |
| 210 | return reported_error(kAsyncBindingPatternProduction); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 211 | } |
| 212 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 213 | V8_INLINE bool is_simple_parameter_list() const { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 214 | return !(function_properties_ & NonSimpleParameter); |
| 215 | } |
| 216 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 217 | V8_INLINE void RecordNonSimpleParameter() { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 226 | Add(Error(loc, message, kExpressionProduction, arg)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 234 | Add(Error(loc, message, kExpressionProduction, arg, type)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 242 | Add(Error(loc, message, kFormalParameterInitializerProduction, arg)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 250 | Add(Error(loc, message, kBindingPatternProduction, arg)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 258 | Add(Error(loc, message, kAssignmentPatternProduction, arg)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 273 | Add(Error(loc, message, kArrowFormalParametersProduction, arg)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 274 | } |
| 275 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 281 | Add(Error(loc, message, kAsyncArrowFormalParametersProduction, arg)); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 289 | Add(Error(loc, message, kAsyncBindingPatternProduction, arg)); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 290 | } |
| 291 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 292 | void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { |
| 293 | if (!is_valid_formal_parameter_list_without_duplicates()) return; |
| 294 | invalid_productions_ |= DistinctFormalParametersProduction; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 295 | Add(Error(loc, MessageTemplate::kParamDupe, |
| 296 | kDistinctFormalParametersProduction)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 307 | Add(Error(loc, message, kStrictModeFormalParametersProduction, arg)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 308 | } |
| 309 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 315 | Add(Error(loc, message, kLetPatternProduction, arg)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 323 | Add(Error(loc, message, kCoverInitializedNameProduction, arg)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 324 | } |
| 325 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 331 | Add(Error(loc, message, kTailCallExpressionProduction, arg)); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 332 | } |
| 333 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 334 | void ForgiveCoverInitializedNameError() { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 335 | if (!(invalid_productions_ & CoverInitializedNameProduction)) return; |
| 336 | Error& e = reported_error(kCoverInitializedNameProduction); |
| 337 | e.kind = kUnusedError; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 338 | invalid_productions_ &= ~CoverInitializedNameProduction; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 339 | } |
| 340 | |
| 341 | void ForgiveAssignmentPatternError() { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 342 | if (!(invalid_productions_ & AssignmentPatternProduction)) return; |
| 343 | Error& e = reported_error(kAssignmentPatternProduction); |
| 344 | e.kind = kUnusedError; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 345 | invalid_productions_ &= ~AssignmentPatternProduction; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 346 | } |
| 347 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 348 | void Accumulate(ExpressionClassifier* inner, |
| 349 | unsigned productions = StandardProductions, |
| 350 | bool merge_non_patterns = true) { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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()); |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 354 | if (merge_non_patterns) MergeNonPatterns(inner); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 355 | // Propagate errors from inner, but don't overwrite already recorded |
| 356 | // errors. |
| 357 | unsigned non_arrow_inner_invalid_productions = |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 358 | inner->invalid_productions_ & ~ArrowFormalParametersProduction; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 412 | } |
| 413 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 414 | reported_errors_->Rewind(reported_errors_end_); |
| 415 | inner->reported_errors_begin_ = inner->reported_errors_end_ = |
| 416 | reported_errors_end_; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 417 | } |
| 418 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 419 | V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; } |
| 420 | |
| 421 | V8_INLINE void Discard() { |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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_); |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 427 | DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length()); |
| 428 | non_patterns_to_rewrite_->Rewind(non_pattern_begin_); |
| 429 | } |
| 430 | |
| 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 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 436 | private: |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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_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 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 472 | Zone* zone_; |
| 473 | ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 474 | ZoneList<Error>* reported_errors_; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 475 | DuplicateFinder* duplicate_finder_; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 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_; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 494 | }; |
| 495 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 496 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame^] | 497 | #undef ERROR_CODES |
| 498 | |
| 499 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 500 | } // namespace internal |
| 501 | } // namespace v8 |
| 502 | |
| 503 | #endif // V8_PARSING_EXPRESSION_CLASSIFIER_H |