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
Run()34 void Run() {
35 DCHECK_NOT_NULL(root_);
36 Visit(root_);
37 }
38
VisitNode(AstNode * node)39 bool VisitNode(AstNode* node) { return true; }
VisitExpression(Expression * node)40 bool VisitExpression(Expression* node) { return true; }
41
42 // Iteration left-to-right.
43 void VisitDeclarations(Declaration::List* declarations);
44 void VisitStatements(ZoneList<Statement*>* statements);
45
46 // Individual nodes
47 #define DECLARE_VISIT(type) void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)48 AST_NODE_LIST(DECLARE_VISIT)
49 #undef DECLARE_VISIT
50
51 protected:
52 int depth() const { return depth_; }
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>
AstTraversalVisitor(Isolate * isolate,AstNode * root)92 AstTraversalVisitor<Subclass>::AstTraversalVisitor(Isolate* isolate,
93 AstNode* root)
94 : root_(root), depth_(0) {
95 InitializeAstVisitor(isolate);
96 }
97
98 template <class Subclass>
AstTraversalVisitor(uintptr_t stack_limit,AstNode * root)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>
VisitDeclarations(Declaration::List * decls)106 void AstTraversalVisitor<Subclass>::VisitDeclarations(
107 Declaration::List* decls) {
108 for (Declaration* decl : *decls) {
109 RECURSE(Visit(decl));
110 }
111 }
112
113 template <class Subclass>
VisitStatements(ZoneList<Statement * > * stmts)114 void AstTraversalVisitor<Subclass>::VisitStatements(
115 ZoneList<Statement*>* stmts) {
116 for (int i = 0; i < stmts->length(); ++i) {
117 Statement* stmt = stmts->at(i);
118 RECURSE(Visit(stmt));
119 if (stmt->IsJump()) break;
120 }
121 }
122
123 template <class Subclass>
VisitVariableDeclaration(VariableDeclaration * decl)124 void AstTraversalVisitor<Subclass>::VisitVariableDeclaration(
125 VariableDeclaration* decl) {
126 PROCESS_NODE(decl);
127 }
128
129 template <class Subclass>
VisitFunctionDeclaration(FunctionDeclaration * decl)130 void AstTraversalVisitor<Subclass>::VisitFunctionDeclaration(
131 FunctionDeclaration* decl) {
132 PROCESS_NODE(decl);
133 RECURSE(Visit(decl->fun()));
134 }
135
136 template <class Subclass>
VisitBlock(Block * stmt)137 void AstTraversalVisitor<Subclass>::VisitBlock(Block* stmt) {
138 PROCESS_NODE(stmt);
139 RECURSE(VisitStatements(stmt->statements()));
140 }
141
142 template <class Subclass>
VisitExpressionStatement(ExpressionStatement * stmt)143 void AstTraversalVisitor<Subclass>::VisitExpressionStatement(
144 ExpressionStatement* stmt) {
145 PROCESS_NODE(stmt);
146 RECURSE(Visit(stmt->expression()));
147 }
148
149 template <class Subclass>
VisitEmptyStatement(EmptyStatement * stmt)150 void AstTraversalVisitor<Subclass>::VisitEmptyStatement(EmptyStatement* stmt) {}
151
152 template <class Subclass>
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * stmt)153 void AstTraversalVisitor<Subclass>::VisitSloppyBlockFunctionStatement(
154 SloppyBlockFunctionStatement* stmt) {
155 PROCESS_NODE(stmt);
156 RECURSE(Visit(stmt->statement()));
157 }
158
159 template <class Subclass>
VisitIfStatement(IfStatement * stmt)160 void AstTraversalVisitor<Subclass>::VisitIfStatement(IfStatement* stmt) {
161 PROCESS_NODE(stmt);
162 RECURSE(Visit(stmt->condition()));
163 RECURSE(Visit(stmt->then_statement()));
164 RECURSE(Visit(stmt->else_statement()));
165 }
166
167 template <class Subclass>
VisitContinueStatement(ContinueStatement * stmt)168 void AstTraversalVisitor<Subclass>::VisitContinueStatement(
169 ContinueStatement* stmt) {
170 PROCESS_NODE(stmt);
171 }
172
173 template <class Subclass>
VisitBreakStatement(BreakStatement * stmt)174 void AstTraversalVisitor<Subclass>::VisitBreakStatement(BreakStatement* stmt) {
175 PROCESS_NODE(stmt);
176 }
177
178 template <class Subclass>
VisitReturnStatement(ReturnStatement * stmt)179 void AstTraversalVisitor<Subclass>::VisitReturnStatement(
180 ReturnStatement* stmt) {
181 PROCESS_NODE(stmt);
182 RECURSE(Visit(stmt->expression()));
183 }
184
185 template <class Subclass>
VisitWithStatement(WithStatement * stmt)186 void AstTraversalVisitor<Subclass>::VisitWithStatement(WithStatement* stmt) {
187 PROCESS_NODE(stmt);
188 RECURSE(Visit(stmt->expression()));
189 RECURSE(Visit(stmt->statement()));
190 }
191
192 template <class Subclass>
VisitSwitchStatement(SwitchStatement * stmt)193 void AstTraversalVisitor<Subclass>::VisitSwitchStatement(
194 SwitchStatement* stmt) {
195 PROCESS_NODE(stmt);
196 RECURSE(Visit(stmt->tag()));
197
198 ZoneList<CaseClause*>* clauses = stmt->cases();
199 for (int i = 0; i < clauses->length(); ++i) {
200 CaseClause* clause = clauses->at(i);
201 if (!clause->is_default()) {
202 Expression* label = clause->label();
203 RECURSE(Visit(label));
204 }
205 ZoneList<Statement*>* stmts = clause->statements();
206 RECURSE(VisitStatements(stmts));
207 }
208 }
209
210 template <class Subclass>
VisitCaseClause(CaseClause * clause)211 void AstTraversalVisitor<Subclass>::VisitCaseClause(CaseClause* clause) {
212 UNREACHABLE();
213 }
214
215 template <class Subclass>
VisitDoWhileStatement(DoWhileStatement * stmt)216 void AstTraversalVisitor<Subclass>::VisitDoWhileStatement(
217 DoWhileStatement* stmt) {
218 PROCESS_NODE(stmt);
219 RECURSE(Visit(stmt->body()));
220 RECURSE(Visit(stmt->cond()));
221 }
222
223 template <class Subclass>
VisitWhileStatement(WhileStatement * stmt)224 void AstTraversalVisitor<Subclass>::VisitWhileStatement(WhileStatement* stmt) {
225 PROCESS_NODE(stmt);
226 RECURSE(Visit(stmt->cond()));
227 RECURSE(Visit(stmt->body()));
228 }
229
230 template <class Subclass>
VisitForStatement(ForStatement * stmt)231 void AstTraversalVisitor<Subclass>::VisitForStatement(ForStatement* stmt) {
232 PROCESS_NODE(stmt);
233 if (stmt->init() != NULL) {
234 RECURSE(Visit(stmt->init()));
235 }
236 if (stmt->cond() != NULL) {
237 RECURSE(Visit(stmt->cond()));
238 }
239 if (stmt->next() != NULL) {
240 RECURSE(Visit(stmt->next()));
241 }
242 RECURSE(Visit(stmt->body()));
243 }
244
245 template <class Subclass>
VisitForInStatement(ForInStatement * stmt)246 void AstTraversalVisitor<Subclass>::VisitForInStatement(ForInStatement* stmt) {
247 PROCESS_NODE(stmt);
248 RECURSE(Visit(stmt->enumerable()));
249 RECURSE(Visit(stmt->body()));
250 }
251
252 template <class Subclass>
VisitForOfStatement(ForOfStatement * stmt)253 void AstTraversalVisitor<Subclass>::VisitForOfStatement(ForOfStatement* stmt) {
254 PROCESS_NODE(stmt);
255 RECURSE(Visit(stmt->assign_iterator()));
256 RECURSE(Visit(stmt->next_result()));
257 RECURSE(Visit(stmt->result_done()));
258 RECURSE(Visit(stmt->assign_each()));
259 RECURSE(Visit(stmt->body()));
260 }
261
262 template <class Subclass>
VisitTryCatchStatement(TryCatchStatement * stmt)263 void AstTraversalVisitor<Subclass>::VisitTryCatchStatement(
264 TryCatchStatement* stmt) {
265 PROCESS_NODE(stmt);
266 RECURSE(Visit(stmt->try_block()));
267 RECURSE(Visit(stmt->catch_block()));
268 }
269
270 template <class Subclass>
VisitTryFinallyStatement(TryFinallyStatement * stmt)271 void AstTraversalVisitor<Subclass>::VisitTryFinallyStatement(
272 TryFinallyStatement* stmt) {
273 PROCESS_NODE(stmt);
274 RECURSE(Visit(stmt->try_block()));
275 RECURSE(Visit(stmt->finally_block()));
276 }
277
278 template <class Subclass>
VisitDebuggerStatement(DebuggerStatement * stmt)279 void AstTraversalVisitor<Subclass>::VisitDebuggerStatement(
280 DebuggerStatement* stmt) {
281 PROCESS_NODE(stmt);
282 }
283
284 template <class Subclass>
VisitFunctionLiteral(FunctionLiteral * expr)285 void AstTraversalVisitor<Subclass>::VisitFunctionLiteral(
286 FunctionLiteral* expr) {
287 PROCESS_EXPRESSION(expr);
288 DeclarationScope* scope = expr->scope();
289 RECURSE_EXPRESSION(VisitDeclarations(scope->declarations()));
290 // A lazily parsed function literal won't have a body.
291 if (expr->scope()->is_lazily_parsed()) return;
292 RECURSE_EXPRESSION(VisitStatements(expr->body()));
293 }
294
295 template <class Subclass>
VisitNativeFunctionLiteral(NativeFunctionLiteral * expr)296 void AstTraversalVisitor<Subclass>::VisitNativeFunctionLiteral(
297 NativeFunctionLiteral* expr) {
298 PROCESS_EXPRESSION(expr);
299 }
300
301 template <class Subclass>
VisitDoExpression(DoExpression * expr)302 void AstTraversalVisitor<Subclass>::VisitDoExpression(DoExpression* expr) {
303 PROCESS_EXPRESSION(expr);
304 RECURSE(VisitBlock(expr->block()));
305 RECURSE(VisitVariableProxy(expr->result()));
306 }
307
308 template <class Subclass>
VisitConditional(Conditional * expr)309 void AstTraversalVisitor<Subclass>::VisitConditional(Conditional* expr) {
310 PROCESS_EXPRESSION(expr);
311 RECURSE_EXPRESSION(Visit(expr->condition()));
312 RECURSE_EXPRESSION(Visit(expr->then_expression()));
313 RECURSE_EXPRESSION(Visit(expr->else_expression()));
314 }
315
316 template <class Subclass>
VisitVariableProxy(VariableProxy * expr)317 void AstTraversalVisitor<Subclass>::VisitVariableProxy(VariableProxy* expr) {
318 PROCESS_EXPRESSION(expr);
319 }
320
321 template <class Subclass>
VisitLiteral(Literal * expr)322 void AstTraversalVisitor<Subclass>::VisitLiteral(Literal* expr) {
323 PROCESS_EXPRESSION(expr);
324 }
325
326 template <class Subclass>
VisitRegExpLiteral(RegExpLiteral * expr)327 void AstTraversalVisitor<Subclass>::VisitRegExpLiteral(RegExpLiteral* expr) {
328 PROCESS_EXPRESSION(expr);
329 }
330
331 template <class Subclass>
VisitObjectLiteral(ObjectLiteral * expr)332 void AstTraversalVisitor<Subclass>::VisitObjectLiteral(ObjectLiteral* expr) {
333 PROCESS_EXPRESSION(expr);
334 ZoneList<ObjectLiteralProperty*>* props = expr->properties();
335 for (int i = 0; i < props->length(); ++i) {
336 ObjectLiteralProperty* prop = props->at(i);
337 RECURSE_EXPRESSION(Visit(prop->key()));
338 RECURSE_EXPRESSION(Visit(prop->value()));
339 }
340 }
341
342 template <class Subclass>
VisitArrayLiteral(ArrayLiteral * expr)343 void AstTraversalVisitor<Subclass>::VisitArrayLiteral(ArrayLiteral* expr) {
344 PROCESS_EXPRESSION(expr);
345 ZoneList<Expression*>* values = expr->values();
346 for (int i = 0; i < values->length(); ++i) {
347 Expression* value = values->at(i);
348 RECURSE_EXPRESSION(Visit(value));
349 }
350 }
351
352 template <class Subclass>
VisitAssignment(Assignment * expr)353 void AstTraversalVisitor<Subclass>::VisitAssignment(Assignment* expr) {
354 PROCESS_EXPRESSION(expr);
355 RECURSE_EXPRESSION(Visit(expr->target()));
356 RECURSE_EXPRESSION(Visit(expr->value()));
357 }
358
359 template <class Subclass>
VisitYield(Yield * expr)360 void AstTraversalVisitor<Subclass>::VisitYield(Yield* expr) {
361 PROCESS_EXPRESSION(expr);
362 RECURSE_EXPRESSION(Visit(expr->generator_object()));
363 RECURSE_EXPRESSION(Visit(expr->expression()));
364 }
365
366 template <class Subclass>
VisitThrow(Throw * expr)367 void AstTraversalVisitor<Subclass>::VisitThrow(Throw* expr) {
368 PROCESS_EXPRESSION(expr);
369 RECURSE_EXPRESSION(Visit(expr->exception()));
370 }
371
372 template <class Subclass>
VisitProperty(Property * expr)373 void AstTraversalVisitor<Subclass>::VisitProperty(Property* expr) {
374 PROCESS_EXPRESSION(expr);
375 RECURSE_EXPRESSION(Visit(expr->obj()));
376 RECURSE_EXPRESSION(Visit(expr->key()));
377 }
378
379 template <class Subclass>
VisitCall(Call * expr)380 void AstTraversalVisitor<Subclass>::VisitCall(Call* expr) {
381 PROCESS_EXPRESSION(expr);
382 RECURSE_EXPRESSION(Visit(expr->expression()));
383 ZoneList<Expression*>* args = expr->arguments();
384 for (int i = 0; i < args->length(); ++i) {
385 Expression* arg = args->at(i);
386 RECURSE_EXPRESSION(Visit(arg));
387 }
388 }
389
390 template <class Subclass>
VisitCallNew(CallNew * expr)391 void AstTraversalVisitor<Subclass>::VisitCallNew(CallNew* expr) {
392 PROCESS_EXPRESSION(expr);
393 RECURSE_EXPRESSION(Visit(expr->expression()));
394 ZoneList<Expression*>* args = expr->arguments();
395 for (int i = 0; i < args->length(); ++i) {
396 Expression* arg = args->at(i);
397 RECURSE_EXPRESSION(Visit(arg));
398 }
399 }
400
401 template <class Subclass>
VisitCallRuntime(CallRuntime * expr)402 void AstTraversalVisitor<Subclass>::VisitCallRuntime(CallRuntime* expr) {
403 PROCESS_EXPRESSION(expr);
404 ZoneList<Expression*>* args = expr->arguments();
405 for (int i = 0; i < args->length(); ++i) {
406 Expression* arg = args->at(i);
407 RECURSE_EXPRESSION(Visit(arg));
408 }
409 }
410
411 template <class Subclass>
VisitUnaryOperation(UnaryOperation * expr)412 void AstTraversalVisitor<Subclass>::VisitUnaryOperation(UnaryOperation* expr) {
413 PROCESS_EXPRESSION(expr);
414 RECURSE_EXPRESSION(Visit(expr->expression()));
415 }
416
417 template <class Subclass>
VisitCountOperation(CountOperation * expr)418 void AstTraversalVisitor<Subclass>::VisitCountOperation(CountOperation* expr) {
419 PROCESS_EXPRESSION(expr);
420 RECURSE_EXPRESSION(Visit(expr->expression()));
421 }
422
423 template <class Subclass>
VisitBinaryOperation(BinaryOperation * expr)424 void AstTraversalVisitor<Subclass>::VisitBinaryOperation(
425 BinaryOperation* expr) {
426 PROCESS_EXPRESSION(expr);
427 RECURSE_EXPRESSION(Visit(expr->left()));
428 RECURSE_EXPRESSION(Visit(expr->right()));
429 }
430
431 template <class Subclass>
VisitCompareOperation(CompareOperation * expr)432 void AstTraversalVisitor<Subclass>::VisitCompareOperation(
433 CompareOperation* expr) {
434 PROCESS_EXPRESSION(expr);
435 RECURSE_EXPRESSION(Visit(expr->left()));
436 RECURSE_EXPRESSION(Visit(expr->right()));
437 }
438
439 template <class Subclass>
VisitThisFunction(ThisFunction * expr)440 void AstTraversalVisitor<Subclass>::VisitThisFunction(ThisFunction* expr) {
441 PROCESS_EXPRESSION(expr);
442 }
443
444 template <class Subclass>
VisitClassLiteral(ClassLiteral * expr)445 void AstTraversalVisitor<Subclass>::VisitClassLiteral(ClassLiteral* expr) {
446 PROCESS_EXPRESSION(expr);
447 if (expr->extends() != nullptr) {
448 RECURSE_EXPRESSION(Visit(expr->extends()));
449 }
450 RECURSE_EXPRESSION(Visit(expr->constructor()));
451 ZoneList<ClassLiteralProperty*>* props = expr->properties();
452 for (int i = 0; i < props->length(); ++i) {
453 ClassLiteralProperty* prop = props->at(i);
454 if (!prop->key()->IsLiteral()) {
455 RECURSE_EXPRESSION(Visit(prop->key()));
456 }
457 RECURSE_EXPRESSION(Visit(prop->value()));
458 }
459 }
460
461 template <class Subclass>
VisitSpread(Spread * expr)462 void AstTraversalVisitor<Subclass>::VisitSpread(Spread* expr) {
463 PROCESS_EXPRESSION(expr);
464 RECURSE_EXPRESSION(Visit(expr->expression()));
465 }
466
467 template <class Subclass>
VisitEmptyParentheses(EmptyParentheses * expr)468 void AstTraversalVisitor<Subclass>::VisitEmptyParentheses(
469 EmptyParentheses* expr) {
470 PROCESS_EXPRESSION(expr);
471 }
472
473 template <class Subclass>
VisitSuperPropertyReference(SuperPropertyReference * expr)474 void AstTraversalVisitor<Subclass>::VisitSuperPropertyReference(
475 SuperPropertyReference* expr) {
476 PROCESS_EXPRESSION(expr);
477 RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
478 RECURSE_EXPRESSION(Visit(expr->home_object()));
479 }
480
481 template <class Subclass>
VisitSuperCallReference(SuperCallReference * expr)482 void AstTraversalVisitor<Subclass>::VisitSuperCallReference(
483 SuperCallReference* expr) {
484 PROCESS_EXPRESSION(expr);
485 RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
486 RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var()));
487 RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var()));
488 }
489
490 template <class Subclass>
VisitRewritableExpression(RewritableExpression * expr)491 void AstTraversalVisitor<Subclass>::VisitRewritableExpression(
492 RewritableExpression* expr) {
493 PROCESS_EXPRESSION(expr);
494 RECURSE(Visit(expr->expression()));
495 }
496
497 #undef PROCESS_NODE
498 #undef PROCESS_EXPRESSION
499 #undef RECURSE_EXPRESSION
500 #undef RECURSE
501
502 } // namespace internal
503 } // namespace v8
504
505 #endif // V8_AST_AST_TRAVERSAL_VISITOR_H_
506