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 386454 : SourceRange() : SourceRange(kNoSourcePosition, kNoSourcePosition) {}
18 4007114 : 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 72192 : static SourceRange ContinuationOf(const SourceRange& that,
25 : int end = kNoSourcePosition) {
26 72192 : 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 3165 : 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 290 : explicit BinaryOperationSourceRanges(const SourceRange& right_range)
69 290 : : right_range_(right_range) {}
70 :
71 280 : SourceRange GetRange(SourceRangeKind kind) override {
72 : DCHECK(HasRange(kind));
73 280 : return right_range_;
74 : }
75 :
76 160 : bool HasRange(SourceRangeKind kind) override {
77 160 : 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 1640 : : continuation_position_(continuation_position) {}
88 :
89 3225 : SourceRange GetRange(SourceRangeKind kind) override {
90 : DCHECK(HasRange(kind));
91 3225 : return SourceRange::OpenEnded(continuation_position_);
92 : }
93 :
94 2745 : bool HasRange(SourceRangeKind kind) override {
95 2745 : return kind == SourceRangeKind::kContinuation;
96 : }
97 :
98 1200 : void RemoveContinuationRange() override {
99 : DCHECK(HasRange(SourceRangeKind::kContinuation));
100 1200 : continuation_position_ = kNoSourcePosition;
101 1200 : }
102 :
103 : private:
104 : int32_t continuation_position_;
105 : };
106 :
107 0 : class BlockSourceRanges final : public ContinuationSourceRanges {
108 : public:
109 725 : explicit BlockSourceRanges(int32_t continuation_position)
110 725 : : ContinuationSourceRanges(continuation_position) {}
111 : };
112 :
113 0 : class CaseClauseSourceRanges final : public AstNodeSourceRanges {
114 : public:
115 30 : explicit CaseClauseSourceRanges(const SourceRange& body_range)
116 30 : : body_range_(body_range) {}
117 :
118 30 : SourceRange GetRange(SourceRangeKind kind) override {
119 : DCHECK(HasRange(kind));
120 30 : 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 100 : explicit ConditionalSourceRanges(const SourceRange& then_range,
134 : const SourceRange& else_range)
135 100 : : then_range_(then_range), else_range_(else_range) {}
136 :
137 200 : SourceRange GetRange(SourceRangeKind kind) override {
138 : DCHECK(HasRange(kind));
139 200 : switch (kind) {
140 : case SourceRangeKind::kThen:
141 100 : return then_range_;
142 : case SourceRangeKind::kElse:
143 100 : return else_range_;
144 : default:
145 0 : UNREACHABLE();
146 : }
147 : }
148 :
149 100 : bool HasRange(SourceRangeKind kind) override {
150 100 : 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 570 : explicit IfStatementSourceRanges(const SourceRange& then_range,
161 : const SourceRange& else_range)
162 570 : : then_range_(then_range), else_range_(else_range) {}
163 :
164 2220 : SourceRange GetRange(SourceRangeKind kind) override {
165 : DCHECK(HasRange(kind));
166 2220 : switch (kind) {
167 : case SourceRangeKind::kElse:
168 550 : return else_range_;
169 : case SourceRangeKind::kThen:
170 550 : return then_range_;
171 : case SourceRangeKind::kContinuation: {
172 1120 : if (!has_continuation_) return SourceRange::Empty();
173 : const SourceRange& trailing_range =
174 915 : else_range_.IsEmpty() ? then_range_ : else_range_;
175 : return SourceRange::ContinuationOf(trailing_range);
176 : }
177 : default:
178 0 : UNREACHABLE();
179 : }
180 : }
181 :
182 775 : bool HasRange(SourceRangeKind kind) override {
183 775 : return kind == SourceRangeKind::kThen || kind == SourceRangeKind::kElse ||
184 775 : kind == SourceRangeKind::kContinuation;
185 : }
186 :
187 225 : void RemoveContinuationRange() override {
188 : DCHECK(HasRange(SourceRangeKind::kContinuation));
189 225 : has_continuation_ = false;
190 225 : }
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 305 : explicit IterationStatementSourceRanges(const SourceRange& body_range)
201 305 : : body_range_(body_range) {}
202 :
203 915 : SourceRange GetRange(SourceRangeKind kind) override {
204 : DCHECK(HasRange(kind));
205 915 : switch (kind) {
206 : case SourceRangeKind::kBody:
207 305 : return body_range_;
208 : case SourceRangeKind::kContinuation:
209 610 : if (!has_continuation_) return SourceRange::Empty();
210 : return SourceRange::ContinuationOf(body_range_);
211 : default:
212 0 : UNREACHABLE();
213 : }
214 : }
215 :
216 370 : bool HasRange(SourceRangeKind kind) override {
217 370 : return kind == SourceRangeKind::kBody ||
218 370 : kind == SourceRangeKind::kContinuation;
219 : }
220 :
221 70 : void RemoveContinuationRange() override {
222 : DCHECK(HasRange(SourceRangeKind::kContinuation));
223 70 : has_continuation_ = false;
224 70 : }
225 :
226 : private:
227 : SourceRange body_range_;
228 : bool has_continuation_ = true;
229 : };
230 :
231 0 : class JumpStatementSourceRanges final : public ContinuationSourceRanges {
232 : public:
233 720 : explicit JumpStatementSourceRanges(int32_t continuation_position)
234 720 : : ContinuationSourceRanges(continuation_position) {}
235 : };
236 :
237 0 : class NaryOperationSourceRanges final : public AstNodeSourceRanges {
238 : public:
239 130 : NaryOperationSourceRanges(Zone* zone, const SourceRange& range)
240 130 : : ranges_(zone) {
241 : AddRange(range);
242 130 : }
243 :
244 : SourceRange GetRangeAtIndex(size_t index) {
245 : DCHECK(index < ranges_.size());
246 610 : return ranges_[index];
247 : }
248 :
249 305 : 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 130 : 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 145 : explicit SuspendSourceRanges(int32_t continuation_position)
262 145 : : ContinuationSourceRanges(continuation_position) {}
263 : };
264 :
265 0 : class SwitchStatementSourceRanges final : public ContinuationSourceRanges {
266 : public:
267 15 : explicit SwitchStatementSourceRanges(int32_t continuation_position)
268 15 : : ContinuationSourceRanges(continuation_position) {}
269 : };
270 :
271 0 : class ThrowSourceRanges final : public ContinuationSourceRanges {
272 : public:
273 35 : explicit ThrowSourceRanges(int32_t continuation_position)
274 35 : : ContinuationSourceRanges(continuation_position) {}
275 : };
276 :
277 0 : class TryCatchStatementSourceRanges final : public AstNodeSourceRanges {
278 : public:
279 65 : explicit TryCatchStatementSourceRanges(const SourceRange& catch_range)
280 65 : : catch_range_(catch_range) {}
281 :
282 195 : SourceRange GetRange(SourceRangeKind kind) override {
283 : DCHECK(HasRange(kind));
284 195 : switch (kind) {
285 : case SourceRangeKind::kCatch:
286 65 : return catch_range_;
287 : case SourceRangeKind::kContinuation:
288 130 : if (!has_continuation_) return SourceRange::Empty();
289 : return SourceRange::ContinuationOf(catch_range_);
290 : default:
291 0 : UNREACHABLE();
292 : }
293 : }
294 :
295 80 : bool HasRange(SourceRangeKind kind) override {
296 80 : return kind == SourceRangeKind::kCatch ||
297 80 : kind == SourceRangeKind::kContinuation;
298 : }
299 :
300 15 : void RemoveContinuationRange() override {
301 : DCHECK(HasRange(SourceRangeKind::kContinuation));
302 15 : has_continuation_ = false;
303 15 : }
304 :
305 : private:
306 : SourceRange catch_range_;
307 : bool has_continuation_ = true;
308 : };
309 :
310 0 : class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges {
311 : public:
312 35 : explicit TryFinallyStatementSourceRanges(const SourceRange& finally_range)
313 35 : : finally_range_(finally_range) {}
314 :
315 105 : SourceRange GetRange(SourceRangeKind kind) override {
316 : DCHECK(HasRange(kind));
317 105 : switch (kind) {
318 : case SourceRangeKind::kFinally:
319 35 : return finally_range_;
320 : case SourceRangeKind::kContinuation:
321 70 : if (!has_continuation_) return SourceRange::Empty();
322 : return SourceRange::ContinuationOf(finally_range_);
323 : default:
324 0 : UNREACHABLE();
325 : }
326 : }
327 :
328 45 : bool HasRange(SourceRangeKind kind) override {
329 45 : return kind == SourceRangeKind::kFinally ||
330 45 : kind == SourceRangeKind::kContinuation;
331 : }
332 :
333 10 : void RemoveContinuationRange() override {
334 : DCHECK(HasRange(SourceRangeKind::kContinuation));
335 10 : has_continuation_ = false;
336 10 : }
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 305 : AstNodeSourceRanges* Find(ZoneObject* node) {
350 : auto it = map_.find(node);
351 30170 : if (it == map_.end()) return nullptr;
352 9440 : 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 6330 : 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_
|