V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
ast-traversal-visitor.h
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; }
41 
42  // Iteration left-to-right.
43  void VisitDeclarations(Declaration::List* declarations);
44  void VisitStatements(const ZonePtrList<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() 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>
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  Declaration::List* decls) {
108  for (Declaration* decl : *decls) {
109  RECURSE(Visit(decl));
110  }
111 }
112 
113 template <class Subclass>
114 void AstTraversalVisitor<Subclass>::VisitStatements(
115  const ZonePtrList<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>
124 void AstTraversalVisitor<Subclass>::VisitVariableDeclaration(
125  VariableDeclaration* decl) {
126  PROCESS_NODE(decl);
127 }
128 
129 template <class Subclass>
130 void AstTraversalVisitor<Subclass>::VisitFunctionDeclaration(
131  FunctionDeclaration* decl) {
132  PROCESS_NODE(decl);
133  RECURSE(Visit(decl->fun()));
134 }
135 
136 template <class Subclass>
137 void AstTraversalVisitor<Subclass>::VisitBlock(Block* stmt) {
138  PROCESS_NODE(stmt);
139  if (stmt->scope() != nullptr) {
140  RECURSE_EXPRESSION(VisitDeclarations(stmt->scope()->declarations()));
141  }
142  RECURSE(VisitStatements(stmt->statements()));
143 }
144 
145 template <class Subclass>
146 void AstTraversalVisitor<Subclass>::VisitExpressionStatement(
147  ExpressionStatement* stmt) {
148  PROCESS_NODE(stmt);
149  RECURSE(Visit(stmt->expression()));
150 }
151 
152 template <class Subclass>
153 void AstTraversalVisitor<Subclass>::VisitEmptyStatement(EmptyStatement* stmt) {}
154 
155 template <class Subclass>
156 void AstTraversalVisitor<Subclass>::VisitSloppyBlockFunctionStatement(
157  SloppyBlockFunctionStatement* stmt) {
158  PROCESS_NODE(stmt);
159  RECURSE(Visit(stmt->statement()));
160 }
161 
162 template <class Subclass>
163 void AstTraversalVisitor<Subclass>::VisitIfStatement(IfStatement* stmt) {
164  PROCESS_NODE(stmt);
165  RECURSE(Visit(stmt->condition()));
166  RECURSE(Visit(stmt->then_statement()));
167  RECURSE(Visit(stmt->else_statement()));
168 }
169 
170 template <class Subclass>
171 void AstTraversalVisitor<Subclass>::VisitContinueStatement(
172  ContinueStatement* stmt) {
173  PROCESS_NODE(stmt);
174 }
175 
176 template <class Subclass>
177 void AstTraversalVisitor<Subclass>::VisitBreakStatement(BreakStatement* stmt) {
178  PROCESS_NODE(stmt);
179 }
180 
181 template <class Subclass>
182 void AstTraversalVisitor<Subclass>::VisitReturnStatement(
183  ReturnStatement* stmt) {
184  PROCESS_NODE(stmt);
185  RECURSE(Visit(stmt->expression()));
186 }
187 
188 template <class Subclass>
189 void AstTraversalVisitor<Subclass>::VisitWithStatement(WithStatement* stmt) {
190  PROCESS_NODE(stmt);
191  RECURSE(Visit(stmt->expression()));
192  RECURSE(Visit(stmt->statement()));
193 }
194 
195 template <class Subclass>
196 void AstTraversalVisitor<Subclass>::VisitSwitchStatement(
197  SwitchStatement* stmt) {
198  PROCESS_NODE(stmt);
199  RECURSE(Visit(stmt->tag()));
200 
201  ZonePtrList<CaseClause>* clauses = stmt->cases();
202  for (int i = 0; i < clauses->length(); ++i) {
203  CaseClause* clause = clauses->at(i);
204  if (!clause->is_default()) {
205  Expression* label = clause->label();
206  RECURSE(Visit(label));
207  }
208  const ZonePtrList<Statement>* stmts = clause->statements();
209  RECURSE(VisitStatements(stmts));
210  }
211 }
212 
213 template <class Subclass>
214 void AstTraversalVisitor<Subclass>::VisitDoWhileStatement(
215  DoWhileStatement* stmt) {
216  PROCESS_NODE(stmt);
217  RECURSE(Visit(stmt->body()));
218  RECURSE(Visit(stmt->cond()));
219 }
220 
221 template <class Subclass>
222 void AstTraversalVisitor<Subclass>::VisitWhileStatement(WhileStatement* stmt) {
223  PROCESS_NODE(stmt);
224  RECURSE(Visit(stmt->cond()));
225  RECURSE(Visit(stmt->body()));
226 }
227 
228 template <class Subclass>
229 void AstTraversalVisitor<Subclass>::VisitForStatement(ForStatement* stmt) {
230  PROCESS_NODE(stmt);
231  if (stmt->init() != nullptr) {
232  RECURSE(Visit(stmt->init()));
233  }
234  if (stmt->cond() != nullptr) {
235  RECURSE(Visit(stmt->cond()));
236  }
237  if (stmt->next() != nullptr) {
238  RECURSE(Visit(stmt->next()));
239  }
240  RECURSE(Visit(stmt->body()));
241 }
242 
243 template <class Subclass>
244 void AstTraversalVisitor<Subclass>::VisitForInStatement(ForInStatement* stmt) {
245  PROCESS_NODE(stmt);
246  RECURSE(Visit(stmt->each()));
247  RECURSE(Visit(stmt->enumerable()));
248  RECURSE(Visit(stmt->body()));
249 }
250 
251 template <class Subclass>
252 void AstTraversalVisitor<Subclass>::VisitForOfStatement(ForOfStatement* stmt) {
253  PROCESS_NODE(stmt);
254  RECURSE(Visit(stmt->assign_iterator()));
255  RECURSE(Visit(stmt->next_result()));
256  RECURSE(Visit(stmt->result_done()));
257  RECURSE(Visit(stmt->assign_each()));
258  RECURSE(Visit(stmt->body()));
259 }
260 
261 template <class Subclass>
262 void AstTraversalVisitor<Subclass>::VisitTryCatchStatement(
263  TryCatchStatement* stmt) {
264  PROCESS_NODE(stmt);
265  RECURSE(Visit(stmt->try_block()));
266  RECURSE(Visit(stmt->catch_block()));
267 }
268 
269 template <class Subclass>
270 void AstTraversalVisitor<Subclass>::VisitTryFinallyStatement(
271  TryFinallyStatement* stmt) {
272  PROCESS_NODE(stmt);
273  RECURSE(Visit(stmt->try_block()));
274  RECURSE(Visit(stmt->finally_block()));
275 }
276 
277 template <class Subclass>
278 void AstTraversalVisitor<Subclass>::VisitDebuggerStatement(
279  DebuggerStatement* stmt) {
280  PROCESS_NODE(stmt);
281 }
282 
283 template <class Subclass>
284 void AstTraversalVisitor<Subclass>::VisitFunctionLiteral(
285  FunctionLiteral* expr) {
286  PROCESS_EXPRESSION(expr);
287  DeclarationScope* scope = expr->scope();
288  RECURSE_EXPRESSION(VisitDeclarations(scope->declarations()));
289  // A lazily parsed function literal won't have a body.
290  if (expr->scope()->was_lazily_parsed()) return;
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  const ZonePtrList<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  const ZonePtrList<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>::VisitCompoundAssignment(
360  CompoundAssignment* expr) {
361  VisitAssignment(expr);
362 }
363 
364 template <class Subclass>
365 void AstTraversalVisitor<Subclass>::VisitYield(Yield* expr) {
366  PROCESS_EXPRESSION(expr);
367  RECURSE_EXPRESSION(Visit(expr->expression()));
368 }
369 
370 template <class Subclass>
371 void AstTraversalVisitor<Subclass>::VisitYieldStar(YieldStar* expr) {
372  PROCESS_EXPRESSION(expr);
373  RECURSE_EXPRESSION(Visit(expr->expression()));
374 }
375 
376 template <class Subclass>
377 void AstTraversalVisitor<Subclass>::VisitAwait(Await* expr) {
378  PROCESS_EXPRESSION(expr);
379  RECURSE_EXPRESSION(Visit(expr->expression()));
380 }
381 
382 template <class Subclass>
383 void AstTraversalVisitor<Subclass>::VisitThrow(Throw* expr) {
384  PROCESS_EXPRESSION(expr);
385  RECURSE_EXPRESSION(Visit(expr->exception()));
386 }
387 
388 template <class Subclass>
389 void AstTraversalVisitor<Subclass>::VisitProperty(Property* expr) {
390  PROCESS_EXPRESSION(expr);
391  RECURSE_EXPRESSION(Visit(expr->obj()));
392  RECURSE_EXPRESSION(Visit(expr->key()));
393 }
394 
395 template <class Subclass>
396 void AstTraversalVisitor<Subclass>::VisitResolvedProperty(
397  ResolvedProperty* expr) {
398  PROCESS_EXPRESSION(expr);
399  RECURSE_EXPRESSION(VisitVariableProxy(expr->object()));
400  RECURSE_EXPRESSION(VisitVariableProxy(expr->property()));
401 }
402 
403 template <class Subclass>
404 void AstTraversalVisitor<Subclass>::VisitCall(Call* expr) {
405  PROCESS_EXPRESSION(expr);
406  RECURSE_EXPRESSION(Visit(expr->expression()));
407  const ZonePtrList<Expression>* args = expr->arguments();
408  for (int i = 0; i < args->length(); ++i) {
409  Expression* arg = args->at(i);
410  RECURSE_EXPRESSION(Visit(arg));
411  }
412 }
413 
414 template <class Subclass>
415 void AstTraversalVisitor<Subclass>::VisitCallNew(CallNew* expr) {
416  PROCESS_EXPRESSION(expr);
417  RECURSE_EXPRESSION(Visit(expr->expression()));
418  const ZonePtrList<Expression>* args = expr->arguments();
419  for (int i = 0; i < args->length(); ++i) {
420  Expression* arg = args->at(i);
421  RECURSE_EXPRESSION(Visit(arg));
422  }
423 }
424 
425 template <class Subclass>
426 void AstTraversalVisitor<Subclass>::VisitCallRuntime(CallRuntime* expr) {
427  PROCESS_EXPRESSION(expr);
428  const ZonePtrList<Expression>* args = expr->arguments();
429  for (int i = 0; i < args->length(); ++i) {
430  Expression* arg = args->at(i);
431  RECURSE_EXPRESSION(Visit(arg));
432  }
433 }
434 
435 template <class Subclass>
436 void AstTraversalVisitor<Subclass>::VisitUnaryOperation(UnaryOperation* expr) {
437  PROCESS_EXPRESSION(expr);
438  RECURSE_EXPRESSION(Visit(expr->expression()));
439 }
440 
441 template <class Subclass>
442 void AstTraversalVisitor<Subclass>::VisitCountOperation(CountOperation* expr) {
443  PROCESS_EXPRESSION(expr);
444  RECURSE_EXPRESSION(Visit(expr->expression()));
445 }
446 
447 template <class Subclass>
448 void AstTraversalVisitor<Subclass>::VisitBinaryOperation(
449  BinaryOperation* expr) {
450  PROCESS_EXPRESSION(expr);
451  RECURSE_EXPRESSION(Visit(expr->left()));
452  RECURSE_EXPRESSION(Visit(expr->right()));
453 }
454 
455 template <class Subclass>
456 void AstTraversalVisitor<Subclass>::VisitNaryOperation(NaryOperation* expr) {
457  PROCESS_EXPRESSION(expr);
458  RECURSE_EXPRESSION(Visit(expr->first()));
459  for (size_t i = 0; i < expr->subsequent_length(); ++i) {
460  RECURSE_EXPRESSION(Visit(expr->subsequent(i)));
461  }
462 }
463 
464 template <class Subclass>
465 void AstTraversalVisitor<Subclass>::VisitCompareOperation(
466  CompareOperation* expr) {
467  PROCESS_EXPRESSION(expr);
468  RECURSE_EXPRESSION(Visit(expr->left()));
469  RECURSE_EXPRESSION(Visit(expr->right()));
470 }
471 
472 template <class Subclass>
473 void AstTraversalVisitor<Subclass>::VisitThisFunction(ThisFunction* expr) {
474  PROCESS_EXPRESSION(expr);
475 }
476 
477 template <class Subclass>
478 void AstTraversalVisitor<Subclass>::VisitClassLiteral(ClassLiteral* expr) {
479  PROCESS_EXPRESSION(expr);
480  if (expr->extends() != nullptr) {
481  RECURSE_EXPRESSION(Visit(expr->extends()));
482  }
483  RECURSE_EXPRESSION(Visit(expr->constructor()));
484  if (expr->static_fields_initializer() != nullptr) {
485  RECURSE_EXPRESSION(Visit(expr->static_fields_initializer()));
486  }
487  if (expr->instance_members_initializer_function() != nullptr) {
488  RECURSE_EXPRESSION(Visit(expr->instance_members_initializer_function()));
489  }
490  ZonePtrList<ClassLiteral::Property>* props = expr->properties();
491  for (int i = 0; i < props->length(); ++i) {
492  ClassLiteralProperty* prop = props->at(i);
493  if (!prop->key()->IsLiteral()) {
494  RECURSE_EXPRESSION(Visit(prop->key()));
495  }
496  RECURSE_EXPRESSION(Visit(prop->value()));
497  }
498 }
499 
500 template <class Subclass>
501 void AstTraversalVisitor<Subclass>::VisitInitializeClassMembersStatement(
502  InitializeClassMembersStatement* stmt) {
503  PROCESS_NODE(stmt);
504  ZonePtrList<ClassLiteral::Property>* props = stmt->fields();
505  for (int i = 0; i < props->length(); ++i) {
506  ClassLiteralProperty* prop = props->at(i);
507  if (!prop->key()->IsLiteral()) {
508  RECURSE(Visit(prop->key()));
509  }
510  RECURSE(Visit(prop->value()));
511  }
512 }
513 
514 template <class Subclass>
515 void AstTraversalVisitor<Subclass>::VisitSpread(Spread* expr) {
516  PROCESS_EXPRESSION(expr);
517  RECURSE_EXPRESSION(Visit(expr->expression()));
518 }
519 
520 template <class Subclass>
521 void AstTraversalVisitor<Subclass>::VisitStoreInArrayLiteral(
522  StoreInArrayLiteral* expr) {
523  PROCESS_EXPRESSION(expr);
524  RECURSE_EXPRESSION(Visit(expr->array()));
525  RECURSE_EXPRESSION(Visit(expr->index()));
526  RECURSE_EXPRESSION(Visit(expr->value()));
527 }
528 
529 template <class Subclass>
530 void AstTraversalVisitor<Subclass>::VisitEmptyParentheses(
531  EmptyParentheses* expr) {
532  PROCESS_EXPRESSION(expr);
533 }
534 
535 template <class Subclass>
536 void AstTraversalVisitor<Subclass>::VisitGetIterator(GetIterator* expr) {
537  PROCESS_EXPRESSION(expr);
538  RECURSE_EXPRESSION(Visit(expr->iterable()));
539 }
540 
541 template <class Subclass>
542 void AstTraversalVisitor<Subclass>::VisitGetTemplateObject(
543  GetTemplateObject* expr) {
544  PROCESS_EXPRESSION(expr);
545 }
546 
547 template <class Subclass>
548 void AstTraversalVisitor<Subclass>::VisitTemplateLiteral(
549  TemplateLiteral* expr) {
550  PROCESS_EXPRESSION(expr);
551  for (Expression* sub : *expr->substitutions()) {
552  RECURSE_EXPRESSION(Visit(sub));
553  }
554 }
555 
556 template <class Subclass>
557 void AstTraversalVisitor<Subclass>::VisitImportCallExpression(
558  ImportCallExpression* expr) {
559  PROCESS_EXPRESSION(expr);
560  RECURSE_EXPRESSION(Visit(expr->argument()));
561 }
562 
563 template <class Subclass>
564 void AstTraversalVisitor<Subclass>::VisitSuperPropertyReference(
565  SuperPropertyReference* expr) {
566  PROCESS_EXPRESSION(expr);
567  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
568  RECURSE_EXPRESSION(Visit(expr->home_object()));
569 }
570 
571 template <class Subclass>
572 void AstTraversalVisitor<Subclass>::VisitSuperCallReference(
573  SuperCallReference* expr) {
574  PROCESS_EXPRESSION(expr);
575  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
576  RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var()));
577  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var()));
578 }
579 
580 template <class Subclass>
581 void AstTraversalVisitor<Subclass>::VisitRewritableExpression(
582  RewritableExpression* expr) {
583  PROCESS_EXPRESSION(expr);
584  RECURSE(Visit(expr->expression()));
585 }
586 
587 #undef PROCESS_NODE
588 #undef PROCESS_EXPRESSION
589 #undef RECURSE_EXPRESSION
590 #undef RECURSE
591 
592 } // namespace internal
593 } // namespace v8
594 
595 #endif // V8_AST_AST_TRAVERSAL_VISITOR_H_
Definition: libplatform.h:13