Home | History | Annotate | Download | only in ast
      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(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() 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>
     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     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     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>
    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   RECURSE(VisitStatements(stmt->statements()));
    140 }
    141 
    142 template <class Subclass>
    143 void AstTraversalVisitor<Subclass>::VisitExpressionStatement(
    144     ExpressionStatement* stmt) {
    145   PROCESS_NODE(stmt);
    146   RECURSE(Visit(stmt->expression()));
    147 }
    148 
    149 template <class Subclass>
    150 void AstTraversalVisitor<Subclass>::VisitEmptyStatement(EmptyStatement* stmt) {}
    151 
    152 template <class Subclass>
    153 void AstTraversalVisitor<Subclass>::VisitSloppyBlockFunctionStatement(
    154     SloppyBlockFunctionStatement* stmt) {
    155   PROCESS_NODE(stmt);
    156   RECURSE(Visit(stmt->statement()));
    157 }
    158 
    159 template <class Subclass>
    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>
    168 void AstTraversalVisitor<Subclass>::VisitContinueStatement(
    169     ContinueStatement* stmt) {
    170   PROCESS_NODE(stmt);
    171 }
    172 
    173 template <class Subclass>
    174 void AstTraversalVisitor<Subclass>::VisitBreakStatement(BreakStatement* stmt) {
    175   PROCESS_NODE(stmt);
    176 }
    177 
    178 template <class Subclass>
    179 void AstTraversalVisitor<Subclass>::VisitReturnStatement(
    180     ReturnStatement* stmt) {
    181   PROCESS_NODE(stmt);
    182   RECURSE(Visit(stmt->expression()));
    183 }
    184 
    185 template <class Subclass>
    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>
    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>
    211 void AstTraversalVisitor<Subclass>::VisitCaseClause(CaseClause* clause) {
    212   UNREACHABLE();
    213 }
    214 
    215 template <class Subclass>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    279 void AstTraversalVisitor<Subclass>::VisitDebuggerStatement(
    280     DebuggerStatement* stmt) {
    281   PROCESS_NODE(stmt);
    282 }
    283 
    284 template <class Subclass>
    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()->was_lazily_parsed()) return;
    292   RECURSE_EXPRESSION(VisitStatements(expr->body()));
    293 }
    294 
    295 template <class Subclass>
    296 void AstTraversalVisitor<Subclass>::VisitNativeFunctionLiteral(
    297     NativeFunctionLiteral* expr) {
    298   PROCESS_EXPRESSION(expr);
    299 }
    300 
    301 template <class Subclass>
    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>
    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>
    317 void AstTraversalVisitor<Subclass>::VisitVariableProxy(VariableProxy* expr) {
    318   PROCESS_EXPRESSION(expr);
    319 }
    320 
    321 template <class Subclass>
    322 void AstTraversalVisitor<Subclass>::VisitLiteral(Literal* expr) {
    323   PROCESS_EXPRESSION(expr);
    324 }
    325 
    326 template <class Subclass>
    327 void AstTraversalVisitor<Subclass>::VisitRegExpLiteral(RegExpLiteral* expr) {
    328   PROCESS_EXPRESSION(expr);
    329 }
    330 
    331 template <class Subclass>
    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>
    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>
    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>
    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>
    367 void AstTraversalVisitor<Subclass>::VisitThrow(Throw* expr) {
    368   PROCESS_EXPRESSION(expr);
    369   RECURSE_EXPRESSION(Visit(expr->exception()));
    370 }
    371 
    372 template <class Subclass>
    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>
    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>
    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>
    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>
    412 void AstTraversalVisitor<Subclass>::VisitUnaryOperation(UnaryOperation* expr) {
    413   PROCESS_EXPRESSION(expr);
    414   RECURSE_EXPRESSION(Visit(expr->expression()));
    415 }
    416 
    417 template <class Subclass>
    418 void AstTraversalVisitor<Subclass>::VisitCountOperation(CountOperation* expr) {
    419   PROCESS_EXPRESSION(expr);
    420   RECURSE_EXPRESSION(Visit(expr->expression()));
    421 }
    422 
    423 template <class Subclass>
    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>
    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>
    440 void AstTraversalVisitor<Subclass>::VisitThisFunction(ThisFunction* expr) {
    441   PROCESS_EXPRESSION(expr);
    442 }
    443 
    444 template <class Subclass>
    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>
    462 void AstTraversalVisitor<Subclass>::VisitSpread(Spread* expr) {
    463   PROCESS_EXPRESSION(expr);
    464   RECURSE_EXPRESSION(Visit(expr->expression()));
    465 }
    466 
    467 template <class Subclass>
    468 void AstTraversalVisitor<Subclass>::VisitEmptyParentheses(
    469     EmptyParentheses* expr) {
    470   PROCESS_EXPRESSION(expr);
    471 }
    472 
    473 template <class Subclass>
    474 void AstTraversalVisitor<Subclass>::VisitGetIterator(GetIterator* expr) {
    475   PROCESS_EXPRESSION(expr);
    476   RECURSE_EXPRESSION(Visit(expr->iterable()));
    477 }
    478 
    479 template <class Subclass>
    480 void AstTraversalVisitor<Subclass>::VisitSuperPropertyReference(
    481     SuperPropertyReference* expr) {
    482   PROCESS_EXPRESSION(expr);
    483   RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
    484   RECURSE_EXPRESSION(Visit(expr->home_object()));
    485 }
    486 
    487 template <class Subclass>
    488 void AstTraversalVisitor<Subclass>::VisitSuperCallReference(
    489     SuperCallReference* expr) {
    490   PROCESS_EXPRESSION(expr);
    491   RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
    492   RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var()));
    493   RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var()));
    494 }
    495 
    496 template <class Subclass>
    497 void AstTraversalVisitor<Subclass>::VisitRewritableExpression(
    498     RewritableExpression* expr) {
    499   PROCESS_EXPRESSION(expr);
    500   RECURSE(Visit(expr->expression()));
    501 }
    502 
    503 #undef PROCESS_NODE
    504 #undef PROCESS_EXPRESSION
    505 #undef RECURSE_EXPRESSION
    506 #undef RECURSE
    507 
    508 }  // namespace internal
    509 }  // namespace v8
    510 
    511 #endif  // V8_AST_AST_TRAVERSAL_VISITOR_H_
    512