OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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_TRAVERSAL_VISITOR_H_ | |
6 #define V8_AST_AST_TRAVERSAL_VISITOR_H_ | |
7 | |
8 #include "src/ast/ast.h" | |
9 #include "src/ast/scopes.h" | |
10 | |
11 namespace v8 { | |
12 namespace internal { | |
13 | |
14 // ---------------------------------------------------------------------------- | |
15 // Traversal visitor | |
16 // - fully traverses the entire AST. | |
17 // | |
18 // Sub-class should parametrize AstTraversalVisitor with itself, e.g.: | |
19 // class SpecificVisitor : public AstTraversalVisitor<SpecificVisitor> { ... } | |
20 // | |
21 // It invokes VisitNode on each AST node, before proceeding with its subtrees. | |
22 // It invokes VisitExpression (after VisitNode) on each AST node that is an | |
23 // expression, before proceeding with its subtrees. | |
24 // It proceeds with the subtrees only if these two methods return true. | |
25 // Sub-classes may override VisitNode and VisitExpressions, whose implementation | |
26 // is dummy here. Or they may override the specific Visit* methods. | |
27 | |
28 template <class Subclass> | |
29 class AstTraversalVisitor : public AstVisitor<Subclass> { | |
30 public: | |
31 explicit AstTraversalVisitor(Isolate* isolate, AstNode* root = nullptr); | |
32 explicit AstTraversalVisitor(uintptr_t stack_limit, AstNode* root = nullptr); | |
33 | |
34 void Run() { | |
35 DCHECK_NOT_NULL(root_); | |
36 Visit(root_); | |
37 } | |
38 | |
39 bool VisitNode(AstNode* node) { return true; } | |
40 bool VisitExpression(Expression* node) { return true; } | |
adamk
2016/07/21 18:11:57
I don't see either of these methods overridden any
nickie
2016/07/22 08:40:18
They're not yet. The idea is to have them there,
adamk
2016/07/22 18:02:31
Makes sense, I wanted to be clear that they're not
| |
41 | |
42 // Iteration left-to-right. | |
43 void VisitDeclarations(ZoneList<Declaration*>* declarations); | |
44 void VisitStatements(ZoneList<Statement*>* statements); | |
45 | |
46 // Individual nodes | |
47 #define DECLARE_VISIT(type) void Visit##type(type* node); | |
48 AST_NODE_LIST(DECLARE_VISIT) | |
49 #undef DECLARE_VISIT | |
50 | |
51 protected: | |
52 int depth() { return depth_; } | |
adamk
2016/07/21 18:11:57
Nit: make this a const method
nickie
2016/07/22 08:40:18
Done.
| |
53 | |
54 private: | |
55 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | |
56 | |
57 AstNode* root_; | |
58 int depth_; | |
59 | |
60 DISALLOW_COPY_AND_ASSIGN(AstTraversalVisitor); | |
61 }; | |
62 | |
63 // ---------------------------------------------------------------------------- | |
64 // Implementation of AstTraversalVisitor | |
65 | |
66 #define PROCESS_NODE(node) do { \ | |
67 if (!(this->impl()->VisitNode(node))) return; \ | |
68 } while (false) | |
69 | |
70 #define PROCESS_EXPRESSION(node) do { \ | |
71 PROCESS_NODE(node); \ | |
72 if (!(this->impl()->VisitExpression(node))) return; \ | |
73 } while (false) | |
74 | |
75 #define RECURSE(call) \ | |
76 do { \ | |
77 DCHECK(!HasStackOverflow()); \ | |
78 this->impl()->call; \ | |
79 if (HasStackOverflow()) return; \ | |
80 } while (false) | |
81 | |
82 #define RECURSE_EXPRESSION(call) \ | |
83 do { \ | |
84 DCHECK(!HasStackOverflow()); \ | |
85 ++depth_; \ | |
86 this->impl()->call; \ | |
87 --depth_; \ | |
88 if (HasStackOverflow()) return; \ | |
89 } while (false) | |
90 | |
91 template <class Subclass> | |
92 AstTraversalVisitor<Subclass>::AstTraversalVisitor(Isolate* isolate, | |
93 AstNode* root) | |
94 : root_(root), depth_(0) { | |
95 InitializeAstVisitor(isolate); | |
96 } | |
97 | |
98 template <class Subclass> | |
99 AstTraversalVisitor<Subclass>::AstTraversalVisitor(uintptr_t stack_limit, | |
100 AstNode* root) | |
101 : root_(root), depth_(0) { | |
102 InitializeAstVisitor(stack_limit); | |
103 } | |
104 | |
105 template <class Subclass> | |
106 void AstTraversalVisitor<Subclass>::VisitDeclarations( | |
107 ZoneList<Declaration*>* decls) { | |
108 for (int i = 0; i < decls->length(); ++i) { | |
109 Declaration* decl = decls->at(i); | |
110 RECURSE(Visit(decl)); | |
111 } | |
112 } | |
113 | |
114 template <class Subclass> | |
115 void AstTraversalVisitor<Subclass>::VisitStatements( | |
116 ZoneList<Statement*>* stmts) { | |
117 for (int i = 0; i < stmts->length(); ++i) { | |
118 Statement* stmt = stmts->at(i); | |
119 RECURSE(Visit(stmt)); | |
120 if (stmt->IsJump()) break; | |
121 } | |
122 } | |
123 | |
124 template <class Subclass> | |
125 void AstTraversalVisitor<Subclass>::VisitVariableDeclaration( | |
126 VariableDeclaration* decl) { | |
127 PROCESS_NODE(decl); | |
128 } | |
129 | |
130 template <class Subclass> | |
131 void AstTraversalVisitor<Subclass>::VisitFunctionDeclaration( | |
132 FunctionDeclaration* decl) { | |
133 PROCESS_NODE(decl); | |
134 RECURSE(Visit(decl->fun())); | |
135 } | |
136 | |
137 template <class Subclass> | |
138 void AstTraversalVisitor<Subclass>::VisitBlock(Block* stmt) { | |
139 PROCESS_NODE(stmt); | |
140 RECURSE(VisitStatements(stmt->statements())); | |
141 } | |
142 | |
143 template <class Subclass> | |
144 void AstTraversalVisitor<Subclass>::VisitExpressionStatement( | |
145 ExpressionStatement* stmt) { | |
146 PROCESS_NODE(stmt); | |
147 RECURSE(Visit(stmt->expression())); | |
148 } | |
149 | |
150 template <class Subclass> | |
151 void AstTraversalVisitor<Subclass>::VisitEmptyStatement(EmptyStatement* stmt) {} | |
152 | |
153 template <class Subclass> | |
154 void AstTraversalVisitor<Subclass>::VisitSloppyBlockFunctionStatement( | |
155 SloppyBlockFunctionStatement* stmt) { | |
156 PROCESS_NODE(stmt); | |
157 RECURSE(Visit(stmt->statement())); | |
158 } | |
159 | |
160 template <class Subclass> | |
161 void AstTraversalVisitor<Subclass>::VisitIfStatement(IfStatement* stmt) { | |
162 PROCESS_NODE(stmt); | |
163 RECURSE(Visit(stmt->condition())); | |
164 RECURSE(Visit(stmt->then_statement())); | |
165 RECURSE(Visit(stmt->else_statement())); | |
166 } | |
167 | |
168 template <class Subclass> | |
169 void AstTraversalVisitor<Subclass>::VisitContinueStatement( | |
170 ContinueStatement* stmt) { | |
171 PROCESS_NODE(stmt); | |
172 } | |
173 | |
174 template <class Subclass> | |
175 void AstTraversalVisitor<Subclass>::VisitBreakStatement(BreakStatement* stmt) { | |
176 PROCESS_NODE(stmt); | |
177 } | |
178 | |
179 template <class Subclass> | |
180 void AstTraversalVisitor<Subclass>::VisitReturnStatement( | |
181 ReturnStatement* stmt) { | |
182 PROCESS_NODE(stmt); | |
183 RECURSE(Visit(stmt->expression())); | |
184 } | |
185 | |
186 template <class Subclass> | |
187 void AstTraversalVisitor<Subclass>::VisitWithStatement(WithStatement* stmt) { | |
188 PROCESS_NODE(stmt); | |
189 RECURSE(Visit(stmt->expression())); | |
190 RECURSE(Visit(stmt->statement())); | |
191 } | |
192 | |
193 template <class Subclass> | |
194 void AstTraversalVisitor<Subclass>::VisitSwitchStatement( | |
195 SwitchStatement* stmt) { | |
196 PROCESS_NODE(stmt); | |
197 RECURSE(Visit(stmt->tag())); | |
198 | |
199 ZoneList<CaseClause*>* clauses = stmt->cases(); | |
200 for (int i = 0; i < clauses->length(); ++i) { | |
201 CaseClause* clause = clauses->at(i); | |
202 if (!clause->is_default()) { | |
203 Expression* label = clause->label(); | |
204 RECURSE(Visit(label)); | |
205 } | |
206 ZoneList<Statement*>* stmts = clause->statements(); | |
207 RECURSE(VisitStatements(stmts)); | |
208 } | |
209 } | |
210 | |
211 template <class Subclass> | |
212 void AstTraversalVisitor<Subclass>::VisitCaseClause(CaseClause* clause) { | |
213 UNREACHABLE(); | |
214 } | |
215 | |
216 template <class Subclass> | |
217 void AstTraversalVisitor<Subclass>::VisitDoWhileStatement( | |
218 DoWhileStatement* stmt) { | |
219 PROCESS_NODE(stmt); | |
220 RECURSE(Visit(stmt->body())); | |
221 RECURSE(Visit(stmt->cond())); | |
222 } | |
223 | |
224 template <class Subclass> | |
225 void AstTraversalVisitor<Subclass>::VisitWhileStatement(WhileStatement* stmt) { | |
226 PROCESS_NODE(stmt); | |
227 RECURSE(Visit(stmt->cond())); | |
228 RECURSE(Visit(stmt->body())); | |
229 } | |
230 | |
231 template <class Subclass> | |
232 void AstTraversalVisitor<Subclass>::VisitForStatement(ForStatement* stmt) { | |
233 PROCESS_NODE(stmt); | |
234 if (stmt->init() != NULL) { | |
235 RECURSE(Visit(stmt->init())); | |
236 } | |
237 if (stmt->cond() != NULL) { | |
238 RECURSE(Visit(stmt->cond())); | |
239 } | |
240 if (stmt->next() != NULL) { | |
241 RECURSE(Visit(stmt->next())); | |
242 } | |
243 RECURSE(Visit(stmt->body())); | |
244 } | |
245 | |
246 template <class Subclass> | |
247 void AstTraversalVisitor<Subclass>::VisitForInStatement(ForInStatement* stmt) { | |
248 PROCESS_NODE(stmt); | |
249 RECURSE(Visit(stmt->enumerable())); | |
250 RECURSE(Visit(stmt->body())); | |
251 } | |
252 | |
253 template <class Subclass> | |
254 void AstTraversalVisitor<Subclass>::VisitForOfStatement(ForOfStatement* stmt) { | |
255 PROCESS_NODE(stmt); | |
256 RECURSE(Visit(stmt->assign_iterator())); | |
257 RECURSE(Visit(stmt->next_result())); | |
258 RECURSE(Visit(stmt->result_done())); | |
259 RECURSE(Visit(stmt->assign_each())); | |
260 RECURSE(Visit(stmt->body())); | |
261 } | |
262 | |
263 template <class Subclass> | |
264 void AstTraversalVisitor<Subclass>::VisitTryCatchStatement( | |
265 TryCatchStatement* stmt) { | |
266 PROCESS_NODE(stmt); | |
267 RECURSE(Visit(stmt->try_block())); | |
268 RECURSE(Visit(stmt->catch_block())); | |
269 } | |
270 | |
271 template <class Subclass> | |
272 void AstTraversalVisitor<Subclass>::VisitTryFinallyStatement( | |
273 TryFinallyStatement* stmt) { | |
274 PROCESS_NODE(stmt); | |
275 RECURSE(Visit(stmt->try_block())); | |
276 RECURSE(Visit(stmt->finally_block())); | |
277 } | |
278 | |
279 template <class Subclass> | |
280 void AstTraversalVisitor<Subclass>::VisitDebuggerStatement( | |
281 DebuggerStatement* stmt) { | |
282 PROCESS_NODE(stmt); | |
283 } | |
284 | |
285 template <class Subclass> | |
286 void AstTraversalVisitor<Subclass>::VisitFunctionLiteral( | |
287 FunctionLiteral* expr) { | |
288 PROCESS_EXPRESSION(expr); | |
289 Scope* scope = expr->scope(); | |
290 RECURSE_EXPRESSION(VisitDeclarations(scope->declarations())); | |
291 RECURSE_EXPRESSION(VisitStatements(expr->body())); | |
292 } | |
293 | |
294 template <class Subclass> | |
295 void AstTraversalVisitor<Subclass>::VisitNativeFunctionLiteral( | |
296 NativeFunctionLiteral* expr) { | |
297 PROCESS_EXPRESSION(expr); | |
298 } | |
299 | |
300 template <class Subclass> | |
301 void AstTraversalVisitor<Subclass>::VisitDoExpression(DoExpression* expr) { | |
302 PROCESS_EXPRESSION(expr); | |
303 RECURSE(VisitBlock(expr->block())); | |
304 RECURSE(VisitVariableProxy(expr->result())); | |
305 } | |
306 | |
307 template <class Subclass> | |
308 void AstTraversalVisitor<Subclass>::VisitConditional(Conditional* expr) { | |
309 PROCESS_EXPRESSION(expr); | |
310 RECURSE_EXPRESSION(Visit(expr->condition())); | |
311 RECURSE_EXPRESSION(Visit(expr->then_expression())); | |
312 RECURSE_EXPRESSION(Visit(expr->else_expression())); | |
313 } | |
314 | |
315 template <class Subclass> | |
316 void AstTraversalVisitor<Subclass>::VisitVariableProxy(VariableProxy* expr) { | |
317 PROCESS_EXPRESSION(expr); | |
318 } | |
319 | |
320 template <class Subclass> | |
321 void AstTraversalVisitor<Subclass>::VisitLiteral(Literal* expr) { | |
322 PROCESS_EXPRESSION(expr); | |
323 } | |
324 | |
325 template <class Subclass> | |
326 void AstTraversalVisitor<Subclass>::VisitRegExpLiteral(RegExpLiteral* expr) { | |
327 PROCESS_EXPRESSION(expr); | |
328 } | |
329 | |
330 template <class Subclass> | |
331 void AstTraversalVisitor<Subclass>::VisitObjectLiteral(ObjectLiteral* expr) { | |
332 PROCESS_EXPRESSION(expr); | |
333 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | |
334 for (int i = 0; i < props->length(); ++i) { | |
335 ObjectLiteralProperty* prop = props->at(i); | |
336 RECURSE_EXPRESSION(Visit(prop->key())); | |
337 RECURSE_EXPRESSION(Visit(prop->value())); | |
338 } | |
339 } | |
340 | |
341 template <class Subclass> | |
342 void AstTraversalVisitor<Subclass>::VisitArrayLiteral(ArrayLiteral* expr) { | |
343 PROCESS_EXPRESSION(expr); | |
344 ZoneList<Expression*>* values = expr->values(); | |
345 for (int i = 0; i < values->length(); ++i) { | |
346 Expression* value = values->at(i); | |
347 RECURSE_EXPRESSION(Visit(value)); | |
348 } | |
349 } | |
350 | |
351 template <class Subclass> | |
352 void AstTraversalVisitor<Subclass>::VisitAssignment(Assignment* expr) { | |
353 PROCESS_EXPRESSION(expr); | |
354 RECURSE_EXPRESSION(Visit(expr->target())); | |
355 RECURSE_EXPRESSION(Visit(expr->value())); | |
356 } | |
357 | |
358 template <class Subclass> | |
359 void AstTraversalVisitor<Subclass>::VisitYield(Yield* expr) { | |
360 PROCESS_EXPRESSION(expr); | |
361 RECURSE_EXPRESSION(Visit(expr->generator_object())); | |
362 RECURSE_EXPRESSION(Visit(expr->expression())); | |
363 } | |
364 | |
365 template <class Subclass> | |
366 void AstTraversalVisitor<Subclass>::VisitThrow(Throw* expr) { | |
367 PROCESS_EXPRESSION(expr); | |
368 RECURSE_EXPRESSION(Visit(expr->exception())); | |
369 } | |
370 | |
371 template <class Subclass> | |
372 void AstTraversalVisitor<Subclass>::VisitProperty(Property* expr) { | |
373 PROCESS_EXPRESSION(expr); | |
374 RECURSE_EXPRESSION(Visit(expr->obj())); | |
375 RECURSE_EXPRESSION(Visit(expr->key())); | |
376 } | |
377 | |
378 template <class Subclass> | |
379 void AstTraversalVisitor<Subclass>::VisitCall(Call* expr) { | |
380 PROCESS_EXPRESSION(expr); | |
381 RECURSE_EXPRESSION(Visit(expr->expression())); | |
382 ZoneList<Expression*>* args = expr->arguments(); | |
383 for (int i = 0; i < args->length(); ++i) { | |
384 Expression* arg = args->at(i); | |
385 RECURSE_EXPRESSION(Visit(arg)); | |
386 } | |
387 } | |
388 | |
389 template <class Subclass> | |
390 void AstTraversalVisitor<Subclass>::VisitCallNew(CallNew* expr) { | |
391 PROCESS_EXPRESSION(expr); | |
392 RECURSE_EXPRESSION(Visit(expr->expression())); | |
393 ZoneList<Expression*>* args = expr->arguments(); | |
394 for (int i = 0; i < args->length(); ++i) { | |
395 Expression* arg = args->at(i); | |
396 RECURSE_EXPRESSION(Visit(arg)); | |
397 } | |
398 } | |
399 | |
400 template <class Subclass> | |
401 void AstTraversalVisitor<Subclass>::VisitCallRuntime(CallRuntime* expr) { | |
402 PROCESS_EXPRESSION(expr); | |
403 ZoneList<Expression*>* args = expr->arguments(); | |
404 for (int i = 0; i < args->length(); ++i) { | |
405 Expression* arg = args->at(i); | |
406 RECURSE_EXPRESSION(Visit(arg)); | |
407 } | |
408 } | |
409 | |
410 template <class Subclass> | |
411 void AstTraversalVisitor<Subclass>::VisitUnaryOperation(UnaryOperation* expr) { | |
412 PROCESS_EXPRESSION(expr); | |
413 RECURSE_EXPRESSION(Visit(expr->expression())); | |
414 } | |
415 | |
416 template <class Subclass> | |
417 void AstTraversalVisitor<Subclass>::VisitCountOperation(CountOperation* expr) { | |
418 PROCESS_EXPRESSION(expr); | |
419 RECURSE_EXPRESSION(Visit(expr->expression())); | |
420 } | |
421 | |
422 template <class Subclass> | |
423 void AstTraversalVisitor<Subclass>::VisitBinaryOperation( | |
424 BinaryOperation* expr) { | |
425 PROCESS_EXPRESSION(expr); | |
426 RECURSE_EXPRESSION(Visit(expr->left())); | |
427 RECURSE_EXPRESSION(Visit(expr->right())); | |
428 } | |
429 | |
430 template <class Subclass> | |
431 void AstTraversalVisitor<Subclass>::VisitCompareOperation( | |
432 CompareOperation* expr) { | |
433 PROCESS_EXPRESSION(expr); | |
434 RECURSE_EXPRESSION(Visit(expr->left())); | |
435 RECURSE_EXPRESSION(Visit(expr->right())); | |
436 } | |
437 | |
438 template <class Subclass> | |
439 void AstTraversalVisitor<Subclass>::VisitThisFunction(ThisFunction* expr) { | |
440 PROCESS_EXPRESSION(expr); | |
441 } | |
442 | |
443 template <class Subclass> | |
444 void AstTraversalVisitor<Subclass>::VisitClassLiteral(ClassLiteral* expr) { | |
445 PROCESS_EXPRESSION(expr); | |
446 if (expr->extends() != nullptr) { | |
447 RECURSE_EXPRESSION(Visit(expr->extends())); | |
448 } | |
449 RECURSE_EXPRESSION(Visit(expr->constructor())); | |
450 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | |
451 for (int i = 0; i < props->length(); ++i) { | |
452 ObjectLiteralProperty* prop = props->at(i); | |
453 if (!prop->key()->IsLiteral()) { | |
454 RECURSE_EXPRESSION(Visit(prop->key())); | |
455 } | |
456 RECURSE_EXPRESSION(Visit(prop->value())); | |
457 } | |
458 } | |
459 | |
460 template <class Subclass> | |
461 void AstTraversalVisitor<Subclass>::VisitSpread(Spread* expr) { | |
462 PROCESS_EXPRESSION(expr); | |
463 RECURSE_EXPRESSION(Visit(expr->expression())); | |
464 } | |
465 | |
466 template <class Subclass> | |
467 void AstTraversalVisitor<Subclass>::VisitEmptyParentheses( | |
468 EmptyParentheses* expr) { | |
469 PROCESS_EXPRESSION(expr); | |
470 } | |
471 | |
472 template <class Subclass> | |
473 void AstTraversalVisitor<Subclass>::VisitSuperPropertyReference( | |
474 SuperPropertyReference* expr) { | |
475 PROCESS_EXPRESSION(expr); | |
476 RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var())); | |
477 RECURSE_EXPRESSION(Visit(expr->home_object())); | |
478 } | |
479 | |
480 template <class Subclass> | |
481 void AstTraversalVisitor<Subclass>::VisitSuperCallReference( | |
482 SuperCallReference* expr) { | |
483 PROCESS_EXPRESSION(expr); | |
484 RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var())); | |
485 RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var())); | |
486 RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var())); | |
487 } | |
488 | |
489 template <class Subclass> | |
490 void AstTraversalVisitor<Subclass>::VisitRewritableExpression( | |
491 RewritableExpression* expr) { | |
492 PROCESS_EXPRESSION(expr); | |
493 RECURSE(Visit(expr->expression())); | |
494 } | |
495 | |
496 #undef PROCESS_NODE | |
497 #undef PROCESS_EXPRESSION | |
498 #undef RECURSE_EXPRESSION | |
499 #undef RECURSE | |
500 | |
501 } // namespace internal | |
502 } // namespace v8 | |
503 | |
504 #endif // V8_AST_AST_TRAVERSAL_VISITOR_H_ | |
OLD | NEW |