• 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   }
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