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