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