1 // Copyright 2017 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_AST_AST_SOURCE_RANGES_H_ 6 #define V8_AST_AST_SOURCE_RANGES_H_ 7 8 #include "src/ast/ast.h" 9 #include "src/zone/zone-containers.h" 10 11 namespace v8 { 12 namespace internal { 13 14 // Specifies a range within the source code. {start} is 0-based and inclusive, 15 // {end} is 0-based and exclusive. 16 struct SourceRange { SourceRangeSourceRange17 SourceRange() : SourceRange(kNoSourcePosition, kNoSourcePosition) {} SourceRangeSourceRange18 SourceRange(int start, int end) : start(start), end(end) {} IsEmptySourceRange19 bool IsEmpty() const { return start == kNoSourcePosition; } EmptySourceRange20 static SourceRange Empty() { return SourceRange(); } OpenEndedSourceRange21 static SourceRange OpenEnded(int32_t start) { 22 return SourceRange(start, kNoSourcePosition); 23 } 24 static SourceRange ContinuationOf(const SourceRange& that, 25 int end = kNoSourcePosition) { 26 return that.IsEmpty() ? Empty() : SourceRange(that.end, end); 27 } 28 29 static constexpr int kFunctionLiteralSourcePosition = -2; 30 STATIC_ASSERT(kFunctionLiteralSourcePosition == kNoSourcePosition - 1); 31 32 // Source ranges associated with a function literal do not contain real 33 // source positions; instead, they are created with special marker values. 34 // These are later recognized and rewritten during processing in 35 // Coverage::Collect(). FunctionLiteralMarkerRangeSourceRange36 static SourceRange FunctionLiteralMarkerRange() { 37 return {kFunctionLiteralSourcePosition, kFunctionLiteralSourcePosition}; 38 } 39 40 int32_t start, end; 41 }; 42 43 // The list of ast node kinds that have associated source ranges. Note that this 44 // macro is not undefined at the end of this file. 45 #define AST_SOURCE_RANGE_LIST(V) \ 46 V(BinaryOperation) \ 47 V(Block) \ 48 V(CaseClause) \ 49 V(Conditional) \ 50 V(Expression) \ 51 V(FunctionLiteral) \ 52 V(IfStatement) \ 53 V(IterationStatement) \ 54 V(JumpStatement) \ 55 V(NaryOperation) \ 56 V(Suspend) \ 57 V(SwitchStatement) \ 58 V(Throw) \ 59 V(TryCatchStatement) \ 60 V(TryFinallyStatement) 61 62 enum class SourceRangeKind { 63 kBody, 64 kCatch, 65 kContinuation, 66 kElse, 67 kFinally, 68 kRight, 69 kThen, 70 }; 71 72 class AstNodeSourceRanges : public ZoneObject { 73 public: 74 virtual ~AstNodeSourceRanges() = default; 75 virtual SourceRange GetRange(SourceRangeKind kind) = 0; 76 virtual bool HasRange(SourceRangeKind kind) = 0; RemoveContinuationRange()77 virtual void RemoveContinuationRange() { UNREACHABLE(); } 78 }; 79 80 class BinaryOperationSourceRanges final : public AstNodeSourceRanges { 81 public: BinaryOperationSourceRanges(const SourceRange & right_range)82 explicit BinaryOperationSourceRanges(const SourceRange& right_range) 83 : right_range_(right_range) {} 84 GetRange(SourceRangeKind kind)85 SourceRange GetRange(SourceRangeKind kind) override { 86 DCHECK(HasRange(kind)); 87 return right_range_; 88 } 89 HasRange(SourceRangeKind kind)90 bool HasRange(SourceRangeKind kind) override { 91 return kind == SourceRangeKind::kRight; 92 } 93 94 private: 95 SourceRange right_range_; 96 }; 97 98 class ContinuationSourceRanges : public AstNodeSourceRanges { 99 public: ContinuationSourceRanges(int32_t continuation_position)100 explicit ContinuationSourceRanges(int32_t continuation_position) 101 : continuation_position_(continuation_position) {} 102 GetRange(SourceRangeKind kind)103 SourceRange GetRange(SourceRangeKind kind) override { 104 DCHECK(HasRange(kind)); 105 return SourceRange::OpenEnded(continuation_position_); 106 } 107 HasRange(SourceRangeKind kind)108 bool HasRange(SourceRangeKind kind) override { 109 return kind == SourceRangeKind::kContinuation; 110 } 111 RemoveContinuationRange()112 void RemoveContinuationRange() override { 113 DCHECK(HasRange(SourceRangeKind::kContinuation)); 114 continuation_position_ = kNoSourcePosition; 115 } 116 117 private: 118 int32_t continuation_position_; 119 }; 120 121 class BlockSourceRanges final : public ContinuationSourceRanges { 122 public: BlockSourceRanges(int32_t continuation_position)123 explicit BlockSourceRanges(int32_t continuation_position) 124 : ContinuationSourceRanges(continuation_position) {} 125 }; 126 127 class CaseClauseSourceRanges final : public AstNodeSourceRanges { 128 public: CaseClauseSourceRanges(const SourceRange & body_range)129 explicit CaseClauseSourceRanges(const SourceRange& body_range) 130 : body_range_(body_range) {} 131 GetRange(SourceRangeKind kind)132 SourceRange GetRange(SourceRangeKind kind) override { 133 DCHECK(HasRange(kind)); 134 return body_range_; 135 } 136 HasRange(SourceRangeKind kind)137 bool HasRange(SourceRangeKind kind) override { 138 return kind == SourceRangeKind::kBody; 139 } 140 141 private: 142 SourceRange body_range_; 143 }; 144 145 class ConditionalSourceRanges final : public AstNodeSourceRanges { 146 public: ConditionalSourceRanges(const SourceRange & then_range,const SourceRange & else_range)147 explicit ConditionalSourceRanges(const SourceRange& then_range, 148 const SourceRange& else_range) 149 : then_range_(then_range), else_range_(else_range) {} 150 GetRange(SourceRangeKind kind)151 SourceRange GetRange(SourceRangeKind kind) override { 152 DCHECK(HasRange(kind)); 153 switch (kind) { 154 case SourceRangeKind::kThen: 155 return then_range_; 156 case SourceRangeKind::kElse: 157 return else_range_; 158 default: 159 UNREACHABLE(); 160 } 161 } 162 HasRange(SourceRangeKind kind)163 bool HasRange(SourceRangeKind kind) override { 164 return kind == SourceRangeKind::kThen || kind == SourceRangeKind::kElse; 165 } 166 167 private: 168 SourceRange then_range_; 169 SourceRange else_range_; 170 }; 171 172 class FunctionLiteralSourceRanges final : public AstNodeSourceRanges { 173 public: GetRange(SourceRangeKind kind)174 SourceRange GetRange(SourceRangeKind kind) override { 175 DCHECK(HasRange(kind)); 176 return SourceRange::FunctionLiteralMarkerRange(); 177 } 178 HasRange(SourceRangeKind kind)179 bool HasRange(SourceRangeKind kind) override { 180 return kind == SourceRangeKind::kBody; 181 } 182 }; 183 184 class IfStatementSourceRanges final : public AstNodeSourceRanges { 185 public: IfStatementSourceRanges(const SourceRange & then_range,const SourceRange & else_range)186 explicit IfStatementSourceRanges(const SourceRange& then_range, 187 const SourceRange& else_range) 188 : then_range_(then_range), else_range_(else_range) {} 189 GetRange(SourceRangeKind kind)190 SourceRange GetRange(SourceRangeKind kind) override { 191 DCHECK(HasRange(kind)); 192 switch (kind) { 193 case SourceRangeKind::kElse: 194 return else_range_; 195 case SourceRangeKind::kThen: 196 return then_range_; 197 case SourceRangeKind::kContinuation: { 198 if (!has_continuation_) return SourceRange::Empty(); 199 const SourceRange& trailing_range = 200 else_range_.IsEmpty() ? then_range_ : else_range_; 201 return SourceRange::ContinuationOf(trailing_range); 202 } 203 default: 204 UNREACHABLE(); 205 } 206 } 207 HasRange(SourceRangeKind kind)208 bool HasRange(SourceRangeKind kind) override { 209 return kind == SourceRangeKind::kThen || kind == SourceRangeKind::kElse || 210 kind == SourceRangeKind::kContinuation; 211 } 212 RemoveContinuationRange()213 void RemoveContinuationRange() override { 214 DCHECK(HasRange(SourceRangeKind::kContinuation)); 215 has_continuation_ = false; 216 } 217 218 private: 219 SourceRange then_range_; 220 SourceRange else_range_; 221 bool has_continuation_ = true; 222 }; 223 224 class IterationStatementSourceRanges final : public AstNodeSourceRanges { 225 public: IterationStatementSourceRanges(const SourceRange & body_range)226 explicit IterationStatementSourceRanges(const SourceRange& body_range) 227 : body_range_(body_range) {} 228 GetRange(SourceRangeKind kind)229 SourceRange GetRange(SourceRangeKind kind) override { 230 DCHECK(HasRange(kind)); 231 switch (kind) { 232 case SourceRangeKind::kBody: 233 return body_range_; 234 case SourceRangeKind::kContinuation: 235 if (!has_continuation_) return SourceRange::Empty(); 236 return SourceRange::ContinuationOf(body_range_); 237 default: 238 UNREACHABLE(); 239 } 240 } 241 HasRange(SourceRangeKind kind)242 bool HasRange(SourceRangeKind kind) override { 243 return kind == SourceRangeKind::kBody || 244 kind == SourceRangeKind::kContinuation; 245 } 246 RemoveContinuationRange()247 void RemoveContinuationRange() override { 248 DCHECK(HasRange(SourceRangeKind::kContinuation)); 249 has_continuation_ = false; 250 } 251 252 private: 253 SourceRange body_range_; 254 bool has_continuation_ = true; 255 }; 256 257 class JumpStatementSourceRanges final : public ContinuationSourceRanges { 258 public: JumpStatementSourceRanges(int32_t continuation_position)259 explicit JumpStatementSourceRanges(int32_t continuation_position) 260 : ContinuationSourceRanges(continuation_position) {} 261 }; 262 263 class NaryOperationSourceRanges final : public AstNodeSourceRanges { 264 public: NaryOperationSourceRanges(Zone * zone,const SourceRange & range)265 NaryOperationSourceRanges(Zone* zone, const SourceRange& range) 266 : ranges_(zone) { 267 AddRange(range); 268 } 269 GetRangeAtIndex(size_t index)270 SourceRange GetRangeAtIndex(size_t index) { 271 DCHECK(index < ranges_.size()); 272 return ranges_[index]; 273 } 274 AddRange(const SourceRange & range)275 void AddRange(const SourceRange& range) { ranges_.push_back(range); } RangeCount()276 size_t RangeCount() const { return ranges_.size(); } 277 GetRange(SourceRangeKind kind)278 SourceRange GetRange(SourceRangeKind kind) override { UNREACHABLE(); } HasRange(SourceRangeKind kind)279 bool HasRange(SourceRangeKind kind) override { return false; } 280 281 private: 282 ZoneVector<SourceRange> ranges_; 283 }; 284 285 class ExpressionSourceRanges final : public AstNodeSourceRanges { 286 public: ExpressionSourceRanges(const SourceRange & right_range)287 explicit ExpressionSourceRanges(const SourceRange& right_range) 288 : right_range_(right_range) {} 289 GetRange(SourceRangeKind kind)290 SourceRange GetRange(SourceRangeKind kind) override { 291 DCHECK(HasRange(kind)); 292 return right_range_; 293 } 294 HasRange(SourceRangeKind kind)295 bool HasRange(SourceRangeKind kind) override { 296 return kind == SourceRangeKind::kRight; 297 } 298 299 private: 300 SourceRange right_range_; 301 }; 302 303 class SuspendSourceRanges final : public ContinuationSourceRanges { 304 public: SuspendSourceRanges(int32_t continuation_position)305 explicit SuspendSourceRanges(int32_t continuation_position) 306 : ContinuationSourceRanges(continuation_position) {} 307 }; 308 309 class SwitchStatementSourceRanges final : public ContinuationSourceRanges { 310 public: SwitchStatementSourceRanges(int32_t continuation_position)311 explicit SwitchStatementSourceRanges(int32_t continuation_position) 312 : ContinuationSourceRanges(continuation_position) {} 313 }; 314 315 class ThrowSourceRanges final : public ContinuationSourceRanges { 316 public: ThrowSourceRanges(int32_t continuation_position)317 explicit ThrowSourceRanges(int32_t continuation_position) 318 : ContinuationSourceRanges(continuation_position) {} 319 }; 320 321 class TryCatchStatementSourceRanges final : public AstNodeSourceRanges { 322 public: TryCatchStatementSourceRanges(const SourceRange & catch_range)323 explicit TryCatchStatementSourceRanges(const SourceRange& catch_range) 324 : catch_range_(catch_range) {} 325 GetRange(SourceRangeKind kind)326 SourceRange GetRange(SourceRangeKind kind) override { 327 DCHECK(HasRange(kind)); 328 switch (kind) { 329 case SourceRangeKind::kCatch: 330 return catch_range_; 331 case SourceRangeKind::kContinuation: 332 if (!has_continuation_) return SourceRange::Empty(); 333 return SourceRange::ContinuationOf(catch_range_); 334 default: 335 UNREACHABLE(); 336 } 337 } 338 HasRange(SourceRangeKind kind)339 bool HasRange(SourceRangeKind kind) override { 340 return kind == SourceRangeKind::kCatch || 341 kind == SourceRangeKind::kContinuation; 342 } 343 RemoveContinuationRange()344 void RemoveContinuationRange() override { 345 DCHECK(HasRange(SourceRangeKind::kContinuation)); 346 has_continuation_ = false; 347 } 348 349 private: 350 SourceRange catch_range_; 351 bool has_continuation_ = true; 352 }; 353 354 class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges { 355 public: TryFinallyStatementSourceRanges(const SourceRange & finally_range)356 explicit TryFinallyStatementSourceRanges(const SourceRange& finally_range) 357 : finally_range_(finally_range) {} 358 GetRange(SourceRangeKind kind)359 SourceRange GetRange(SourceRangeKind kind) override { 360 DCHECK(HasRange(kind)); 361 switch (kind) { 362 case SourceRangeKind::kFinally: 363 return finally_range_; 364 case SourceRangeKind::kContinuation: 365 if (!has_continuation_) return SourceRange::Empty(); 366 return SourceRange::ContinuationOf(finally_range_); 367 default: 368 UNREACHABLE(); 369 } 370 } 371 HasRange(SourceRangeKind kind)372 bool HasRange(SourceRangeKind kind) override { 373 return kind == SourceRangeKind::kFinally || 374 kind == SourceRangeKind::kContinuation; 375 } 376 RemoveContinuationRange()377 void RemoveContinuationRange() override { 378 DCHECK(HasRange(SourceRangeKind::kContinuation)); 379 has_continuation_ = false; 380 } 381 382 private: 383 SourceRange finally_range_; 384 bool has_continuation_ = true; 385 }; 386 387 // Maps ast node pointers to associated source ranges. The parser creates these 388 // mappings and the bytecode generator consumes them. 389 class SourceRangeMap final : public ZoneObject { 390 public: SourceRangeMap(Zone * zone)391 explicit SourceRangeMap(Zone* zone) : map_(zone) {} 392 Find(ZoneObject * node)393 AstNodeSourceRanges* Find(ZoneObject* node) { 394 auto it = map_.find(node); 395 if (it == map_.end()) return nullptr; 396 return it->second; 397 } 398 399 // Type-checked insertion. 400 #define DEFINE_MAP_INSERT(type) \ 401 void Insert(type* node, type##SourceRanges* ranges) { \ 402 DCHECK_NOT_NULL(node); \ 403 map_.emplace(node, ranges); \ 404 } 405 AST_SOURCE_RANGE_LIST(DEFINE_MAP_INSERT) 406 #undef DEFINE_MAP_INSERT 407 408 private: 409 ZoneMap<ZoneObject*, AstNodeSourceRanges*> map_; 410 }; 411 412 } // namespace internal 413 } // namespace v8 414 415 #endif // V8_AST_AST_SOURCE_RANGES_H_ 416