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