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 } ContinuationOfSourceRange24 static SourceRange ContinuationOf(const SourceRange& that) { 25 return that.IsEmpty() ? Empty() : OpenEnded(that.end); 26 } 27 int32_t start, end; 28 }; 29 30 // The list of ast node kinds that have associated source ranges. Note that this 31 // macro is not undefined at the end of this file. 32 #define AST_SOURCE_RANGE_LIST(V) \ 33 V(BinaryOperation) \ 34 V(Block) \ 35 V(CaseClause) \ 36 V(Conditional) \ 37 V(IfStatement) \ 38 V(IterationStatement) \ 39 V(JumpStatement) \ 40 V(NaryOperation) \ 41 V(Suspend) \ 42 V(SwitchStatement) \ 43 V(Throw) \ 44 V(TryCatchStatement) \ 45 V(TryFinallyStatement) 46 47 enum class SourceRangeKind { 48 kBody, 49 kCatch, 50 kContinuation, 51 kElse, 52 kFinally, 53 kRight, 54 kThen, 55 }; 56 57 class AstNodeSourceRanges : public ZoneObject { 58 public: ~AstNodeSourceRanges()59 virtual ~AstNodeSourceRanges() {} 60 virtual SourceRange GetRange(SourceRangeKind kind) = 0; 61 }; 62 63 class BinaryOperationSourceRanges final : public AstNodeSourceRanges { 64 public: BinaryOperationSourceRanges(const SourceRange & right_range)65 explicit BinaryOperationSourceRanges(const SourceRange& right_range) 66 : right_range_(right_range) {} 67 GetRange(SourceRangeKind kind)68 SourceRange GetRange(SourceRangeKind kind) { 69 DCHECK_EQ(kind, SourceRangeKind::kRight); 70 return right_range_; 71 } 72 73 private: 74 SourceRange right_range_; 75 }; 76 77 class ContinuationSourceRanges : public AstNodeSourceRanges { 78 public: ContinuationSourceRanges(int32_t continuation_position)79 explicit ContinuationSourceRanges(int32_t continuation_position) 80 : continuation_position_(continuation_position) {} 81 GetRange(SourceRangeKind kind)82 SourceRange GetRange(SourceRangeKind kind) { 83 DCHECK_EQ(kind, SourceRangeKind::kContinuation); 84 return SourceRange::OpenEnded(continuation_position_); 85 } 86 87 private: 88 int32_t continuation_position_; 89 }; 90 91 class BlockSourceRanges final : public ContinuationSourceRanges { 92 public: BlockSourceRanges(int32_t continuation_position)93 explicit BlockSourceRanges(int32_t continuation_position) 94 : ContinuationSourceRanges(continuation_position) {} 95 }; 96 97 class CaseClauseSourceRanges final : public AstNodeSourceRanges { 98 public: CaseClauseSourceRanges(const SourceRange & body_range)99 explicit CaseClauseSourceRanges(const SourceRange& body_range) 100 : body_range_(body_range) {} 101 GetRange(SourceRangeKind kind)102 SourceRange GetRange(SourceRangeKind kind) { 103 DCHECK_EQ(kind, SourceRangeKind::kBody); 104 return body_range_; 105 } 106 107 private: 108 SourceRange body_range_; 109 }; 110 111 class ConditionalSourceRanges final : public AstNodeSourceRanges { 112 public: ConditionalSourceRanges(const SourceRange & then_range,const SourceRange & else_range)113 explicit ConditionalSourceRanges(const SourceRange& then_range, 114 const SourceRange& else_range) 115 : then_range_(then_range), else_range_(else_range) {} 116 GetRange(SourceRangeKind kind)117 SourceRange GetRange(SourceRangeKind kind) { 118 switch (kind) { 119 case SourceRangeKind::kThen: 120 return then_range_; 121 case SourceRangeKind::kElse: 122 return else_range_; 123 default: 124 UNREACHABLE(); 125 } 126 } 127 128 private: 129 SourceRange then_range_; 130 SourceRange else_range_; 131 }; 132 133 class IfStatementSourceRanges final : public AstNodeSourceRanges { 134 public: IfStatementSourceRanges(const SourceRange & then_range,const SourceRange & else_range)135 explicit IfStatementSourceRanges(const SourceRange& then_range, 136 const SourceRange& else_range) 137 : then_range_(then_range), else_range_(else_range) {} 138 GetRange(SourceRangeKind kind)139 SourceRange GetRange(SourceRangeKind kind) { 140 switch (kind) { 141 case SourceRangeKind::kElse: 142 return else_range_; 143 case SourceRangeKind::kThen: 144 return then_range_; 145 case SourceRangeKind::kContinuation: { 146 const SourceRange& trailing_range = 147 else_range_.IsEmpty() ? then_range_ : else_range_; 148 return SourceRange::ContinuationOf(trailing_range); 149 } 150 default: 151 UNREACHABLE(); 152 } 153 } 154 155 private: 156 SourceRange then_range_; 157 SourceRange else_range_; 158 }; 159 160 class IterationStatementSourceRanges final : public AstNodeSourceRanges { 161 public: IterationStatementSourceRanges(const SourceRange & body_range)162 explicit IterationStatementSourceRanges(const SourceRange& body_range) 163 : body_range_(body_range) {} 164 GetRange(SourceRangeKind kind)165 SourceRange GetRange(SourceRangeKind kind) { 166 switch (kind) { 167 case SourceRangeKind::kBody: 168 return body_range_; 169 case SourceRangeKind::kContinuation: 170 return SourceRange::ContinuationOf(body_range_); 171 default: 172 UNREACHABLE(); 173 } 174 } 175 176 private: 177 SourceRange body_range_; 178 }; 179 180 class JumpStatementSourceRanges final : public ContinuationSourceRanges { 181 public: JumpStatementSourceRanges(int32_t continuation_position)182 explicit JumpStatementSourceRanges(int32_t continuation_position) 183 : ContinuationSourceRanges(continuation_position) {} 184 }; 185 186 class NaryOperationSourceRanges final : public AstNodeSourceRanges { 187 public: NaryOperationSourceRanges(Zone * zone,const SourceRange & range)188 NaryOperationSourceRanges(Zone* zone, const SourceRange& range) 189 : ranges_(zone) { 190 AddRange(range); 191 } 192 GetRangeAtIndex(size_t index)193 SourceRange GetRangeAtIndex(size_t index) { 194 DCHECK(index < ranges_.size()); 195 return ranges_[index]; 196 } 197 AddRange(const SourceRange & range)198 void AddRange(const SourceRange& range) { ranges_.push_back(range); } RangeCount()199 size_t RangeCount() const { return ranges_.size(); } 200 GetRange(SourceRangeKind kind)201 SourceRange GetRange(SourceRangeKind kind) { UNREACHABLE(); } 202 203 private: 204 ZoneVector<SourceRange> ranges_; 205 }; 206 207 class SuspendSourceRanges final : public ContinuationSourceRanges { 208 public: SuspendSourceRanges(int32_t continuation_position)209 explicit SuspendSourceRanges(int32_t continuation_position) 210 : ContinuationSourceRanges(continuation_position) {} 211 }; 212 213 class SwitchStatementSourceRanges final : public ContinuationSourceRanges { 214 public: SwitchStatementSourceRanges(int32_t continuation_position)215 explicit SwitchStatementSourceRanges(int32_t continuation_position) 216 : ContinuationSourceRanges(continuation_position) {} 217 }; 218 219 class ThrowSourceRanges final : public ContinuationSourceRanges { 220 public: ThrowSourceRanges(int32_t continuation_position)221 explicit ThrowSourceRanges(int32_t continuation_position) 222 : ContinuationSourceRanges(continuation_position) {} 223 }; 224 225 class TryCatchStatementSourceRanges final : public AstNodeSourceRanges { 226 public: TryCatchStatementSourceRanges(const SourceRange & catch_range)227 explicit TryCatchStatementSourceRanges(const SourceRange& catch_range) 228 : catch_range_(catch_range) {} 229 GetRange(SourceRangeKind kind)230 SourceRange GetRange(SourceRangeKind kind) { 231 switch (kind) { 232 case SourceRangeKind::kCatch: 233 return catch_range_; 234 case SourceRangeKind::kContinuation: 235 return SourceRange::ContinuationOf(catch_range_); 236 default: 237 UNREACHABLE(); 238 } 239 } 240 241 private: 242 SourceRange catch_range_; 243 }; 244 245 class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges { 246 public: TryFinallyStatementSourceRanges(const SourceRange & finally_range)247 explicit TryFinallyStatementSourceRanges(const SourceRange& finally_range) 248 : finally_range_(finally_range) {} 249 GetRange(SourceRangeKind kind)250 SourceRange GetRange(SourceRangeKind kind) { 251 switch (kind) { 252 case SourceRangeKind::kFinally: 253 return finally_range_; 254 case SourceRangeKind::kContinuation: 255 return SourceRange::ContinuationOf(finally_range_); 256 default: 257 UNREACHABLE(); 258 } 259 } 260 261 private: 262 SourceRange finally_range_; 263 }; 264 265 // Maps ast node pointers to associated source ranges. The parser creates these 266 // mappings and the bytecode generator consumes them. 267 class SourceRangeMap final : public ZoneObject { 268 public: SourceRangeMap(Zone * zone)269 explicit SourceRangeMap(Zone* zone) : map_(zone) {} 270 Find(ZoneObject * node)271 AstNodeSourceRanges* Find(ZoneObject* node) { 272 auto it = map_.find(node); 273 if (it == map_.end()) return nullptr; 274 return it->second; 275 } 276 277 // Type-checked insertion. 278 #define DEFINE_MAP_INSERT(type) \ 279 void Insert(type* node, type##SourceRanges* ranges) { \ 280 DCHECK_NOT_NULL(node); \ 281 map_.emplace(node, ranges); \ 282 } 283 AST_SOURCE_RANGE_LIST(DEFINE_MAP_INSERT) 284 #undef DEFINE_MAP_INSERT 285 286 private: 287 ZoneMap<ZoneObject*, AstNodeSourceRanges*> map_; 288 }; 289 290 } // namespace internal 291 } // namespace v8 292 293 #endif // V8_AST_AST_SOURCE_RANGES_H_ 294