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