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