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