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 : SourceRange() : SourceRange(kNoSourcePosition, kNoSourcePosition) {}
18 53492371 : 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 877 : static SourceRange ContinuationOf(const SourceRange& that) {
25 877 : 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(Block) \
34 : V(CaseClause) \
35 : V(Conditional) \
36 : V(IfStatement) \
37 : V(IterationStatement) \
38 : V(JumpStatement) \
39 : V(Suspend) \
40 : V(SwitchStatement) \
41 : V(Throw) \
42 : V(TryCatchStatement) \
43 : V(TryFinallyStatement)
44 :
45 : enum class SourceRangeKind {
46 : kBody,
47 : kCatch,
48 : kContinuation,
49 : kElse,
50 : kFinally,
51 : kThen,
52 : };
53 :
54 2462 : class AstNodeSourceRanges : public ZoneObject {
55 : public:
56 0 : virtual ~AstNodeSourceRanges() {}
57 : virtual SourceRange GetRange(SourceRangeKind kind) = 0;
58 : };
59 :
60 0 : class ContinuationSourceRanges : public AstNodeSourceRanges {
61 : public:
62 : explicit ContinuationSourceRanges(int32_t continuation_position)
63 1461 : : continuation_position_(continuation_position) {}
64 :
65 1149 : SourceRange GetRange(SourceRangeKind kind) {
66 : DCHECK_EQ(kind, SourceRangeKind::kContinuation);
67 1149 : return SourceRange::OpenEnded(continuation_position_);
68 : }
69 :
70 : private:
71 : int32_t continuation_position_;
72 : };
73 :
74 0 : class BlockSourceRanges final : public ContinuationSourceRanges {
75 : public:
76 612 : explicit BlockSourceRanges(int32_t continuation_position)
77 612 : : ContinuationSourceRanges(continuation_position) {}
78 : };
79 :
80 0 : class CaseClauseSourceRanges final : public AstNodeSourceRanges {
81 : public:
82 36 : explicit CaseClauseSourceRanges(const SourceRange& body_range)
83 36 : : body_range_(body_range) {}
84 :
85 36 : SourceRange GetRange(SourceRangeKind kind) {
86 : DCHECK_EQ(kind, SourceRangeKind::kBody);
87 36 : return body_range_;
88 : }
89 :
90 : private:
91 : SourceRange body_range_;
92 : };
93 :
94 0 : class ConditionalSourceRanges final : public AstNodeSourceRanges {
95 : public:
96 88 : explicit ConditionalSourceRanges(const SourceRange& then_range,
97 : const SourceRange& else_range)
98 88 : : then_range_(then_range), else_range_(else_range) {}
99 :
100 176 : SourceRange GetRange(SourceRangeKind kind) {
101 176 : switch (kind) {
102 : case SourceRangeKind::kThen:
103 88 : return then_range_;
104 : case SourceRangeKind::kElse:
105 88 : return else_range_;
106 : default:
107 0 : UNREACHABLE();
108 : }
109 : }
110 :
111 : private:
112 : SourceRange then_range_;
113 : SourceRange else_range_;
114 : };
115 :
116 0 : class IfStatementSourceRanges final : public AstNodeSourceRanges {
117 : public:
118 427 : explicit IfStatementSourceRanges(const SourceRange& then_range,
119 : const SourceRange& else_range)
120 427 : : then_range_(then_range), else_range_(else_range) {}
121 :
122 1281 : SourceRange GetRange(SourceRangeKind kind) {
123 1281 : switch (kind) {
124 : case SourceRangeKind::kElse:
125 427 : return else_range_;
126 : case SourceRangeKind::kThen:
127 427 : return then_range_;
128 : case SourceRangeKind::kContinuation: {
129 : const SourceRange& trailing_range =
130 427 : else_range_.IsEmpty() ? then_range_ : else_range_;
131 : return SourceRange::ContinuationOf(trailing_range);
132 : }
133 : default:
134 0 : UNREACHABLE();
135 : }
136 : }
137 :
138 : private:
139 : SourceRange then_range_;
140 : SourceRange else_range_;
141 : };
142 :
143 0 : class IterationStatementSourceRanges final : public AstNodeSourceRanges {
144 : public:
145 330 : explicit IterationStatementSourceRanges(const SourceRange& body_range)
146 330 : : body_range_(body_range) {}
147 :
148 660 : SourceRange GetRange(SourceRangeKind kind) {
149 660 : switch (kind) {
150 : case SourceRangeKind::kBody:
151 330 : return body_range_;
152 : case SourceRangeKind::kContinuation:
153 : return SourceRange::ContinuationOf(body_range_);
154 : default:
155 0 : UNREACHABLE();
156 : }
157 : }
158 :
159 : private:
160 : SourceRange body_range_;
161 : };
162 :
163 0 : class JumpStatementSourceRanges final : public ContinuationSourceRanges {
164 : public:
165 615 : explicit JumpStatementSourceRanges(int32_t continuation_position)
166 615 : : ContinuationSourceRanges(continuation_position) {}
167 : };
168 :
169 0 : class SuspendSourceRanges final : public ContinuationSourceRanges {
170 : public:
171 174 : explicit SuspendSourceRanges(int32_t continuation_position)
172 174 : : ContinuationSourceRanges(continuation_position) {}
173 : };
174 :
175 0 : class SwitchStatementSourceRanges final : public ContinuationSourceRanges {
176 : public:
177 18 : explicit SwitchStatementSourceRanges(int32_t continuation_position)
178 18 : : ContinuationSourceRanges(continuation_position) {}
179 : };
180 :
181 0 : class ThrowSourceRanges final : public ContinuationSourceRanges {
182 : public:
183 42 : explicit ThrowSourceRanges(int32_t continuation_position)
184 42 : : ContinuationSourceRanges(continuation_position) {}
185 : };
186 :
187 0 : class TryCatchStatementSourceRanges final : public AstNodeSourceRanges {
188 : public:
189 78 : explicit TryCatchStatementSourceRanges(const SourceRange& catch_range)
190 78 : : catch_range_(catch_range) {}
191 :
192 156 : SourceRange GetRange(SourceRangeKind kind) {
193 156 : switch (kind) {
194 : case SourceRangeKind::kCatch:
195 78 : return catch_range_;
196 : case SourceRangeKind::kContinuation:
197 : return SourceRange::ContinuationOf(catch_range_);
198 : default:
199 0 : UNREACHABLE();
200 : }
201 : }
202 :
203 : private:
204 : SourceRange catch_range_;
205 : };
206 :
207 0 : class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges {
208 : public:
209 42 : explicit TryFinallyStatementSourceRanges(const SourceRange& finally_range)
210 42 : : finally_range_(finally_range) {}
211 :
212 84 : SourceRange GetRange(SourceRangeKind kind) {
213 84 : switch (kind) {
214 : case SourceRangeKind::kFinally:
215 42 : return finally_range_;
216 : case SourceRangeKind::kContinuation:
217 : return SourceRange::ContinuationOf(finally_range_);
218 : default:
219 0 : UNREACHABLE();
220 : }
221 : }
222 :
223 : private:
224 : SourceRange finally_range_;
225 : };
226 :
227 : // Maps ast node pointers to associated source ranges. The parser creates these
228 : // mappings and the bytecode generator consumes them.
229 : class SourceRangeMap final : public ZoneObject {
230 : public:
231 : explicit SourceRangeMap(Zone* zone) : map_(zone) {}
232 :
233 : AstNodeSourceRanges* Find(ZoneObject* node) {
234 : auto it = map_.find(node);
235 5252 : if (it == map_.end()) return nullptr;
236 3542 : return it->second;
237 : }
238 :
239 : // Type-checked insertion.
240 : #define DEFINE_MAP_INSERT(type) \
241 : void Insert(type* node, type##SourceRanges* ranges) { \
242 : DCHECK_NOT_NULL(node); \
243 : map_.emplace(node, ranges); \
244 : }
245 4924 : AST_SOURCE_RANGE_LIST(DEFINE_MAP_INSERT)
246 : #undef DEFINE_MAP_INSERT
247 :
248 : private:
249 : ZoneMap<ZoneObject*, AstNodeSourceRanges*> map_;
250 : };
251 :
252 : } // namespace internal
253 : } // namespace v8
254 :
255 : #endif // V8_AST_AST_SOURCE_RANGES_H_
|