Home | History | Annotate | Download | only in ast
      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 "src/ast/prettyprinter.h"
      6 
      7 #include <stdarg.h>
      8 
      9 #include "src/ast/ast-value-factory.h"
     10 #include "src/ast/scopes.h"
     11 #include "src/base/platform/platform.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin) {
     17   isolate_ = isolate;
     18   output_ = NULL;
     19   size_ = 0;
     20   pos_ = 0;
     21   position_ = 0;
     22   found_ = false;
     23   done_ = false;
     24   is_builtin_ = is_builtin;
     25   InitializeAstVisitor(isolate);
     26 }
     27 
     28 
     29 CallPrinter::~CallPrinter() { DeleteArray(output_); }
     30 
     31 
     32 const char* CallPrinter::Print(FunctionLiteral* program, int position) {
     33   Init();
     34   position_ = position;
     35   Find(program);
     36   return output_;
     37 }
     38 
     39 
     40 void CallPrinter::Find(AstNode* node, bool print) {
     41   if (done_) return;
     42   if (found_) {
     43     if (print) {
     44       int start = pos_;
     45       Visit(node);
     46       if (start != pos_) return;
     47     }
     48     Print("(intermediate value)");
     49   } else {
     50     Visit(node);
     51   }
     52 }
     53 
     54 
     55 void CallPrinter::Init() {
     56   if (size_ == 0) {
     57     DCHECK(output_ == NULL);
     58     const int initial_size = 256;
     59     output_ = NewArray<char>(initial_size);
     60     size_ = initial_size;
     61   }
     62   output_[0] = '\0';
     63   pos_ = 0;
     64 }
     65 
     66 
     67 void CallPrinter::Print(const char* format, ...) {
     68   if (!found_ || done_) return;
     69   for (;;) {
     70     va_list arguments;
     71     va_start(arguments, format);
     72     int n = VSNPrintF(Vector<char>(output_, size_) + pos_, format, arguments);
     73     va_end(arguments);
     74 
     75     if (n >= 0) {
     76       // there was enough space - we are done
     77       pos_ += n;
     78       return;
     79     } else {
     80       // there was not enough space - allocate more and try again
     81       const int slack = 32;
     82       int new_size = size_ + (size_ >> 1) + slack;
     83       char* new_output = NewArray<char>(new_size);
     84       MemCopy(new_output, output_, pos_);
     85       DeleteArray(output_);
     86       output_ = new_output;
     87       size_ = new_size;
     88     }
     89   }
     90 }
     91 
     92 
     93 void CallPrinter::VisitBlock(Block* node) {
     94   FindStatements(node->statements());
     95 }
     96 
     97 
     98 void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {}
     99 
    100 
    101 void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {}
    102 
    103 
    104 void CallPrinter::VisitImportDeclaration(ImportDeclaration* node) {
    105 }
    106 
    107 
    108 void CallPrinter::VisitExportDeclaration(ExportDeclaration* node) {}
    109 
    110 
    111 void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) {
    112   Find(node->expression());
    113 }
    114 
    115 
    116 void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {}
    117 
    118 
    119 void CallPrinter::VisitSloppyBlockFunctionStatement(
    120     SloppyBlockFunctionStatement* node) {
    121   Find(node->statement());
    122 }
    123 
    124 
    125 void CallPrinter::VisitIfStatement(IfStatement* node) {
    126   Find(node->condition());
    127   Find(node->then_statement());
    128   if (node->HasElseStatement()) {
    129     Find(node->else_statement());
    130   }
    131 }
    132 
    133 
    134 void CallPrinter::VisitContinueStatement(ContinueStatement* node) {}
    135 
    136 
    137 void CallPrinter::VisitBreakStatement(BreakStatement* node) {}
    138 
    139 
    140 void CallPrinter::VisitReturnStatement(ReturnStatement* node) {
    141   Find(node->expression());
    142 }
    143 
    144 
    145 void CallPrinter::VisitWithStatement(WithStatement* node) {
    146   Find(node->expression());
    147   Find(node->statement());
    148 }
    149 
    150 
    151 void CallPrinter::VisitSwitchStatement(SwitchStatement* node) {
    152   Find(node->tag());
    153   ZoneList<CaseClause*>* cases = node->cases();
    154   for (int i = 0; i < cases->length(); i++) Find(cases->at(i));
    155 }
    156 
    157 
    158 void CallPrinter::VisitCaseClause(CaseClause* clause) {
    159   if (!clause->is_default()) {
    160     Find(clause->label());
    161   }
    162   FindStatements(clause->statements());
    163 }
    164 
    165 
    166 void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
    167   Find(node->body());
    168   Find(node->cond());
    169 }
    170 
    171 
    172 void CallPrinter::VisitWhileStatement(WhileStatement* node) {
    173   Find(node->cond());
    174   Find(node->body());
    175 }
    176 
    177 
    178 void CallPrinter::VisitForStatement(ForStatement* node) {
    179   if (node->init() != NULL) {
    180     Find(node->init());
    181   }
    182   if (node->cond() != NULL) Find(node->cond());
    183   if (node->next() != NULL) Find(node->next());
    184   Find(node->body());
    185 }
    186 
    187 
    188 void CallPrinter::VisitForInStatement(ForInStatement* node) {
    189   Find(node->each());
    190   Find(node->enumerable());
    191   Find(node->body());
    192 }
    193 
    194 
    195 void CallPrinter::VisitForOfStatement(ForOfStatement* node) {
    196   Find(node->assign_iterator());
    197   Find(node->next_result());
    198   Find(node->result_done());
    199   Find(node->assign_each());
    200   Find(node->body());
    201 }
    202 
    203 
    204 void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
    205   Find(node->try_block());
    206   Find(node->catch_block());
    207 }
    208 
    209 
    210 void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    211   Find(node->try_block());
    212   Find(node->finally_block());
    213 }
    214 
    215 
    216 void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {}
    217 
    218 
    219 void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    220   FindStatements(node->body());
    221 }
    222 
    223 
    224 void CallPrinter::VisitClassLiteral(ClassLiteral* node) {
    225   if (node->extends()) Find(node->extends());
    226   for (int i = 0; i < node->properties()->length(); i++) {
    227     Find(node->properties()->at(i)->value());
    228   }
    229 }
    230 
    231 
    232 void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
    233 
    234 
    235 void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); }
    236 
    237 
    238 void CallPrinter::VisitConditional(Conditional* node) {
    239   Find(node->condition());
    240   Find(node->then_expression());
    241   Find(node->else_expression());
    242 }
    243 
    244 
    245 void CallPrinter::VisitLiteral(Literal* node) {
    246   PrintLiteral(*node->value(), true);
    247 }
    248 
    249 
    250 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
    251   Print("/");
    252   PrintLiteral(*node->pattern(), false);
    253   Print("/");
    254   if (node->flags() & RegExp::kGlobal) Print("g");
    255   if (node->flags() & RegExp::kIgnoreCase) Print("i");
    256   if (node->flags() & RegExp::kMultiline) Print("m");
    257   if (node->flags() & RegExp::kUnicode) Print("u");
    258   if (node->flags() & RegExp::kSticky) Print("y");
    259 }
    260 
    261 
    262 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) {
    263   for (int i = 0; i < node->properties()->length(); i++) {
    264     Find(node->properties()->at(i)->value());
    265   }
    266 }
    267 
    268 
    269 void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) {
    270   Print("[");
    271   for (int i = 0; i < node->values()->length(); i++) {
    272     if (i != 0) Print(",");
    273     Find(node->values()->at(i), true);
    274   }
    275   Print("]");
    276 }
    277 
    278 
    279 void CallPrinter::VisitVariableProxy(VariableProxy* node) {
    280   if (is_builtin_) {
    281     // Variable names of builtins are meaningless due to minification.
    282     Print("(var)");
    283   } else {
    284     PrintLiteral(*node->name(), false);
    285   }
    286 }
    287 
    288 
    289 void CallPrinter::VisitAssignment(Assignment* node) {
    290   Find(node->target());
    291   Find(node->value());
    292 }
    293 
    294 
    295 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
    296 
    297 
    298 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); }
    299 
    300 
    301 void CallPrinter::VisitProperty(Property* node) {
    302   Expression* key = node->key();
    303   Literal* literal = key->AsLiteral();
    304   if (literal != NULL && literal->value()->IsInternalizedString()) {
    305     Find(node->obj(), true);
    306     Print(".");
    307     PrintLiteral(*literal->value(), false);
    308   } else {
    309     Find(node->obj(), true);
    310     Print("[");
    311     Find(key, true);
    312     Print("]");
    313   }
    314 }
    315 
    316 
    317 void CallPrinter::VisitCall(Call* node) {
    318   bool was_found = !found_ && node->position() == position_;
    319   if (was_found) {
    320     // Bail out if the error is caused by a direct call to a variable in builtin
    321     // code. The variable name is meaningless due to minification.
    322     if (is_builtin_ && node->expression()->IsVariableProxy()) {
    323       done_ = true;
    324       return;
    325     }
    326     found_ = true;
    327   }
    328   Find(node->expression(), true);
    329   if (!was_found) Print("(...)");
    330   FindArguments(node->arguments());
    331   if (was_found) done_ = true;
    332 }
    333 
    334 
    335 void CallPrinter::VisitCallNew(CallNew* node) {
    336   bool was_found = !found_ && node->position() == position_;
    337   if (was_found) {
    338     // Bail out if the error is caused by a direct call to a variable in builtin
    339     // code. The variable name is meaningless due to minification.
    340     if (is_builtin_ && node->expression()->IsVariableProxy()) {
    341       done_ = true;
    342       return;
    343     }
    344     found_ = true;
    345   }
    346   Find(node->expression(), was_found);
    347   FindArguments(node->arguments());
    348   if (was_found) done_ = true;
    349 }
    350 
    351 
    352 void CallPrinter::VisitCallRuntime(CallRuntime* node) {
    353   FindArguments(node->arguments());
    354 }
    355 
    356 
    357 void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
    358   Token::Value op = node->op();
    359   bool needsSpace =
    360       op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
    361   Print("(%s%s", Token::String(op), needsSpace ? " " : "");
    362   Find(node->expression(), true);
    363   Print(")");
    364 }
    365 
    366 
    367 void CallPrinter::VisitCountOperation(CountOperation* node) {
    368   Print("(");
    369   if (node->is_prefix()) Print("%s", Token::String(node->op()));
    370   Find(node->expression(), true);
    371   if (node->is_postfix()) Print("%s", Token::String(node->op()));
    372   Print(")");
    373 }
    374 
    375 
    376 void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
    377   Print("(");
    378   Find(node->left(), true);
    379   Print(" %s ", Token::String(node->op()));
    380   Find(node->right(), true);
    381   Print(")");
    382 }
    383 
    384 
    385 void CallPrinter::VisitCompareOperation(CompareOperation* node) {
    386   Print("(");
    387   Find(node->left(), true);
    388   Print(" %s ", Token::String(node->op()));
    389   Find(node->right(), true);
    390   Print(")");
    391 }
    392 
    393 
    394 void CallPrinter::VisitSpread(Spread* node) {
    395   Print("(...");
    396   Find(node->expression(), true);
    397   Print(")");
    398 }
    399 
    400 
    401 void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
    402   UNREACHABLE();
    403 }
    404 
    405 
    406 void CallPrinter::VisitThisFunction(ThisFunction* node) {}
    407 
    408 
    409 void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
    410 
    411 
    412 void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
    413   Print("super");
    414 }
    415 
    416 
    417 void CallPrinter::VisitRewritableExpression(RewritableExpression* node) {
    418   Find(node->expression());
    419 }
    420 
    421 
    422 void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {
    423   if (statements == NULL) return;
    424   for (int i = 0; i < statements->length(); i++) {
    425     Find(statements->at(i));
    426   }
    427 }
    428 
    429 
    430 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) {
    431   if (found_) return;
    432   for (int i = 0; i < arguments->length(); i++) {
    433     Find(arguments->at(i));
    434   }
    435 }
    436 
    437 
    438 void CallPrinter::PrintLiteral(Object* value, bool quote) {
    439   Object* object = value;
    440   if (object->IsString()) {
    441     if (quote) Print("\"");
    442     Print("%s", String::cast(object)->ToCString().get());
    443     if (quote) Print("\"");
    444   } else if (object->IsNull(isolate_)) {
    445     Print("null");
    446   } else if (object->IsTrue(isolate_)) {
    447     Print("true");
    448   } else if (object->IsFalse(isolate_)) {
    449     Print("false");
    450   } else if (object->IsUndefined(isolate_)) {
    451     Print("undefined");
    452   } else if (object->IsNumber()) {
    453     Print("%g", object->Number());
    454   } else if (object->IsSymbol()) {
    455     // Symbols can only occur as literals if they were inserted by the parser.
    456     PrintLiteral(Symbol::cast(object)->name(), false);
    457   }
    458 }
    459 
    460 
    461 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
    462   PrintLiteral(*value->string(), quote);
    463 }
    464 
    465 
    466 //-----------------------------------------------------------------------------
    467 
    468 
    469 #ifdef DEBUG
    470 
    471 // A helper for ast nodes that use FeedbackVectorSlots.
    472 static int FormatSlotNode(Vector<char>* buf, Expression* node,
    473                           const char* node_name, FeedbackVectorSlot slot) {
    474   int pos = SNPrintF(*buf, "%s", node_name);
    475   if (!slot.IsInvalid()) {
    476     pos += SNPrintF(*buf + pos, " Slot(%d)", slot.ToInt());
    477   }
    478   return pos;
    479 }
    480 
    481 
    482 PrettyPrinter::PrettyPrinter(Isolate* isolate) {
    483   isolate_ = isolate;
    484   output_ = NULL;
    485   size_ = 0;
    486   pos_ = 0;
    487   InitializeAstVisitor(isolate);
    488 }
    489 
    490 
    491 PrettyPrinter::~PrettyPrinter() {
    492   DeleteArray(output_);
    493 }
    494 
    495 
    496 void PrettyPrinter::VisitBlock(Block* node) {
    497   if (!node->ignore_completion_value()) Print("{ ");
    498   PrintStatements(node->statements());
    499   if (node->statements()->length() > 0) Print(" ");
    500   if (!node->ignore_completion_value()) Print("}");
    501 }
    502 
    503 
    504 void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
    505   Print("var ");
    506   PrintLiteral(node->proxy()->name(), false);
    507   Print(";");
    508 }
    509 
    510 
    511 void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
    512   Print("function ");
    513   PrintLiteral(node->proxy()->name(), false);
    514   Print(" = ");
    515   PrintFunctionLiteral(node->fun());
    516   Print(";");
    517 }
    518 
    519 
    520 void PrettyPrinter::VisitImportDeclaration(ImportDeclaration* node) {
    521   Print("import ");
    522   PrintLiteral(node->proxy()->name(), false);
    523   Print(" from ");
    524   PrintLiteral(node->module_specifier()->string(), true);
    525   Print(";");
    526 }
    527 
    528 
    529 void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) {
    530   Print("export ");
    531   PrintLiteral(node->proxy()->name(), false);
    532   Print(";");
    533 }
    534 
    535 
    536 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
    537   Visit(node->expression());
    538   Print(";");
    539 }
    540 
    541 
    542 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
    543   Print(";");
    544 }
    545 
    546 
    547 void PrettyPrinter::VisitSloppyBlockFunctionStatement(
    548     SloppyBlockFunctionStatement* node) {
    549   Visit(node->statement());
    550 }
    551 
    552 
    553 void PrettyPrinter::VisitIfStatement(IfStatement* node) {
    554   Print("if (");
    555   Visit(node->condition());
    556   Print(") ");
    557   Visit(node->then_statement());
    558   if (node->HasElseStatement()) {
    559     Print(" else ");
    560     Visit(node->else_statement());
    561   }
    562 }
    563 
    564 
    565 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
    566   Print("continue");
    567   ZoneList<const AstRawString*>* labels = node->target()->labels();
    568   if (labels != NULL) {
    569     Print(" ");
    570     DCHECK(labels->length() > 0);  // guaranteed to have at least one entry
    571     PrintLiteral(labels->at(0), false);  // any label from the list is fine
    572   }
    573   Print(";");
    574 }
    575 
    576 
    577 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
    578   Print("break");
    579   ZoneList<const AstRawString*>* labels = node->target()->labels();
    580   if (labels != NULL) {
    581     Print(" ");
    582     DCHECK(labels->length() > 0);  // guaranteed to have at least one entry
    583     PrintLiteral(labels->at(0), false);  // any label from the list is fine
    584   }
    585   Print(";");
    586 }
    587 
    588 
    589 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
    590   Print("return ");
    591   Visit(node->expression());
    592   Print(";");
    593 }
    594 
    595 
    596 void PrettyPrinter::VisitWithStatement(WithStatement* node) {
    597   Print("with (");
    598   Visit(node->expression());
    599   Print(") ");
    600   Visit(node->statement());
    601 }
    602 
    603 
    604 void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) {
    605   PrintLabels(node->labels());
    606   Print("switch (");
    607   Visit(node->tag());
    608   Print(") { ");
    609   ZoneList<CaseClause*>* cases = node->cases();
    610   for (int i = 0; i < cases->length(); i++)
    611     Visit(cases->at(i));
    612   Print("}");
    613 }
    614 
    615 
    616 void PrettyPrinter::VisitCaseClause(CaseClause* clause) {
    617   if (clause->is_default()) {
    618     Print("default");
    619   } else {
    620     Print("case ");
    621     Visit(clause->label());
    622   }
    623   Print(": ");
    624   PrintStatements(clause->statements());
    625   if (clause->statements()->length() > 0)
    626     Print(" ");
    627 }
    628 
    629 
    630 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
    631   PrintLabels(node->labels());
    632   Print("do ");
    633   Visit(node->body());
    634   Print(" while (");
    635   Visit(node->cond());
    636   Print(");");
    637 }
    638 
    639 
    640 void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
    641   PrintLabels(node->labels());
    642   Print("while (");
    643   Visit(node->cond());
    644   Print(") ");
    645   Visit(node->body());
    646 }
    647 
    648 
    649 void PrettyPrinter::VisitForStatement(ForStatement* node) {
    650   PrintLabels(node->labels());
    651   Print("for (");
    652   if (node->init() != NULL) {
    653     Visit(node->init());
    654     Print(" ");
    655   } else {
    656     Print("; ");
    657   }
    658   if (node->cond() != NULL) Visit(node->cond());
    659   Print("; ");
    660   if (node->next() != NULL) {
    661     Visit(node->next());  // prints extra ';', unfortunately
    662     // to fix: should use Expression for next
    663   }
    664   Print(") ");
    665   Visit(node->body());
    666 }
    667 
    668 
    669 void PrettyPrinter::VisitForInStatement(ForInStatement* node) {
    670   PrintLabels(node->labels());
    671   Print("for (");
    672   Visit(node->each());
    673   Print(" in ");
    674   Visit(node->enumerable());
    675   Print(") ");
    676   Visit(node->body());
    677 }
    678 
    679 
    680 void PrettyPrinter::VisitForOfStatement(ForOfStatement* node) {
    681   // TODO(adamk): ForOf is largely desugared as part of parsing,
    682   // so it's hard to display useful stuff here. Should likely
    683   // either bite the bullet and display less or try harder
    684   // to preserve more.
    685   PrintLabels(node->labels());
    686   // The <each> is embedded inside a do-expression by the time we get here.
    687   Print("for (<each> of ");
    688   if (node->assign_iterator()->IsAssignment() &&
    689       node->assign_iterator()->AsAssignment()->value()->IsCall() &&
    690       node->assign_iterator()
    691           ->AsAssignment()
    692           ->value()
    693           ->AsCall()
    694           ->expression()
    695           ->IsProperty() &&
    696       node->assign_iterator()
    697           ->AsAssignment()
    698           ->value()
    699           ->AsCall()
    700           ->expression()
    701           ->IsProperty()) {
    702     Visit(node->assign_iterator()
    703               ->AsAssignment()
    704               ->value()
    705               ->AsCall()
    706               ->expression()
    707               ->AsProperty()
    708               ->obj());
    709   } else {
    710     Print("<iterable>");
    711   }
    712   Print(") ");
    713   Visit(node->body());
    714 }
    715 
    716 
    717 void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
    718   Print("try ");
    719   Visit(node->try_block());
    720   Print(" catch (");
    721   const bool quote = false;
    722   PrintLiteral(node->variable()->name(), quote);
    723   Print(") ");
    724   Visit(node->catch_block());
    725 }
    726 
    727 
    728 void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    729   Print("try ");
    730   Visit(node->try_block());
    731   Print(" finally ");
    732   Visit(node->finally_block());
    733 }
    734 
    735 
    736 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
    737   Print("debugger ");
    738 }
    739 
    740 
    741 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    742   Print("(");
    743   PrintFunctionLiteral(node);
    744   Print(")");
    745 }
    746 
    747 
    748 void PrettyPrinter::VisitClassLiteral(ClassLiteral* node) {
    749   Print("(class ");
    750   PrintLiteral(node->constructor()->name(), false);
    751   if (node->extends()) {
    752     Print(" extends ");
    753     Visit(node->extends());
    754   }
    755   Print(" { ");
    756   for (int i = 0; i < node->properties()->length(); i++) {
    757     PrintObjectLiteralProperty(node->properties()->at(i));
    758   }
    759   Print(" })");
    760 }
    761 
    762 
    763 void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
    764   Print("(");
    765   PrintLiteral(node->name(), false);
    766   Print(")");
    767 }
    768 
    769 
    770 void PrettyPrinter::VisitDoExpression(DoExpression* node) {
    771   Print("(do {");
    772   PrintStatements(node->block()->statements());
    773   Print("})");
    774 }
    775 
    776 
    777 void PrettyPrinter::VisitConditional(Conditional* node) {
    778   Visit(node->condition());
    779   Print(" ? ");
    780   Visit(node->then_expression());
    781   Print(" : ");
    782   Visit(node->else_expression());
    783 }
    784 
    785 
    786 void PrettyPrinter::VisitLiteral(Literal* node) {
    787   PrintLiteral(node->value(), true);
    788 }
    789 
    790 
    791 void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
    792   Print(" RegExp(");
    793   PrintLiteral(node->pattern(), false);
    794   Print(",");
    795   if (node->flags() & RegExp::kGlobal) Print("g");
    796   if (node->flags() & RegExp::kIgnoreCase) Print("i");
    797   if (node->flags() & RegExp::kMultiline) Print("m");
    798   if (node->flags() & RegExp::kUnicode) Print("u");
    799   if (node->flags() & RegExp::kSticky) Print("y");
    800   Print(") ");
    801 }
    802 
    803 
    804 void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
    805   Print("{ ");
    806   for (int i = 0; i < node->properties()->length(); i++) {
    807     if (i != 0) Print(",");
    808     PrintObjectLiteralProperty(node->properties()->at(i));
    809   }
    810   Print(" }");
    811 }
    812 
    813 
    814 void PrettyPrinter::PrintObjectLiteralProperty(
    815     ObjectLiteralProperty* property) {
    816   // TODO(arv): Better printing of methods etc.
    817   Print(" ");
    818   Visit(property->key());
    819   Print(": ");
    820   Visit(property->value());
    821 }
    822 
    823 
    824 void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
    825   Print("[ ");
    826   Print(" literal_index = %d", node->literal_index());
    827   for (int i = 0; i < node->values()->length(); i++) {
    828     if (i != 0) Print(",");
    829     Visit(node->values()->at(i));
    830   }
    831   Print(" ]");
    832 }
    833 
    834 
    835 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
    836   PrintLiteral(node->name(), false);
    837 }
    838 
    839 
    840 void PrettyPrinter::VisitAssignment(Assignment* node) {
    841   Visit(node->target());
    842   Print(" %s ", Token::String(node->op()));
    843   Visit(node->value());
    844 }
    845 
    846 
    847 void PrettyPrinter::VisitYield(Yield* node) {
    848   Print("yield ");
    849   Visit(node->expression());
    850 }
    851 
    852 
    853 void PrettyPrinter::VisitThrow(Throw* node) {
    854   Print("throw ");
    855   Visit(node->exception());
    856 }
    857 
    858 
    859 void PrettyPrinter::VisitProperty(Property* node) {
    860   Expression* key = node->key();
    861   Literal* literal = key->AsLiteral();
    862   if (literal != NULL && literal->value()->IsInternalizedString()) {
    863     Print("(");
    864     Visit(node->obj());
    865     Print(").");
    866     PrintLiteral(literal->value(), false);
    867   } else {
    868     Visit(node->obj());
    869     Print("[");
    870     Visit(key);
    871     Print("]");
    872   }
    873 }
    874 
    875 
    876 void PrettyPrinter::VisitCall(Call* node) {
    877   Visit(node->expression());
    878   PrintArguments(node->arguments());
    879 }
    880 
    881 
    882 void PrettyPrinter::VisitCallNew(CallNew* node) {
    883   Print("new (");
    884   Visit(node->expression());
    885   Print(")");
    886   PrintArguments(node->arguments());
    887 }
    888 
    889 
    890 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
    891   Print("%%%s\n", node->debug_name());
    892   PrintArguments(node->arguments());
    893 }
    894 
    895 
    896 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) {
    897   Token::Value op = node->op();
    898   bool needsSpace =
    899       op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
    900   Print("(%s%s", Token::String(op), needsSpace ? " " : "");
    901   Visit(node->expression());
    902   Print(")");
    903 }
    904 
    905 
    906 void PrettyPrinter::VisitCountOperation(CountOperation* node) {
    907   Print("(");
    908   if (node->is_prefix()) Print("%s", Token::String(node->op()));
    909   Visit(node->expression());
    910   if (node->is_postfix()) Print("%s", Token::String(node->op()));
    911   Print(")");
    912 }
    913 
    914 
    915 void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) {
    916   Print("(");
    917   Visit(node->left());
    918   Print(" %s ", Token::String(node->op()));
    919   Visit(node->right());
    920   Print(")");
    921 }
    922 
    923 
    924 void PrettyPrinter::VisitCompareOperation(CompareOperation* node) {
    925   Print("(");
    926   Visit(node->left());
    927   Print(" %s ", Token::String(node->op()));
    928   Visit(node->right());
    929   Print(")");
    930 }
    931 
    932 
    933 void PrettyPrinter::VisitSpread(Spread* node) {
    934   Print("(...");
    935   Visit(node->expression());
    936   Print(")");
    937 }
    938 
    939 
    940 void PrettyPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
    941   Print("()");
    942 }
    943 
    944 
    945 void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
    946   Print("<this-function>");
    947 }
    948 
    949 
    950 void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
    951   Print("<super-property-reference>");
    952 }
    953 
    954 
    955 void PrettyPrinter::VisitSuperCallReference(SuperCallReference* node) {
    956   Print("<super-call-reference>");
    957 }
    958 
    959 
    960 void PrettyPrinter::VisitRewritableExpression(RewritableExpression* node) {
    961   Visit(node->expression());
    962 }
    963 
    964 
    965 const char* PrettyPrinter::Print(AstNode* node) {
    966   Init();
    967   Visit(node);
    968   return output_;
    969 }
    970 
    971 
    972 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
    973   Init();
    974   ExpressionStatement* statement =
    975     program->body()->at(0)->AsExpressionStatement();
    976   Visit(statement->expression());
    977   return output_;
    978 }
    979 
    980 
    981 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
    982   Init();
    983   PrintStatements(program->body());
    984   Print("\n");
    985   return output_;
    986 }
    987 
    988 
    989 void PrettyPrinter::PrintOut(Isolate* isolate, AstNode* node) {
    990   PrettyPrinter printer(isolate);
    991   PrintF("%s\n", printer.Print(node));
    992 }
    993 
    994 
    995 void PrettyPrinter::Init() {
    996   if (size_ == 0) {
    997     DCHECK(output_ == NULL);
    998     const int initial_size = 256;
    999     output_ = NewArray<char>(initial_size);
   1000     size_ = initial_size;
   1001   }
   1002   output_[0] = '\0';
   1003   pos_ = 0;
   1004 }
   1005 
   1006 
   1007 void PrettyPrinter::Print(const char* format, ...) {
   1008   for (;;) {
   1009     va_list arguments;
   1010     va_start(arguments, format);
   1011     int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
   1012                       format,
   1013                       arguments);
   1014     va_end(arguments);
   1015 
   1016     if (n >= 0) {
   1017       // there was enough space - we are done
   1018       pos_ += n;
   1019       return;
   1020     } else {
   1021       // there was not enough space - allocate more and try again
   1022       const int slack = 32;
   1023       int new_size = size_ + (size_ >> 1) + slack;
   1024       char* new_output = NewArray<char>(new_size);
   1025       MemCopy(new_output, output_, pos_);
   1026       DeleteArray(output_);
   1027       output_ = new_output;
   1028       size_ = new_size;
   1029     }
   1030   }
   1031 }
   1032 
   1033 
   1034 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
   1035   if (statements == NULL) return;
   1036   for (int i = 0; i < statements->length(); i++) {
   1037     if (i != 0) Print(" ");
   1038     Visit(statements->at(i));
   1039   }
   1040 }
   1041 
   1042 
   1043 void PrettyPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) {
   1044   if (labels != NULL) {
   1045     for (int i = 0; i < labels->length(); i++) {
   1046       PrintLiteral(labels->at(i), false);
   1047       Print(": ");
   1048     }
   1049   }
   1050 }
   1051 
   1052 
   1053 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
   1054   Print("(");
   1055   for (int i = 0; i < arguments->length(); i++) {
   1056     if (i != 0) Print(", ");
   1057     Visit(arguments->at(i));
   1058   }
   1059   Print(")");
   1060 }
   1061 
   1062 
   1063 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
   1064   Object* object = *value;
   1065   if (object->IsString()) {
   1066     String* string = String::cast(object);
   1067     if (quote) Print("\"");
   1068     for (int i = 0; i < string->length(); i++) {
   1069       Print("%c", string->Get(i));
   1070     }
   1071     if (quote) Print("\"");
   1072   } else if (object->IsNull(isolate_)) {
   1073     Print("null");
   1074   } else if (object->IsTrue(isolate_)) {
   1075     Print("true");
   1076   } else if (object->IsFalse(isolate_)) {
   1077     Print("false");
   1078   } else if (object->IsUndefined(isolate_)) {
   1079     Print("undefined");
   1080   } else if (object->IsNumber()) {
   1081     Print("%g", object->Number());
   1082   } else if (object->IsJSObject()) {
   1083     // regular expression
   1084     if (object->IsJSFunction()) {
   1085       Print("JS-Function");
   1086     } else if (object->IsJSArray()) {
   1087       Print("JS-array[%u]",
   1088             Smi::cast(JSArray::cast(object)->length())->value());
   1089     } else if (object->IsJSObject()) {
   1090       Print("JS-Object");
   1091     } else {
   1092       Print("?UNKNOWN?");
   1093     }
   1094   } else if (object->IsFixedArray()) {
   1095     Print("FixedArray");
   1096   } else {
   1097     Print("<unknown literal %p>", static_cast<void*>(object));
   1098   }
   1099 }
   1100 
   1101 
   1102 void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) {
   1103   PrintLiteral(value->string(), quote);
   1104 }
   1105 
   1106 
   1107 void PrettyPrinter::PrintParameters(Scope* scope) {
   1108   Print("(");
   1109   for (int i = 0; i < scope->num_parameters(); i++) {
   1110     if (i  > 0) Print(", ");
   1111     PrintLiteral(scope->parameter(i)->name(), false);
   1112   }
   1113   Print(")");
   1114 }
   1115 
   1116 
   1117 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
   1118   for (int i = 0; i < declarations->length(); i++) {
   1119     if (i > 0) Print(" ");
   1120     Visit(declarations->at(i));
   1121   }
   1122 }
   1123 
   1124 
   1125 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
   1126   Print("function ");
   1127   PrintLiteral(function->name(), false);
   1128   PrintParameters(function->scope());
   1129   Print(" { ");
   1130   PrintDeclarations(function->scope()->declarations());
   1131   PrintStatements(function->body());
   1132   Print(" }");
   1133 }
   1134 
   1135 
   1136 //-----------------------------------------------------------------------------
   1137 
   1138 class IndentedScope BASE_EMBEDDED {
   1139  public:
   1140   IndentedScope(AstPrinter* printer, const char* txt)
   1141       : ast_printer_(printer) {
   1142     ast_printer_->PrintIndented(txt);
   1143     ast_printer_->Print("\n");
   1144     ast_printer_->inc_indent();
   1145   }
   1146 
   1147   IndentedScope(AstPrinter* printer, const char* txt, int pos)
   1148       : ast_printer_(printer) {
   1149     ast_printer_->PrintIndented(txt);
   1150     ast_printer_->Print(" at %d\n", pos);
   1151     ast_printer_->inc_indent();
   1152   }
   1153 
   1154   virtual ~IndentedScope() {
   1155     ast_printer_->dec_indent();
   1156   }
   1157 
   1158  private:
   1159   AstPrinter* ast_printer_;
   1160 };
   1161 
   1162 
   1163 //-----------------------------------------------------------------------------
   1164 
   1165 
   1166 AstPrinter::AstPrinter(Isolate* isolate) : PrettyPrinter(isolate), indent_(0) {}
   1167 
   1168 
   1169 AstPrinter::~AstPrinter() {
   1170   DCHECK(indent_ == 0);
   1171 }
   1172 
   1173 
   1174 void AstPrinter::PrintIndented(const char* txt) {
   1175   for (int i = 0; i < indent_; i++) {
   1176     Print(". ");
   1177   }
   1178   Print("%s", txt);
   1179 }
   1180 
   1181 
   1182 void AstPrinter::PrintLiteralIndented(const char* info,
   1183                                       Handle<Object> value,
   1184                                       bool quote) {
   1185   PrintIndented(info);
   1186   Print(" ");
   1187   PrintLiteral(value, quote);
   1188   Print("\n");
   1189 }
   1190 
   1191 
   1192 void AstPrinter::PrintLiteralWithModeIndented(const char* info,
   1193                                               Variable* var,
   1194                                               Handle<Object> value) {
   1195   if (var == NULL) {
   1196     PrintLiteralIndented(info, value, true);
   1197   } else {
   1198     EmbeddedVector<char, 256> buf;
   1199     int pos = SNPrintF(buf, "%s (mode = %s", info,
   1200                        Variable::Mode2String(var->mode()));
   1201     SNPrintF(buf + pos, ")");
   1202     PrintLiteralIndented(buf.start(), value, true);
   1203   }
   1204 }
   1205 
   1206 
   1207 void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) {
   1208   if (labels == NULL || labels->length() == 0) return;
   1209   PrintIndented("LABELS ");
   1210   PrintLabels(labels);
   1211   Print("\n");
   1212 }
   1213 
   1214 
   1215 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
   1216   IndentedScope indent(this, s, node->position());
   1217   Visit(node);
   1218 }
   1219 
   1220 
   1221 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
   1222   Init();
   1223   { IndentedScope indent(this, "FUNC", program->position());
   1224     PrintIndented("KIND");
   1225     Print(" %d\n", program->kind());
   1226     PrintIndented("YIELD COUNT");
   1227     Print(" %d\n", program->yield_count());
   1228     PrintLiteralIndented("NAME", program->name(), true);
   1229     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
   1230     PrintParameters(program->scope());
   1231     PrintDeclarations(program->scope()->declarations());
   1232     PrintStatements(program->body());
   1233   }
   1234   return Output();
   1235 }
   1236 
   1237 
   1238 void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) {
   1239   AstPrinter printer(isolate);
   1240   printer.Init();
   1241   printer.Visit(node);
   1242   PrintF("%s", printer.Output());
   1243 }
   1244 
   1245 
   1246 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
   1247   if (declarations->length() > 0) {
   1248     IndentedScope indent(this, "DECLS");
   1249     for (int i = 0; i < declarations->length(); i++) {
   1250       Visit(declarations->at(i));
   1251     }
   1252   }
   1253 }
   1254 
   1255 
   1256 void AstPrinter::PrintParameters(Scope* scope) {
   1257   if (scope->num_parameters() > 0) {
   1258     IndentedScope indent(this, "PARAMS");
   1259     for (int i = 0; i < scope->num_parameters(); i++) {
   1260       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
   1261                                    scope->parameter(i)->name());
   1262     }
   1263   }
   1264 }
   1265 
   1266 
   1267 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
   1268   for (int i = 0; i < statements->length(); i++) {
   1269     Visit(statements->at(i));
   1270   }
   1271 }
   1272 
   1273 
   1274 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
   1275   for (int i = 0; i < arguments->length(); i++) {
   1276     Visit(arguments->at(i));
   1277   }
   1278 }
   1279 
   1280 
   1281 void AstPrinter::VisitBlock(Block* node) {
   1282   const char* block_txt =
   1283       node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK";
   1284   IndentedScope indent(this, block_txt, node->position());
   1285   PrintStatements(node->statements());
   1286 }
   1287 
   1288 
   1289 // TODO(svenpanne) Start with IndentedScope.
   1290 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
   1291   PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
   1292                                node->proxy()->var(),
   1293                                node->proxy()->name());
   1294 }
   1295 
   1296 
   1297 // TODO(svenpanne) Start with IndentedScope.
   1298 void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
   1299   PrintIndented("FUNCTION ");
   1300   PrintLiteral(node->proxy()->name(), true);
   1301   Print(" = function ");
   1302   PrintLiteral(node->fun()->name(), false);
   1303   Print("\n");
   1304 }
   1305 
   1306 
   1307 void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
   1308   IndentedScope indent(this, "IMPORT", node->position());
   1309   PrintLiteralIndented("NAME", node->proxy()->name(), true);
   1310   PrintLiteralIndented("FROM", node->module_specifier()->string(), true);
   1311 }
   1312 
   1313 
   1314 void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
   1315   IndentedScope indent(this, "EXPORT", node->position());
   1316   PrintLiteral(node->proxy()->name(), true);
   1317 }
   1318 
   1319 
   1320 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
   1321   IndentedScope indent(this, "EXPRESSION STATEMENT", node->position());
   1322   Visit(node->expression());
   1323 }
   1324 
   1325 
   1326 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
   1327   IndentedScope indent(this, "EMPTY", node->position());
   1328 }
   1329 
   1330 
   1331 void AstPrinter::VisitSloppyBlockFunctionStatement(
   1332     SloppyBlockFunctionStatement* node) {
   1333   Visit(node->statement());
   1334 }
   1335 
   1336 
   1337 void AstPrinter::VisitIfStatement(IfStatement* node) {
   1338   IndentedScope indent(this, "IF", node->position());
   1339   PrintIndentedVisit("CONDITION", node->condition());
   1340   PrintIndentedVisit("THEN", node->then_statement());
   1341   if (node->HasElseStatement()) {
   1342     PrintIndentedVisit("ELSE", node->else_statement());
   1343   }
   1344 }
   1345 
   1346 
   1347 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
   1348   IndentedScope indent(this, "CONTINUE", node->position());
   1349   PrintLabelsIndented(node->target()->labels());
   1350 }
   1351 
   1352 
   1353 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
   1354   IndentedScope indent(this, "BREAK", node->position());
   1355   PrintLabelsIndented(node->target()->labels());
   1356 }
   1357 
   1358 
   1359 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
   1360   IndentedScope indent(this, "RETURN", node->position());
   1361   Visit(node->expression());
   1362 }
   1363 
   1364 
   1365 void AstPrinter::VisitWithStatement(WithStatement* node) {
   1366   IndentedScope indent(this, "WITH", node->position());
   1367   PrintIndentedVisit("OBJECT", node->expression());
   1368   PrintIndentedVisit("BODY", node->statement());
   1369 }
   1370 
   1371 
   1372 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
   1373   IndentedScope indent(this, "SWITCH", node->position());
   1374   PrintLabelsIndented(node->labels());
   1375   PrintIndentedVisit("TAG", node->tag());
   1376   for (int i = 0; i < node->cases()->length(); i++) {
   1377     Visit(node->cases()->at(i));
   1378   }
   1379 }
   1380 
   1381 
   1382 void AstPrinter::VisitCaseClause(CaseClause* clause) {
   1383   if (clause->is_default()) {
   1384     IndentedScope indent(this, "DEFAULT", clause->position());
   1385     PrintStatements(clause->statements());
   1386   } else {
   1387     IndentedScope indent(this, "CASE", clause->position());
   1388     Visit(clause->label());
   1389     PrintStatements(clause->statements());
   1390   }
   1391 }
   1392 
   1393 
   1394 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
   1395   IndentedScope indent(this, "DO", node->position());
   1396   PrintIndented("YIELD COUNT");
   1397   Print(" %d\n", node->yield_count());
   1398   PrintLabelsIndented(node->labels());
   1399   PrintIndentedVisit("BODY", node->body());
   1400   PrintIndentedVisit("COND", node->cond());
   1401 }
   1402 
   1403 
   1404 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
   1405   IndentedScope indent(this, "WHILE", node->position());
   1406   PrintIndented("YIELD COUNT");
   1407   Print(" %d\n", node->yield_count());
   1408   PrintLabelsIndented(node->labels());
   1409   PrintIndentedVisit("COND", node->cond());
   1410   PrintIndentedVisit("BODY", node->body());
   1411 }
   1412 
   1413 
   1414 void AstPrinter::VisitForStatement(ForStatement* node) {
   1415   IndentedScope indent(this, "FOR", node->position());
   1416   PrintIndented("YIELD COUNT");
   1417   Print(" %d\n", node->yield_count());
   1418   PrintLabelsIndented(node->labels());
   1419   if (node->init()) PrintIndentedVisit("INIT", node->init());
   1420   if (node->cond()) PrintIndentedVisit("COND", node->cond());
   1421   PrintIndentedVisit("BODY", node->body());
   1422   if (node->next()) PrintIndentedVisit("NEXT", node->next());
   1423 }
   1424 
   1425 
   1426 void AstPrinter::VisitForInStatement(ForInStatement* node) {
   1427   IndentedScope indent(this, "FOR IN", node->position());
   1428   PrintIndented("YIELD COUNT");
   1429   Print(" %d\n", node->yield_count());
   1430   PrintIndentedVisit("FOR", node->each());
   1431   PrintIndentedVisit("IN", node->enumerable());
   1432   PrintIndentedVisit("BODY", node->body());
   1433 }
   1434 
   1435 
   1436 void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
   1437   IndentedScope indent(this, "FOR OF", node->position());
   1438   PrintIndented("YIELD COUNT");
   1439   Print(" %d\n", node->yield_count());
   1440   PrintIndentedVisit("INIT", node->assign_iterator());
   1441   PrintIndentedVisit("NEXT", node->next_result());
   1442   PrintIndentedVisit("DONE", node->result_done());
   1443   PrintIndentedVisit("EACH", node->assign_each());
   1444   PrintIndentedVisit("BODY", node->body());
   1445 }
   1446 
   1447 
   1448 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
   1449   IndentedScope indent(this, "TRY CATCH", node->position());
   1450   PrintIndentedVisit("TRY", node->try_block());
   1451   PrintLiteralWithModeIndented("CATCHVAR",
   1452                                node->variable(),
   1453                                node->variable()->name());
   1454   PrintIndentedVisit("CATCH", node->catch_block());
   1455 }
   1456 
   1457 
   1458 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
   1459   IndentedScope indent(this, "TRY FINALLY", node->position());
   1460   PrintIndentedVisit("TRY", node->try_block());
   1461   PrintIndentedVisit("FINALLY", node->finally_block());
   1462 }
   1463 
   1464 
   1465 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
   1466   IndentedScope indent(this, "DEBUGGER", node->position());
   1467 }
   1468 
   1469 
   1470 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
   1471   IndentedScope indent(this, "FUNC LITERAL", node->position());
   1472   PrintLiteralIndented("NAME", node->name(), false);
   1473   PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
   1474   PrintParameters(node->scope());
   1475   // We don't want to see the function literal in this case: it
   1476   // will be printed via PrintProgram when the code for it is
   1477   // generated.
   1478   // PrintStatements(node->body());
   1479 }
   1480 
   1481 
   1482 void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
   1483   IndentedScope indent(this, "CLASS LITERAL", node->position());
   1484   PrintLiteralIndented("NAME", node->constructor()->name(), false);
   1485   if (node->extends() != nullptr) {
   1486     PrintIndentedVisit("EXTENDS", node->extends());
   1487   }
   1488   PrintProperties(node->properties());
   1489 }
   1490 
   1491 
   1492 void AstPrinter::PrintProperties(
   1493     ZoneList<ObjectLiteral::Property*>* properties) {
   1494   for (int i = 0; i < properties->length(); i++) {
   1495     ObjectLiteral::Property* property = properties->at(i);
   1496     const char* prop_kind = nullptr;
   1497     switch (property->kind()) {
   1498       case ObjectLiteral::Property::CONSTANT:
   1499         prop_kind = "CONSTANT";
   1500         break;
   1501       case ObjectLiteral::Property::COMPUTED:
   1502         prop_kind = "COMPUTED";
   1503         break;
   1504       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   1505         prop_kind = "MATERIALIZED_LITERAL";
   1506         break;
   1507       case ObjectLiteral::Property::PROTOTYPE:
   1508         prop_kind = "PROTOTYPE";
   1509         break;
   1510       case ObjectLiteral::Property::GETTER:
   1511         prop_kind = "GETTER";
   1512         break;
   1513       case ObjectLiteral::Property::SETTER:
   1514         prop_kind = "SETTER";
   1515         break;
   1516     }
   1517     EmbeddedVector<char, 128> buf;
   1518     SNPrintF(buf, "PROPERTY%s - %s", property->is_static() ? " - STATIC" : "",
   1519              prop_kind);
   1520     IndentedScope prop(this, buf.start());
   1521     PrintIndentedVisit("KEY", properties->at(i)->key());
   1522     PrintIndentedVisit("VALUE", properties->at(i)->value());
   1523   }
   1524 }
   1525 
   1526 
   1527 void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
   1528   IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position());
   1529   PrintLiteralIndented("NAME", node->name(), false);
   1530 }
   1531 
   1532 
   1533 void AstPrinter::VisitDoExpression(DoExpression* node) {
   1534   IndentedScope indent(this, "DO EXPRESSION", node->position());
   1535   PrintStatements(node->block()->statements());
   1536 }
   1537 
   1538 
   1539 void AstPrinter::VisitConditional(Conditional* node) {
   1540   IndentedScope indent(this, "CONDITIONAL", node->position());
   1541   PrintIndentedVisit("CONDITION", node->condition());
   1542   PrintIndentedVisit("THEN", node->then_expression());
   1543   PrintIndentedVisit("ELSE", node->else_expression());
   1544 }
   1545 
   1546 
   1547 // TODO(svenpanne) Start with IndentedScope.
   1548 void AstPrinter::VisitLiteral(Literal* node) {
   1549   PrintLiteralIndented("LITERAL", node->value(), true);
   1550 }
   1551 
   1552 
   1553 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
   1554   IndentedScope indent(this, "REGEXP LITERAL", node->position());
   1555   EmbeddedVector<char, 128> buf;
   1556   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
   1557   PrintIndented(buf.start());
   1558   PrintLiteralIndented("PATTERN", node->pattern(), false);
   1559   int i = 0;
   1560   if (node->flags() & RegExp::kGlobal) buf[i++] = 'g';
   1561   if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i';
   1562   if (node->flags() & RegExp::kMultiline) buf[i++] = 'm';
   1563   if (node->flags() & RegExp::kUnicode) buf[i++] = 'u';
   1564   if (node->flags() & RegExp::kSticky) buf[i++] = 'y';
   1565   buf[i] = '\0';
   1566   PrintIndented("FLAGS ");
   1567   Print("%s", buf.start());
   1568   Print("\n");
   1569 }
   1570 
   1571 
   1572 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
   1573   IndentedScope indent(this, "OBJ LITERAL", node->position());
   1574   EmbeddedVector<char, 128> buf;
   1575   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
   1576   PrintIndented(buf.start());
   1577   PrintProperties(node->properties());
   1578 }
   1579 
   1580 
   1581 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
   1582   IndentedScope indent(this, "ARRAY LITERAL", node->position());
   1583 
   1584   EmbeddedVector<char, 128> buf;
   1585   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
   1586   PrintIndented(buf.start());
   1587   if (node->values()->length() > 0) {
   1588     IndentedScope indent(this, "VALUES", node->position());
   1589     for (int i = 0; i < node->values()->length(); i++) {
   1590       Visit(node->values()->at(i));
   1591     }
   1592   }
   1593 }
   1594 
   1595 
   1596 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
   1597   EmbeddedVector<char, 128> buf;
   1598   int pos =
   1599       FormatSlotNode(&buf, node, "VAR PROXY", node->VariableFeedbackSlot());
   1600 
   1601   if (!node->is_resolved()) {
   1602     SNPrintF(buf + pos, " unresolved");
   1603     PrintLiteralWithModeIndented(buf.start(), nullptr, node->name());
   1604   } else {
   1605     Variable* var = node->var();
   1606     switch (var->location()) {
   1607       case VariableLocation::UNALLOCATED:
   1608         SNPrintF(buf + pos, " unallocated");
   1609         break;
   1610       case VariableLocation::PARAMETER:
   1611         SNPrintF(buf + pos, " parameter[%d]", var->index());
   1612         break;
   1613       case VariableLocation::LOCAL:
   1614         SNPrintF(buf + pos, " local[%d]", var->index());
   1615         break;
   1616       case VariableLocation::CONTEXT:
   1617         SNPrintF(buf + pos, " context[%d]", var->index());
   1618         break;
   1619       case VariableLocation::GLOBAL:
   1620         SNPrintF(buf + pos, " global[%d]", var->index());
   1621         break;
   1622       case VariableLocation::LOOKUP:
   1623         SNPrintF(buf + pos, " lookup");
   1624         break;
   1625     }
   1626     PrintLiteralWithModeIndented(buf.start(), var, node->name());
   1627   }
   1628 }
   1629 
   1630 
   1631 void AstPrinter::VisitAssignment(Assignment* node) {
   1632   IndentedScope indent(this, Token::Name(node->op()), node->position());
   1633   Visit(node->target());
   1634   Visit(node->value());
   1635 }
   1636 
   1637 
   1638 void AstPrinter::VisitYield(Yield* node) {
   1639   EmbeddedVector<char, 128> buf;
   1640   SNPrintF(buf, "YIELD id %d", node->yield_id());
   1641   IndentedScope indent(this, buf.start(), node->position());
   1642   Visit(node->expression());
   1643 }
   1644 
   1645 
   1646 void AstPrinter::VisitThrow(Throw* node) {
   1647   IndentedScope indent(this, "THROW", node->position());
   1648   Visit(node->exception());
   1649 }
   1650 
   1651 
   1652 void AstPrinter::VisitProperty(Property* node) {
   1653   EmbeddedVector<char, 128> buf;
   1654   FormatSlotNode(&buf, node, "PROPERTY", node->PropertyFeedbackSlot());
   1655   IndentedScope indent(this, buf.start(), node->position());
   1656 
   1657   Visit(node->obj());
   1658   Literal* literal = node->key()->AsLiteral();
   1659   if (literal != NULL && literal->value()->IsInternalizedString()) {
   1660     PrintLiteralIndented("NAME", literal->value(), false);
   1661   } else {
   1662     PrintIndentedVisit("KEY", node->key());
   1663   }
   1664 }
   1665 
   1666 
   1667 void AstPrinter::VisitCall(Call* node) {
   1668   EmbeddedVector<char, 128> buf;
   1669   const char* name =
   1670       node->tail_call_mode() == TailCallMode::kAllow ? "TAIL CALL" : "CALL";
   1671   FormatSlotNode(&buf, node, name, node->CallFeedbackICSlot());
   1672   IndentedScope indent(this, buf.start());
   1673 
   1674   Visit(node->expression());
   1675   PrintArguments(node->arguments());
   1676 }
   1677 
   1678 
   1679 void AstPrinter::VisitCallNew(CallNew* node) {
   1680   IndentedScope indent(this, "CALL NEW", node->position());
   1681   Visit(node->expression());
   1682   PrintArguments(node->arguments());
   1683 }
   1684 
   1685 
   1686 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
   1687   EmbeddedVector<char, 128> buf;
   1688   SNPrintF(buf, "CALL RUNTIME %s", node->debug_name());
   1689   IndentedScope indent(this, buf.start(), node->position());
   1690   PrintArguments(node->arguments());
   1691 }
   1692 
   1693 
   1694 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
   1695   IndentedScope indent(this, Token::Name(node->op()), node->position());
   1696   Visit(node->expression());
   1697 }
   1698 
   1699 
   1700 void AstPrinter::VisitCountOperation(CountOperation* node) {
   1701   EmbeddedVector<char, 128> buf;
   1702   SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
   1703            Token::Name(node->op()));
   1704   IndentedScope indent(this, buf.start(), node->position());
   1705   Visit(node->expression());
   1706 }
   1707 
   1708 
   1709 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
   1710   IndentedScope indent(this, Token::Name(node->op()), node->position());
   1711   Visit(node->left());
   1712   Visit(node->right());
   1713 }
   1714 
   1715 
   1716 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
   1717   IndentedScope indent(this, Token::Name(node->op()), node->position());
   1718   Visit(node->left());
   1719   Visit(node->right());
   1720 }
   1721 
   1722 
   1723 void AstPrinter::VisitSpread(Spread* node) {
   1724   IndentedScope indent(this, "...", node->position());
   1725   Visit(node->expression());
   1726 }
   1727 
   1728 
   1729 void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
   1730   IndentedScope indent(this, "()", node->position());
   1731 }
   1732 
   1733 
   1734 void AstPrinter::VisitThisFunction(ThisFunction* node) {
   1735   IndentedScope indent(this, "THIS-FUNCTION", node->position());
   1736 }
   1737 
   1738 
   1739 void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
   1740   IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position());
   1741 }
   1742 
   1743 
   1744 void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
   1745   IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position());
   1746 }
   1747 
   1748 
   1749 void AstPrinter::VisitRewritableExpression(RewritableExpression* node) {
   1750   Visit(node->expression());
   1751 }
   1752 
   1753 
   1754 #endif  // DEBUG
   1755 
   1756 }  // namespace internal
   1757 }  // namespace v8
   1758