Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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 #include <stdarg.h>
      6 
      7 #include "src/v8.h"
      8 
      9 #include "src/ast-value-factory.h"
     10 #include "src/base/platform/platform.h"
     11 #include "src/prettyprinter.h"
     12 #include "src/scopes.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 
     17 #ifdef DEBUG
     18 
     19 PrettyPrinter::PrettyPrinter(Zone* zone) {
     20   output_ = NULL;
     21   size_ = 0;
     22   pos_ = 0;
     23   InitializeAstVisitor(zone);
     24 }
     25 
     26 
     27 PrettyPrinter::~PrettyPrinter() {
     28   DeleteArray(output_);
     29 }
     30 
     31 
     32 void PrettyPrinter::VisitBlock(Block* node) {
     33   if (!node->is_initializer_block()) Print("{ ");
     34   PrintStatements(node->statements());
     35   if (node->statements()->length() > 0) Print(" ");
     36   if (!node->is_initializer_block()) Print("}");
     37 }
     38 
     39 
     40 void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
     41   Print("var ");
     42   PrintLiteral(node->proxy()->name(), false);
     43   Print(";");
     44 }
     45 
     46 
     47 void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
     48   Print("function ");
     49   PrintLiteral(node->proxy()->name(), false);
     50   Print(" = ");
     51   PrintFunctionLiteral(node->fun());
     52   Print(";");
     53 }
     54 
     55 
     56 void PrettyPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
     57   Print("module ");
     58   PrintLiteral(node->proxy()->name(), false);
     59   Print(" = ");
     60   Visit(node->module());
     61   Print(";");
     62 }
     63 
     64 
     65 void PrettyPrinter::VisitImportDeclaration(ImportDeclaration* node) {
     66   Print("import ");
     67   PrintLiteral(node->proxy()->name(), false);
     68   Print(" from ");
     69   Visit(node->module());
     70   Print(";");
     71 }
     72 
     73 
     74 void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) {
     75   Print("export ");
     76   PrintLiteral(node->proxy()->name(), false);
     77   Print(";");
     78 }
     79 
     80 
     81 void PrettyPrinter::VisitModuleLiteral(ModuleLiteral* node) {
     82   VisitBlock(node->body());
     83 }
     84 
     85 
     86 void PrettyPrinter::VisitModuleVariable(ModuleVariable* node) {
     87   Visit(node->proxy());
     88 }
     89 
     90 
     91 void PrettyPrinter::VisitModulePath(ModulePath* node) {
     92   Visit(node->module());
     93   Print(".");
     94   PrintLiteral(node->name(), false);
     95 }
     96 
     97 
     98 void PrettyPrinter::VisitModuleUrl(ModuleUrl* node) {
     99   Print("at ");
    100   PrintLiteral(node->url(), true);
    101 }
    102 
    103 
    104 void PrettyPrinter::VisitModuleStatement(ModuleStatement* node) {
    105   Print("module ");
    106   PrintLiteral(node->proxy()->name(), false);
    107   Print(" ");
    108   Visit(node->body());
    109 }
    110 
    111 
    112 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
    113   Visit(node->expression());
    114   Print(";");
    115 }
    116 
    117 
    118 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
    119   Print(";");
    120 }
    121 
    122 
    123 void PrettyPrinter::VisitIfStatement(IfStatement* node) {
    124   Print("if (");
    125   Visit(node->condition());
    126   Print(") ");
    127   Visit(node->then_statement());
    128   if (node->HasElseStatement()) {
    129     Print(" else ");
    130     Visit(node->else_statement());
    131   }
    132 }
    133 
    134 
    135 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
    136   Print("continue");
    137   ZoneList<const AstRawString*>* labels = node->target()->labels();
    138   if (labels != NULL) {
    139     Print(" ");
    140     DCHECK(labels->length() > 0);  // guaranteed to have at least one entry
    141     PrintLiteral(labels->at(0), false);  // any label from the list is fine
    142   }
    143   Print(";");
    144 }
    145 
    146 
    147 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
    148   Print("break");
    149   ZoneList<const AstRawString*>* labels = node->target()->labels();
    150   if (labels != NULL) {
    151     Print(" ");
    152     DCHECK(labels->length() > 0);  // guaranteed to have at least one entry
    153     PrintLiteral(labels->at(0), false);  // any label from the list is fine
    154   }
    155   Print(";");
    156 }
    157 
    158 
    159 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
    160   Print("return ");
    161   Visit(node->expression());
    162   Print(";");
    163 }
    164 
    165 
    166 void PrettyPrinter::VisitWithStatement(WithStatement* node) {
    167   Print("with (");
    168   Visit(node->expression());
    169   Print(") ");
    170   Visit(node->statement());
    171 }
    172 
    173 
    174 void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) {
    175   PrintLabels(node->labels());
    176   Print("switch (");
    177   Visit(node->tag());
    178   Print(") { ");
    179   ZoneList<CaseClause*>* cases = node->cases();
    180   for (int i = 0; i < cases->length(); i++)
    181     Visit(cases->at(i));
    182   Print("}");
    183 }
    184 
    185 
    186 void PrettyPrinter::VisitCaseClause(CaseClause* clause) {
    187   if (clause->is_default()) {
    188     Print("default");
    189   } else {
    190     Print("case ");
    191     Visit(clause->label());
    192   }
    193   Print(": ");
    194   PrintStatements(clause->statements());
    195   if (clause->statements()->length() > 0)
    196     Print(" ");
    197 }
    198 
    199 
    200 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
    201   PrintLabels(node->labels());
    202   Print("do ");
    203   Visit(node->body());
    204   Print(" while (");
    205   Visit(node->cond());
    206   Print(");");
    207 }
    208 
    209 
    210 void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
    211   PrintLabels(node->labels());
    212   Print("while (");
    213   Visit(node->cond());
    214   Print(") ");
    215   Visit(node->body());
    216 }
    217 
    218 
    219 void PrettyPrinter::VisitForStatement(ForStatement* node) {
    220   PrintLabels(node->labels());
    221   Print("for (");
    222   if (node->init() != NULL) {
    223     Visit(node->init());
    224     Print(" ");
    225   } else {
    226     Print("; ");
    227   }
    228   if (node->cond() != NULL) Visit(node->cond());
    229   Print("; ");
    230   if (node->next() != NULL) {
    231     Visit(node->next());  // prints extra ';', unfortunately
    232     // to fix: should use Expression for next
    233   }
    234   Print(") ");
    235   Visit(node->body());
    236 }
    237 
    238 
    239 void PrettyPrinter::VisitForInStatement(ForInStatement* node) {
    240   PrintLabels(node->labels());
    241   Print("for (");
    242   Visit(node->each());
    243   Print(" in ");
    244   Visit(node->enumerable());
    245   Print(") ");
    246   Visit(node->body());
    247 }
    248 
    249 
    250 void PrettyPrinter::VisitForOfStatement(ForOfStatement* node) {
    251   PrintLabels(node->labels());
    252   Print("for (");
    253   Visit(node->each());
    254   Print(" of ");
    255   Visit(node->iterable());
    256   Print(") ");
    257   Visit(node->body());
    258 }
    259 
    260 
    261 void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
    262   Print("try ");
    263   Visit(node->try_block());
    264   Print(" catch (");
    265   const bool quote = false;
    266   PrintLiteral(node->variable()->name(), quote);
    267   Print(") ");
    268   Visit(node->catch_block());
    269 }
    270 
    271 
    272 void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    273   Print("try ");
    274   Visit(node->try_block());
    275   Print(" finally ");
    276   Visit(node->finally_block());
    277 }
    278 
    279 
    280 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
    281   Print("debugger ");
    282 }
    283 
    284 
    285 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    286   Print("(");
    287   PrintFunctionLiteral(node);
    288   Print(")");
    289 }
    290 
    291 
    292 void PrettyPrinter::VisitClassLiteral(ClassLiteral* node) {
    293   Print("(class ");
    294   PrintLiteral(node->name(), false);
    295   if (node->extends()) {
    296     Print(" extends ");
    297     Visit(node->extends());
    298   }
    299   Print(" { ");
    300   for (int i = 0; i < node->properties()->length(); i++) {
    301     PrintObjectLiteralProperty(node->properties()->at(i));
    302   }
    303   Print(" })");
    304 }
    305 
    306 
    307 void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
    308   Print("(");
    309   PrintLiteral(node->name(), false);
    310   Print(")");
    311 }
    312 
    313 
    314 void PrettyPrinter::VisitConditional(Conditional* node) {
    315   Visit(node->condition());
    316   Print(" ? ");
    317   Visit(node->then_expression());
    318   Print(" : ");
    319   Visit(node->else_expression());
    320 }
    321 
    322 
    323 void PrettyPrinter::VisitLiteral(Literal* node) {
    324   PrintLiteral(node->value(), true);
    325 }
    326 
    327 
    328 void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
    329   Print(" RegExp(");
    330   PrintLiteral(node->pattern(), false);
    331   Print(",");
    332   PrintLiteral(node->flags(), false);
    333   Print(") ");
    334 }
    335 
    336 
    337 void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
    338   Print("{ ");
    339   for (int i = 0; i < node->properties()->length(); i++) {
    340     if (i != 0) Print(",");
    341     PrintObjectLiteralProperty(node->properties()->at(i));
    342   }
    343   Print(" }");
    344 }
    345 
    346 
    347 void PrettyPrinter::PrintObjectLiteralProperty(
    348     ObjectLiteralProperty* property) {
    349   // TODO(arv): Better printing of methods etc.
    350   Print(" ");
    351   Visit(property->key());
    352   Print(": ");
    353   Visit(property->value());
    354 }
    355 
    356 
    357 void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
    358   Print("[ ");
    359   for (int i = 0; i < node->values()->length(); i++) {
    360     if (i != 0) Print(",");
    361     Visit(node->values()->at(i));
    362   }
    363   Print(" ]");
    364 }
    365 
    366 
    367 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
    368   PrintLiteral(node->name(), false);
    369 }
    370 
    371 
    372 void PrettyPrinter::VisitAssignment(Assignment* node) {
    373   Visit(node->target());
    374   Print(" %s ", Token::String(node->op()));
    375   Visit(node->value());
    376 }
    377 
    378 
    379 void PrettyPrinter::VisitYield(Yield* node) {
    380   Print("yield ");
    381   Visit(node->expression());
    382 }
    383 
    384 
    385 void PrettyPrinter::VisitThrow(Throw* node) {
    386   Print("throw ");
    387   Visit(node->exception());
    388 }
    389 
    390 
    391 void PrettyPrinter::VisitProperty(Property* node) {
    392   Expression* key = node->key();
    393   Literal* literal = key->AsLiteral();
    394   if (literal != NULL && literal->value()->IsInternalizedString()) {
    395     Print("(");
    396     Visit(node->obj());
    397     Print(").");
    398     PrintLiteral(literal->value(), false);
    399   } else {
    400     Visit(node->obj());
    401     Print("[");
    402     Visit(key);
    403     Print("]");
    404   }
    405 }
    406 
    407 
    408 void PrettyPrinter::VisitCall(Call* node) {
    409   Visit(node->expression());
    410   PrintArguments(node->arguments());
    411 }
    412 
    413 
    414 void PrettyPrinter::VisitCallNew(CallNew* node) {
    415   Print("new (");
    416   Visit(node->expression());
    417   Print(")");
    418   PrintArguments(node->arguments());
    419 }
    420 
    421 
    422 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
    423   Print("%%");
    424   PrintLiteral(node->name(), false);
    425   PrintArguments(node->arguments());
    426 }
    427 
    428 
    429 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) {
    430   Token::Value op = node->op();
    431   bool needsSpace =
    432       op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
    433   Print("(%s%s", Token::String(op), needsSpace ? " " : "");
    434   Visit(node->expression());
    435   Print(")");
    436 }
    437 
    438 
    439 void PrettyPrinter::VisitCountOperation(CountOperation* node) {
    440   Print("(");
    441   if (node->is_prefix()) Print("%s", Token::String(node->op()));
    442   Visit(node->expression());
    443   if (node->is_postfix()) Print("%s", Token::String(node->op()));
    444   Print(")");
    445 }
    446 
    447 
    448 void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) {
    449   Print("(");
    450   Visit(node->left());
    451   Print(" %s ", Token::String(node->op()));
    452   Visit(node->right());
    453   Print(")");
    454 }
    455 
    456 
    457 void PrettyPrinter::VisitCompareOperation(CompareOperation* node) {
    458   Print("(");
    459   Visit(node->left());
    460   Print(" %s ", Token::String(node->op()));
    461   Visit(node->right());
    462   Print(")");
    463 }
    464 
    465 
    466 void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
    467   Print("<this-function>");
    468 }
    469 
    470 
    471 void PrettyPrinter::VisitSuperReference(SuperReference* node) {
    472   Print("<super-reference>");
    473 }
    474 
    475 
    476 const char* PrettyPrinter::Print(AstNode* node) {
    477   Init();
    478   Visit(node);
    479   return output_;
    480 }
    481 
    482 
    483 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
    484   Init();
    485   ExpressionStatement* statement =
    486     program->body()->at(0)->AsExpressionStatement();
    487   Visit(statement->expression());
    488   return output_;
    489 }
    490 
    491 
    492 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
    493   Init();
    494   PrintStatements(program->body());
    495   Print("\n");
    496   return output_;
    497 }
    498 
    499 
    500 void PrettyPrinter::PrintOut(Zone* zone, AstNode* node) {
    501   PrettyPrinter printer(zone);
    502   PrintF("%s", printer.Print(node));
    503 }
    504 
    505 
    506 void PrettyPrinter::Init() {
    507   if (size_ == 0) {
    508     DCHECK(output_ == NULL);
    509     const int initial_size = 256;
    510     output_ = NewArray<char>(initial_size);
    511     size_ = initial_size;
    512   }
    513   output_[0] = '\0';
    514   pos_ = 0;
    515 }
    516 
    517 
    518 void PrettyPrinter::Print(const char* format, ...) {
    519   for (;;) {
    520     va_list arguments;
    521     va_start(arguments, format);
    522     int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
    523                       format,
    524                       arguments);
    525     va_end(arguments);
    526 
    527     if (n >= 0) {
    528       // there was enough space - we are done
    529       pos_ += n;
    530       return;
    531     } else {
    532       // there was not enough space - allocate more and try again
    533       const int slack = 32;
    534       int new_size = size_ + (size_ >> 1) + slack;
    535       char* new_output = NewArray<char>(new_size);
    536       MemCopy(new_output, output_, pos_);
    537       DeleteArray(output_);
    538       output_ = new_output;
    539       size_ = new_size;
    540     }
    541   }
    542 }
    543 
    544 
    545 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
    546   if (statements == NULL) return;
    547   for (int i = 0; i < statements->length(); i++) {
    548     if (i != 0) Print(" ");
    549     Visit(statements->at(i));
    550   }
    551 }
    552 
    553 
    554 void PrettyPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) {
    555   if (labels != NULL) {
    556     for (int i = 0; i < labels->length(); i++) {
    557       PrintLiteral(labels->at(i), false);
    558       Print(": ");
    559     }
    560   }
    561 }
    562 
    563 
    564 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
    565   Print("(");
    566   for (int i = 0; i < arguments->length(); i++) {
    567     if (i != 0) Print(", ");
    568     Visit(arguments->at(i));
    569   }
    570   Print(")");
    571 }
    572 
    573 
    574 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
    575   Object* object = *value;
    576   if (object->IsString()) {
    577     String* string = String::cast(object);
    578     if (quote) Print("\"");
    579     for (int i = 0; i < string->length(); i++) {
    580       Print("%c", string->Get(i));
    581     }
    582     if (quote) Print("\"");
    583   } else if (object->IsNull()) {
    584     Print("null");
    585   } else if (object->IsTrue()) {
    586     Print("true");
    587   } else if (object->IsFalse()) {
    588     Print("false");
    589   } else if (object->IsUndefined()) {
    590     Print("undefined");
    591   } else if (object->IsNumber()) {
    592     Print("%g", object->Number());
    593   } else if (object->IsJSObject()) {
    594     // regular expression
    595     if (object->IsJSFunction()) {
    596       Print("JS-Function");
    597     } else if (object->IsJSArray()) {
    598       Print("JS-array[%u]", JSArray::cast(object)->length());
    599     } else if (object->IsJSObject()) {
    600       Print("JS-Object");
    601     } else {
    602       Print("?UNKNOWN?");
    603     }
    604   } else if (object->IsFixedArray()) {
    605     Print("FixedArray");
    606   } else {
    607     Print("<unknown literal %p>", object);
    608   }
    609 }
    610 
    611 
    612 void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) {
    613   PrintLiteral(value->string(), quote);
    614 }
    615 
    616 
    617 void PrettyPrinter::PrintParameters(Scope* scope) {
    618   Print("(");
    619   for (int i = 0; i < scope->num_parameters(); i++) {
    620     if (i  > 0) Print(", ");
    621     PrintLiteral(scope->parameter(i)->name(), false);
    622   }
    623   Print(")");
    624 }
    625 
    626 
    627 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
    628   for (int i = 0; i < declarations->length(); i++) {
    629     if (i > 0) Print(" ");
    630     Visit(declarations->at(i));
    631   }
    632 }
    633 
    634 
    635 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
    636   Print("function ");
    637   PrintLiteral(function->name(), false);
    638   PrintParameters(function->scope());
    639   Print(" { ");
    640   PrintDeclarations(function->scope()->declarations());
    641   PrintStatements(function->body());
    642   Print(" }");
    643 }
    644 
    645 
    646 //-----------------------------------------------------------------------------
    647 
    648 class IndentedScope BASE_EMBEDDED {
    649  public:
    650   IndentedScope(AstPrinter* printer, const char* txt)
    651       : ast_printer_(printer) {
    652     ast_printer_->PrintIndented(txt);
    653     ast_printer_->Print("\n");
    654     ast_printer_->inc_indent();
    655   }
    656 
    657   virtual ~IndentedScope() {
    658     ast_printer_->dec_indent();
    659   }
    660 
    661  private:
    662   AstPrinter* ast_printer_;
    663 };
    664 
    665 
    666 //-----------------------------------------------------------------------------
    667 
    668 
    669 AstPrinter::AstPrinter(Zone* zone) : PrettyPrinter(zone), indent_(0) {
    670 }
    671 
    672 
    673 AstPrinter::~AstPrinter() {
    674   DCHECK(indent_ == 0);
    675 }
    676 
    677 
    678 void AstPrinter::PrintIndented(const char* txt) {
    679   for (int i = 0; i < indent_; i++) {
    680     Print(". ");
    681   }
    682   Print(txt);
    683 }
    684 
    685 
    686 void AstPrinter::PrintLiteralIndented(const char* info,
    687                                       Handle<Object> value,
    688                                       bool quote) {
    689   PrintIndented(info);
    690   Print(" ");
    691   PrintLiteral(value, quote);
    692   Print("\n");
    693 }
    694 
    695 
    696 void AstPrinter::PrintLiteralWithModeIndented(const char* info,
    697                                               Variable* var,
    698                                               Handle<Object> value) {
    699   if (var == NULL) {
    700     PrintLiteralIndented(info, value, true);
    701   } else {
    702     EmbeddedVector<char, 256> buf;
    703     int pos = SNPrintF(buf, "%s (mode = %s", info,
    704                        Variable::Mode2String(var->mode()));
    705     SNPrintF(buf + pos, ")");
    706     PrintLiteralIndented(buf.start(), value, true);
    707   }
    708 }
    709 
    710 
    711 void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) {
    712   if (labels == NULL || labels->length() == 0) return;
    713   PrintIndented("LABELS ");
    714   PrintLabels(labels);
    715   Print("\n");
    716 }
    717 
    718 
    719 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
    720   IndentedScope indent(this, s);
    721   Visit(node);
    722 }
    723 
    724 
    725 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
    726   Init();
    727   { IndentedScope indent(this, "FUNC");
    728     PrintLiteralIndented("NAME", program->name(), true);
    729     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
    730     PrintParameters(program->scope());
    731     PrintDeclarations(program->scope()->declarations());
    732     PrintStatements(program->body());
    733   }
    734   return Output();
    735 }
    736 
    737 
    738 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
    739   if (declarations->length() > 0) {
    740     IndentedScope indent(this, "DECLS");
    741     for (int i = 0; i < declarations->length(); i++) {
    742       Visit(declarations->at(i));
    743     }
    744   }
    745 }
    746 
    747 
    748 void AstPrinter::PrintParameters(Scope* scope) {
    749   if (scope->num_parameters() > 0) {
    750     IndentedScope indent(this, "PARAMS");
    751     for (int i = 0; i < scope->num_parameters(); i++) {
    752       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
    753                                    scope->parameter(i)->name());
    754     }
    755   }
    756 }
    757 
    758 
    759 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
    760   for (int i = 0; i < statements->length(); i++) {
    761     Visit(statements->at(i));
    762   }
    763 }
    764 
    765 
    766 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
    767   for (int i = 0; i < arguments->length(); i++) {
    768     Visit(arguments->at(i));
    769   }
    770 }
    771 
    772 
    773 void AstPrinter::VisitBlock(Block* node) {
    774   const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
    775   IndentedScope indent(this, block_txt);
    776   PrintStatements(node->statements());
    777 }
    778 
    779 
    780 // TODO(svenpanne) Start with IndentedScope.
    781 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
    782   PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
    783                                node->proxy()->var(),
    784                                node->proxy()->name());
    785 }
    786 
    787 
    788 // TODO(svenpanne) Start with IndentedScope.
    789 void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
    790   PrintIndented("FUNCTION ");
    791   PrintLiteral(node->proxy()->name(), true);
    792   Print(" = function ");
    793   PrintLiteral(node->fun()->name(), false);
    794   Print("\n");
    795 }
    796 
    797 
    798 void AstPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
    799   IndentedScope indent(this, "MODULE");
    800   PrintLiteralIndented("NAME", node->proxy()->name(), true);
    801   Visit(node->module());
    802 }
    803 
    804 
    805 void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
    806   IndentedScope indent(this, "IMPORT");
    807   PrintLiteralIndented("NAME", node->proxy()->name(), true);
    808   Visit(node->module());
    809 }
    810 
    811 
    812 void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
    813   IndentedScope indent(this, "EXPORT ");
    814   PrintLiteral(node->proxy()->name(), true);
    815 }
    816 
    817 
    818 void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) {
    819   IndentedScope indent(this, "MODULE LITERAL");
    820   VisitBlock(node->body());
    821 }
    822 
    823 
    824 void AstPrinter::VisitModuleVariable(ModuleVariable* node) {
    825   IndentedScope indent(this, "MODULE VARIABLE");
    826   Visit(node->proxy());
    827 }
    828 
    829 
    830 void AstPrinter::VisitModulePath(ModulePath* node) {
    831   IndentedScope indent(this, "MODULE PATH");
    832   PrintIndentedVisit("MODULE PATH PARENT", node->module());
    833   PrintLiteralIndented("NAME", node->name(), true);
    834 }
    835 
    836 
    837 void AstPrinter::VisitModuleUrl(ModuleUrl* node) {
    838   PrintLiteralIndented("URL", node->url(), true);
    839 }
    840 
    841 
    842 void AstPrinter::VisitModuleStatement(ModuleStatement* node) {
    843   IndentedScope indent(this, "MODULE STATEMENT");
    844   PrintLiteralIndented("NAME", node->proxy()->name(), true);
    845   PrintStatements(node->body()->statements());
    846 }
    847 
    848 
    849 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
    850   IndentedScope indent(this, "EXPRESSION STATEMENT");
    851   Visit(node->expression());
    852 }
    853 
    854 
    855 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
    856   IndentedScope indent(this, "EMPTY");
    857 }
    858 
    859 
    860 void AstPrinter::VisitIfStatement(IfStatement* node) {
    861   IndentedScope indent(this, "IF");
    862   PrintIndentedVisit("CONDITION", node->condition());
    863   PrintIndentedVisit("THEN", node->then_statement());
    864   if (node->HasElseStatement()) {
    865     PrintIndentedVisit("ELSE", node->else_statement());
    866   }
    867 }
    868 
    869 
    870 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
    871   IndentedScope indent(this, "CONTINUE");
    872   PrintLabelsIndented(node->target()->labels());
    873 }
    874 
    875 
    876 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
    877   IndentedScope indent(this, "BREAK");
    878   PrintLabelsIndented(node->target()->labels());
    879 }
    880 
    881 
    882 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
    883   IndentedScope indent(this, "RETURN");
    884   Visit(node->expression());
    885 }
    886 
    887 
    888 void AstPrinter::VisitWithStatement(WithStatement* node) {
    889   IndentedScope indent(this, "WITH");
    890   PrintIndentedVisit("OBJECT", node->expression());
    891   PrintIndentedVisit("BODY", node->statement());
    892 }
    893 
    894 
    895 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
    896   IndentedScope indent(this, "SWITCH");
    897   PrintLabelsIndented(node->labels());
    898   PrintIndentedVisit("TAG", node->tag());
    899   for (int i = 0; i < node->cases()->length(); i++) {
    900     Visit(node->cases()->at(i));
    901   }
    902 }
    903 
    904 
    905 void AstPrinter::VisitCaseClause(CaseClause* clause) {
    906   if (clause->is_default()) {
    907     IndentedScope indent(this, "DEFAULT");
    908     PrintStatements(clause->statements());
    909   } else {
    910     IndentedScope indent(this, "CASE");
    911     Visit(clause->label());
    912     PrintStatements(clause->statements());
    913   }
    914 }
    915 
    916 
    917 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
    918   IndentedScope indent(this, "DO");
    919   PrintLabelsIndented(node->labels());
    920   PrintIndentedVisit("BODY", node->body());
    921   PrintIndentedVisit("COND", node->cond());
    922 }
    923 
    924 
    925 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
    926   IndentedScope indent(this, "WHILE");
    927   PrintLabelsIndented(node->labels());
    928   PrintIndentedVisit("COND", node->cond());
    929   PrintIndentedVisit("BODY", node->body());
    930 }
    931 
    932 
    933 void AstPrinter::VisitForStatement(ForStatement* node) {
    934   IndentedScope indent(this, "FOR");
    935   PrintLabelsIndented(node->labels());
    936   if (node->init()) PrintIndentedVisit("INIT", node->init());
    937   if (node->cond()) PrintIndentedVisit("COND", node->cond());
    938   PrintIndentedVisit("BODY", node->body());
    939   if (node->next()) PrintIndentedVisit("NEXT", node->next());
    940 }
    941 
    942 
    943 void AstPrinter::VisitForInStatement(ForInStatement* node) {
    944   IndentedScope indent(this, "FOR IN");
    945   PrintIndentedVisit("FOR", node->each());
    946   PrintIndentedVisit("IN", node->enumerable());
    947   PrintIndentedVisit("BODY", node->body());
    948 }
    949 
    950 
    951 void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
    952   IndentedScope indent(this, "FOR OF");
    953   PrintIndentedVisit("FOR", node->each());
    954   PrintIndentedVisit("OF", node->iterable());
    955   PrintIndentedVisit("BODY", node->body());
    956 }
    957 
    958 
    959 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
    960   IndentedScope indent(this, "TRY CATCH");
    961   PrintIndentedVisit("TRY", node->try_block());
    962   PrintLiteralWithModeIndented("CATCHVAR",
    963                                node->variable(),
    964                                node->variable()->name());
    965   PrintIndentedVisit("CATCH", node->catch_block());
    966 }
    967 
    968 
    969 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    970   IndentedScope indent(this, "TRY FINALLY");
    971   PrintIndentedVisit("TRY", node->try_block());
    972   PrintIndentedVisit("FINALLY", node->finally_block());
    973 }
    974 
    975 
    976 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
    977   IndentedScope indent(this, "DEBUGGER");
    978 }
    979 
    980 
    981 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    982   IndentedScope indent(this, "FUNC LITERAL");
    983   PrintLiteralIndented("NAME", node->name(), false);
    984   PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
    985   PrintParameters(node->scope());
    986   // We don't want to see the function literal in this case: it
    987   // will be printed via PrintProgram when the code for it is
    988   // generated.
    989   // PrintStatements(node->body());
    990 }
    991 
    992 
    993 void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
    994   IndentedScope indent(this, "CLASS LITERAL");
    995   PrintLiteralIndented("NAME", node->name(), false);
    996 }
    997 
    998 
    999 void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
   1000   IndentedScope indent(this, "NATIVE FUNC LITERAL");
   1001   PrintLiteralIndented("NAME", node->name(), false);
   1002 }
   1003 
   1004 
   1005 void AstPrinter::VisitConditional(Conditional* node) {
   1006   IndentedScope indent(this, "CONDITIONAL");
   1007   PrintIndentedVisit("CONDITION", node->condition());
   1008   PrintIndentedVisit("THEN", node->then_expression());
   1009   PrintIndentedVisit("ELSE", node->else_expression());
   1010 }
   1011 
   1012 
   1013 // TODO(svenpanne) Start with IndentedScope.
   1014 void AstPrinter::VisitLiteral(Literal* node) {
   1015   PrintLiteralIndented("LITERAL", node->value(), true);
   1016 }
   1017 
   1018 
   1019 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
   1020   IndentedScope indent(this, "REGEXP LITERAL");
   1021   PrintLiteralIndented("PATTERN", node->pattern(), false);
   1022   PrintLiteralIndented("FLAGS", node->flags(), false);
   1023 }
   1024 
   1025 
   1026 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
   1027   IndentedScope indent(this, "OBJ LITERAL");
   1028   for (int i = 0; i < node->properties()->length(); i++) {
   1029     const char* prop_kind = NULL;
   1030     switch (node->properties()->at(i)->kind()) {
   1031       case ObjectLiteral::Property::CONSTANT:
   1032         prop_kind = "PROPERTY - CONSTANT";
   1033         break;
   1034       case ObjectLiteral::Property::COMPUTED:
   1035         prop_kind = "PROPERTY - COMPUTED";
   1036         break;
   1037       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   1038         prop_kind = "PROPERTY - MATERIALIZED_LITERAL";
   1039         break;
   1040       case ObjectLiteral::Property::PROTOTYPE:
   1041         prop_kind = "PROPERTY - PROTOTYPE";
   1042         break;
   1043       case ObjectLiteral::Property::GETTER:
   1044         prop_kind = "PROPERTY - GETTER";
   1045         break;
   1046       case ObjectLiteral::Property::SETTER:
   1047         prop_kind = "PROPERTY - SETTER";
   1048         break;
   1049       default:
   1050         UNREACHABLE();
   1051     }
   1052     IndentedScope prop(this, prop_kind);
   1053     PrintIndentedVisit("KEY", node->properties()->at(i)->key());
   1054     PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
   1055   }
   1056 }
   1057 
   1058 
   1059 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
   1060   IndentedScope indent(this, "ARRAY LITERAL");
   1061   if (node->values()->length() > 0) {
   1062     IndentedScope indent(this, "VALUES");
   1063     for (int i = 0; i < node->values()->length(); i++) {
   1064       Visit(node->values()->at(i));
   1065     }
   1066   }
   1067 }
   1068 
   1069 
   1070 // TODO(svenpanne) Start with IndentedScope.
   1071 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
   1072   Variable* var = node->var();
   1073   EmbeddedVector<char, 128> buf;
   1074   int pos = SNPrintF(buf, "VAR PROXY");
   1075   switch (var->location()) {
   1076     case Variable::UNALLOCATED:
   1077       break;
   1078     case Variable::PARAMETER:
   1079       SNPrintF(buf + pos, " parameter[%d]", var->index());
   1080       break;
   1081     case Variable::LOCAL:
   1082       SNPrintF(buf + pos, " local[%d]", var->index());
   1083       break;
   1084     case Variable::CONTEXT:
   1085       SNPrintF(buf + pos, " context[%d]", var->index());
   1086       break;
   1087     case Variable::LOOKUP:
   1088       SNPrintF(buf + pos, " lookup");
   1089       break;
   1090   }
   1091   PrintLiteralWithModeIndented(buf.start(), var, node->name());
   1092 }
   1093 
   1094 
   1095 void AstPrinter::VisitAssignment(Assignment* node) {
   1096   IndentedScope indent(this, Token::Name(node->op()));
   1097   Visit(node->target());
   1098   Visit(node->value());
   1099 }
   1100 
   1101 
   1102 void AstPrinter::VisitYield(Yield* node) {
   1103   IndentedScope indent(this, "YIELD");
   1104   Visit(node->expression());
   1105 }
   1106 
   1107 
   1108 void AstPrinter::VisitThrow(Throw* node) {
   1109   IndentedScope indent(this, "THROW");
   1110   Visit(node->exception());
   1111 }
   1112 
   1113 
   1114 void AstPrinter::VisitProperty(Property* node) {
   1115   IndentedScope indent(this, "PROPERTY");
   1116   Visit(node->obj());
   1117   Literal* literal = node->key()->AsLiteral();
   1118   if (literal != NULL && literal->value()->IsInternalizedString()) {
   1119     PrintLiteralIndented("NAME", literal->value(), false);
   1120   } else {
   1121     PrintIndentedVisit("KEY", node->key());
   1122   }
   1123 }
   1124 
   1125 
   1126 void AstPrinter::VisitCall(Call* node) {
   1127   IndentedScope indent(this, "CALL");
   1128   Visit(node->expression());
   1129   PrintArguments(node->arguments());
   1130 }
   1131 
   1132 
   1133 void AstPrinter::VisitCallNew(CallNew* node) {
   1134   IndentedScope indent(this, "CALL NEW");
   1135   Visit(node->expression());
   1136   PrintArguments(node->arguments());
   1137 }
   1138 
   1139 
   1140 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
   1141   IndentedScope indent(this, "CALL RUNTIME");
   1142   PrintLiteralIndented("NAME", node->name(), false);
   1143   PrintArguments(node->arguments());
   1144 }
   1145 
   1146 
   1147 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
   1148   IndentedScope indent(this, Token::Name(node->op()));
   1149   Visit(node->expression());
   1150 }
   1151 
   1152 
   1153 void AstPrinter::VisitCountOperation(CountOperation* node) {
   1154   EmbeddedVector<char, 128> buf;
   1155   SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
   1156            Token::Name(node->op()));
   1157   IndentedScope indent(this, buf.start());
   1158   Visit(node->expression());
   1159 }
   1160 
   1161 
   1162 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
   1163   IndentedScope indent(this, Token::Name(node->op()));
   1164   Visit(node->left());
   1165   Visit(node->right());
   1166 }
   1167 
   1168 
   1169 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
   1170   IndentedScope indent(this, Token::Name(node->op()));
   1171   Visit(node->left());
   1172   Visit(node->right());
   1173 }
   1174 
   1175 
   1176 void AstPrinter::VisitThisFunction(ThisFunction* node) {
   1177   IndentedScope indent(this, "THIS-FUNCTION");
   1178 }
   1179 
   1180 
   1181 void AstPrinter::VisitSuperReference(SuperReference* node) {
   1182   IndentedScope indent(this, "SUPER-REFERENCE");
   1183 }
   1184 
   1185 #endif  // DEBUG
   1186 
   1187 } }  // namespace v8::internal
   1188