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