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