Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdarg.h>
     29 
     30 #include "v8.h"
     31 
     32 #include "prettyprinter.h"
     33 #include "scopes.h"
     34 #include "platform.h"
     35 
     36 namespace v8 {
     37 namespace internal {
     38 
     39 #ifdef DEBUG
     40 
     41 PrettyPrinter::PrettyPrinter() {
     42   output_ = NULL;
     43   size_ = 0;
     44   pos_ = 0;
     45 }
     46 
     47 
     48 PrettyPrinter::~PrettyPrinter() {
     49   DeleteArray(output_);
     50 }
     51 
     52 
     53 void PrettyPrinter::VisitBlock(Block* node) {
     54   if (!node->is_initializer_block()) Print("{ ");
     55   PrintStatements(node->statements());
     56   if (node->statements()->length() > 0) Print(" ");
     57   if (!node->is_initializer_block()) Print("}");
     58 }
     59 
     60 
     61 void PrettyPrinter::VisitDeclaration(Declaration* node) {
     62   Print("var ");
     63   PrintLiteral(node->proxy()->name(), false);
     64   if (node->fun() != NULL) {
     65     Print(" = ");
     66     PrintFunctionLiteral(node->fun());
     67   }
     68   Print(";");
     69 }
     70 
     71 
     72 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
     73   Visit(node->expression());
     74   Print(";");
     75 }
     76 
     77 
     78 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
     79   Print(";");
     80 }
     81 
     82 
     83 void PrettyPrinter::VisitIfStatement(IfStatement* node) {
     84   Print("if (");
     85   Visit(node->condition());
     86   Print(") ");
     87   Visit(node->then_statement());
     88   if (node->HasElseStatement()) {
     89     Print(" else ");
     90     Visit(node->else_statement());
     91   }
     92 }
     93 
     94 
     95 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
     96   Print("continue");
     97   ZoneStringList* labels = node->target()->labels();
     98   if (labels != NULL) {
     99     Print(" ");
    100     ASSERT(labels->length() > 0);  // guaranteed to have at least one entry
    101     PrintLiteral(labels->at(0), false);  // any label from the list is fine
    102   }
    103   Print(";");
    104 }
    105 
    106 
    107 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
    108   Print("break");
    109   ZoneStringList* labels = node->target()->labels();
    110   if (labels != NULL) {
    111     Print(" ");
    112     ASSERT(labels->length() > 0);  // guaranteed to have at least one entry
    113     PrintLiteral(labels->at(0), false);  // any label from the list is fine
    114   }
    115   Print(";");
    116 }
    117 
    118 
    119 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
    120   Print("return ");
    121   Visit(node->expression());
    122   Print(";");
    123 }
    124 
    125 
    126 void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
    127   Print("<enter with> (");
    128   Visit(node->expression());
    129   Print(") ");
    130 }
    131 
    132 
    133 void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) {
    134   Print("<exit with>");
    135 }
    136 
    137 
    138 void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) {
    139   PrintLabels(node->labels());
    140   Print("switch (");
    141   Visit(node->tag());
    142   Print(") { ");
    143   ZoneList<CaseClause*>* cases = node->cases();
    144   for (int i = 0; i < cases->length(); i++)
    145     PrintCaseClause(cases->at(i));
    146   Print("}");
    147 }
    148 
    149 
    150 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
    151   PrintLabels(node->labels());
    152   Print("do ");
    153   Visit(node->body());
    154   Print(" while (");
    155   Visit(node->cond());
    156   Print(");");
    157 }
    158 
    159 
    160 void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
    161   PrintLabels(node->labels());
    162   Print("while (");
    163   Visit(node->cond());
    164   Print(") ");
    165   Visit(node->body());
    166 }
    167 
    168 
    169 void PrettyPrinter::VisitForStatement(ForStatement* node) {
    170   PrintLabels(node->labels());
    171   Print("for (");
    172   if (node->init() != NULL) {
    173     Visit(node->init());
    174     Print(" ");
    175   } else {
    176     Print("; ");
    177   }
    178   if (node->cond() != NULL) Visit(node->cond());
    179   Print("; ");
    180   if (node->next() != NULL) {
    181     Visit(node->next());  // prints extra ';', unfortunately
    182     // to fix: should use Expression for next
    183   }
    184   Print(") ");
    185   Visit(node->body());
    186 }
    187 
    188 
    189 void PrettyPrinter::VisitForInStatement(ForInStatement* node) {
    190   PrintLabels(node->labels());
    191   Print("for (");
    192   Visit(node->each());
    193   Print(" in ");
    194   Visit(node->enumerable());
    195   Print(") ");
    196   Visit(node->body());
    197 }
    198 
    199 
    200 void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
    201   Print("try ");
    202   Visit(node->try_block());
    203   Print(" catch (");
    204   Visit(node->catch_var());
    205   Print(") ");
    206   Visit(node->catch_block());
    207 }
    208 
    209 
    210 void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    211   Print("try ");
    212   Visit(node->try_block());
    213   Print(" finally ");
    214   Visit(node->finally_block());
    215 }
    216 
    217 
    218 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
    219   Print("debugger ");
    220 }
    221 
    222 
    223 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    224   Print("(");
    225   PrintFunctionLiteral(node);
    226   Print(")");
    227 }
    228 
    229 
    230 void PrettyPrinter::VisitFunctionBoilerplateLiteral(
    231     FunctionBoilerplateLiteral* node) {
    232   Print("(");
    233   PrintLiteral(node->boilerplate(), true);
    234   Print(")");
    235 }
    236 
    237 
    238 void PrettyPrinter::VisitConditional(Conditional* node) {
    239   Visit(node->condition());
    240   Print(" ? ");
    241   Visit(node->then_expression());
    242   Print(" : ");
    243   Visit(node->else_expression());
    244 }
    245 
    246 
    247 void PrettyPrinter::VisitLiteral(Literal* node) {
    248   PrintLiteral(node->handle(), true);
    249 }
    250 
    251 
    252 void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
    253   Print(" RegExp(");
    254   PrintLiteral(node->pattern(), false);
    255   Print(",");
    256   PrintLiteral(node->flags(), false);
    257   Print(") ");
    258 }
    259 
    260 
    261 void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
    262   Print("{ ");
    263   for (int i = 0; i < node->properties()->length(); i++) {
    264     if (i != 0) Print(",");
    265     ObjectLiteral::Property* property = node->properties()->at(i);
    266     Print(" ");
    267     Visit(property->key());
    268     Print(": ");
    269     Visit(property->value());
    270   }
    271   Print(" }");
    272 }
    273 
    274 
    275 void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
    276   Print("[ ");
    277   for (int i = 0; i < node->values()->length(); i++) {
    278     if (i != 0) Print(",");
    279     Visit(node->values()->at(i));
    280   }
    281   Print(" ]");
    282 }
    283 
    284 
    285 void PrettyPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
    286   Print("{ ");
    287   Visit(node->key());
    288   Print(": ");
    289   Visit(node->value());
    290   Print(" }");
    291 }
    292 
    293 
    294 void PrettyPrinter::VisitSlot(Slot* node) {
    295   switch (node->type()) {
    296     case Slot::PARAMETER:
    297       Print("parameter[%d]", node->index());
    298       break;
    299     case Slot::LOCAL:
    300       Print("frame[%d]", node->index());
    301       break;
    302     case Slot::CONTEXT:
    303       Print(".context[%d]", node->index());
    304       break;
    305     case Slot::LOOKUP:
    306       Print(".context[");
    307       PrintLiteral(node->var()->name(), false);
    308       Print("]");
    309       break;
    310     default:
    311       UNREACHABLE();
    312   }
    313 }
    314 
    315 
    316 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
    317   PrintLiteral(node->name(), false);
    318 }
    319 
    320 
    321 void PrettyPrinter::VisitAssignment(Assignment* node) {
    322   Visit(node->target());
    323   Print(" %s ", Token::String(node->op()));
    324   Visit(node->value());
    325 }
    326 
    327 
    328 void PrettyPrinter::VisitThrow(Throw* node) {
    329   Print("throw ");
    330   Visit(node->exception());
    331 }
    332 
    333 
    334 void PrettyPrinter::VisitProperty(Property* node) {
    335   Expression* key = node->key();
    336   Literal* literal = key->AsLiteral();
    337   if (literal != NULL && literal->handle()->IsSymbol()) {
    338     Print("(");
    339     Visit(node->obj());
    340     Print(").");
    341     PrintLiteral(literal->handle(), false);
    342   } else {
    343     Visit(node->obj());
    344     Print("[");
    345     Visit(key);
    346     Print("]");
    347   }
    348 }
    349 
    350 
    351 void PrettyPrinter::VisitCall(Call* node) {
    352   Visit(node->expression());
    353   PrintArguments(node->arguments());
    354 }
    355 
    356 
    357 void PrettyPrinter::VisitCallNew(CallNew* node) {
    358   Print("new (");
    359   Visit(node->expression());
    360   Print(")");
    361   PrintArguments(node->arguments());
    362 }
    363 
    364 
    365 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
    366   Print("%%");
    367   PrintLiteral(node->name(), false);
    368   PrintArguments(node->arguments());
    369 }
    370 
    371 
    372 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) {
    373   Print("(%s", Token::String(node->op()));
    374   Visit(node->expression());
    375   Print(")");
    376 }
    377 
    378 
    379 void PrettyPrinter::VisitCountOperation(CountOperation* node) {
    380   Print("(");
    381   if (node->is_prefix()) Print("%s", Token::String(node->op()));
    382   Visit(node->expression());
    383   if (node->is_postfix()) Print("%s", Token::String(node->op()));
    384   Print(")");
    385 }
    386 
    387 
    388 void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) {
    389   Print("(");
    390   Visit(node->left());
    391   Print("%s", Token::String(node->op()));
    392   Visit(node->right());
    393   Print(")");
    394 }
    395 
    396 
    397 void PrettyPrinter::VisitCompareOperation(CompareOperation* node) {
    398   Print("(");
    399   Visit(node->left());
    400   Print("%s", Token::String(node->op()));
    401   Visit(node->right());
    402   Print(")");
    403 }
    404 
    405 
    406 void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
    407   Print("<this-function>");
    408 }
    409 
    410 
    411 const char* PrettyPrinter::Print(AstNode* node) {
    412   Init();
    413   Visit(node);
    414   return output_;
    415 }
    416 
    417 
    418 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
    419   Init();
    420   ExpressionStatement* statement =
    421     program->body()->at(0)->AsExpressionStatement();
    422   Visit(statement->expression());
    423   return output_;
    424 }
    425 
    426 
    427 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
    428   Init();
    429   PrintStatements(program->body());
    430   Print("\n");
    431   return output_;
    432 }
    433 
    434 
    435 void PrettyPrinter::PrintOut(AstNode* node) {
    436   PrettyPrinter printer;
    437   PrintF("%s", printer.Print(node));
    438 }
    439 
    440 
    441 void PrettyPrinter::Init() {
    442   if (size_ == 0) {
    443     ASSERT(output_ == NULL);
    444     const int initial_size = 256;
    445     output_ = NewArray<char>(initial_size);
    446     size_ = initial_size;
    447   }
    448   output_[0] = '\0';
    449   pos_ = 0;
    450 }
    451 
    452 
    453 void PrettyPrinter::Print(const char* format, ...) {
    454   for (;;) {
    455     va_list arguments;
    456     va_start(arguments, format);
    457     int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_,
    458                           format,
    459                           arguments);
    460     va_end(arguments);
    461 
    462     if (n >= 0) {
    463       // there was enough space - we are done
    464       pos_ += n;
    465       return;
    466     } else {
    467       // there was not enough space - allocate more and try again
    468       const int slack = 32;
    469       int new_size = size_ + (size_ >> 1) + slack;
    470       char* new_output = NewArray<char>(new_size);
    471       memcpy(new_output, output_, pos_);
    472       DeleteArray(output_);
    473       output_ = new_output;
    474       size_ = new_size;
    475     }
    476   }
    477 }
    478 
    479 
    480 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
    481   for (int i = 0; i < statements->length(); i++) {
    482     if (i != 0) Print(" ");
    483     Visit(statements->at(i));
    484   }
    485 }
    486 
    487 
    488 void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
    489   if (labels != NULL) {
    490     for (int i = 0; i < labels->length(); i++) {
    491       PrintLiteral(labels->at(i), false);
    492       Print(": ");
    493     }
    494   }
    495 }
    496 
    497 
    498 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
    499   Print("(");
    500   for (int i = 0; i < arguments->length(); i++) {
    501     if (i != 0) Print(", ");
    502     Visit(arguments->at(i));
    503   }
    504   Print(")");
    505 }
    506 
    507 
    508 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
    509   Object* object = *value;
    510   if (object->IsString()) {
    511     String* string = String::cast(object);
    512     if (quote) Print("\"");
    513     for (int i = 0; i < string->length(); i++) {
    514       Print("%c", string->Get(i));
    515     }
    516     if (quote) Print("\"");
    517   } else if (object == Heap::null_value()) {
    518     Print("null");
    519   } else if (object == Heap::true_value()) {
    520     Print("true");
    521   } else if (object == Heap::false_value()) {
    522     Print("false");
    523   } else if (object == Heap::undefined_value()) {
    524     Print("undefined");
    525   } else if (object->IsNumber()) {
    526     Print("%g", object->Number());
    527   } else if (object->IsJSObject()) {
    528     // regular expression
    529     if (object->IsJSFunction()) {
    530       Print("JS-Function");
    531     } else if (object->IsJSArray()) {
    532       Print("JS-array[%u]", JSArray::cast(object)->length());
    533     } else if (object->IsJSObject()) {
    534       Print("JS-Object");
    535     } else {
    536       Print("?UNKNOWN?");
    537     }
    538   } else if (object->IsFixedArray()) {
    539     Print("FixedArray");
    540   } else {
    541     Print("<unknown literal %p>", object);
    542   }
    543 }
    544 
    545 
    546 void PrettyPrinter::PrintParameters(Scope* scope) {
    547   Print("(");
    548   for (int i = 0; i < scope->num_parameters(); i++) {
    549     if (i  > 0) Print(", ");
    550     PrintLiteral(scope->parameter(i)->name(), false);
    551   }
    552   Print(")");
    553 }
    554 
    555 
    556 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
    557   for (int i = 0; i < declarations->length(); i++) {
    558     if (i > 0) Print(" ");
    559     Visit(declarations->at(i));
    560   }
    561 }
    562 
    563 
    564 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
    565   Print("function ");
    566   PrintLiteral(function->name(), false);
    567   PrintParameters(function->scope());
    568   Print(" { ");
    569   PrintDeclarations(function->scope()->declarations());
    570   PrintStatements(function->body());
    571   Print(" }");
    572 }
    573 
    574 
    575 void PrettyPrinter::PrintCaseClause(CaseClause* clause) {
    576   if (clause->is_default()) {
    577     Print("default");
    578   } else {
    579     Print("case ");
    580     Visit(clause->label());
    581   }
    582   Print(": ");
    583   PrintStatements(clause->statements());
    584   if (clause->statements()->length() > 0)
    585     Print(" ");
    586 }
    587 
    588 
    589 //-----------------------------------------------------------------------------
    590 
    591 class IndentedScope BASE_EMBEDDED {
    592  public:
    593   IndentedScope() {
    594     ast_printer_->inc_indent();
    595   }
    596 
    597   explicit IndentedScope(const char* txt, AstNode* node = NULL) {
    598     ast_printer_->PrintIndented(txt);
    599     if (node != NULL && node->AsExpression() != NULL) {
    600       Expression* expr = node->AsExpression();
    601       bool printed_first = false;
    602       if ((expr->type() != NULL) && (expr->type()->IsKnown())) {
    603         ast_printer_->Print(" (type = ");
    604         ast_printer_->Print(StaticType::Type2String(expr->type()));
    605         printed_first = true;
    606       }
    607       if (expr->num() != Expression::kNoLabel) {
    608         ast_printer_->Print(printed_first ? ", num = " : " (num = ");
    609         ast_printer_->Print("%d", expr->num());
    610         printed_first = true;
    611       }
    612       if (printed_first) ast_printer_->Print(")");
    613     }
    614     ast_printer_->Print("\n");
    615     ast_printer_->inc_indent();
    616   }
    617 
    618   virtual ~IndentedScope() {
    619     ast_printer_->dec_indent();
    620   }
    621 
    622   static void SetAstPrinter(AstPrinter* a) { ast_printer_ = a; }
    623 
    624  private:
    625   static AstPrinter* ast_printer_;
    626 };
    627 
    628 
    629 AstPrinter* IndentedScope::ast_printer_ = NULL;
    630 
    631 
    632 //-----------------------------------------------------------------------------
    633 
    634 int AstPrinter::indent_ = 0;
    635 
    636 
    637 AstPrinter::AstPrinter() {
    638   ASSERT(indent_ == 0);
    639   IndentedScope::SetAstPrinter(this);
    640 }
    641 
    642 
    643 AstPrinter::~AstPrinter() {
    644   ASSERT(indent_ == 0);
    645   IndentedScope::SetAstPrinter(NULL);
    646 }
    647 
    648 
    649 void AstPrinter::PrintIndented(const char* txt) {
    650   for (int i = 0; i < indent_; i++) {
    651     Print(". ");
    652   }
    653   Print(txt);
    654 }
    655 
    656 
    657 void AstPrinter::PrintLiteralIndented(const char* info,
    658                                       Handle<Object> value,
    659                                       bool quote) {
    660   PrintIndented(info);
    661   Print(" ");
    662   PrintLiteral(value, quote);
    663   Print("\n");
    664 }
    665 
    666 
    667 void AstPrinter::PrintLiteralWithModeIndented(const char* info,
    668                                               Variable* var,
    669                                               Handle<Object> value,
    670                                               StaticType* type,
    671                                               int num) {
    672   if (var == NULL) {
    673     PrintLiteralIndented(info, value, true);
    674   } else {
    675     EmbeddedVector<char, 256> buf;
    676     int pos = OS::SNPrintF(buf, "%s (mode = %s", info,
    677                            Variable::Mode2String(var->mode()));
    678     if (type->IsKnown()) {
    679       pos += OS::SNPrintF(buf + pos, ", type = %s",
    680                           StaticType::Type2String(type));
    681     }
    682     if (num != Expression::kNoLabel) {
    683       pos += OS::SNPrintF(buf + pos, ", num = %d", num);
    684     }
    685     OS::SNPrintF(buf + pos, ")");
    686     PrintLiteralIndented(buf.start(), value, true);
    687   }
    688 }
    689 
    690 
    691 void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) {
    692   if (labels != NULL && labels->length() > 0) {
    693     if (info == NULL) {
    694       PrintIndented("LABELS ");
    695     } else {
    696       PrintIndented(info);
    697       Print(" ");
    698     }
    699     PrintLabels(labels);
    700   } else if (info != NULL) {
    701     PrintIndented(info);
    702   }
    703   Print("\n");
    704 }
    705 
    706 
    707 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
    708   IndentedScope indent(s, node);
    709   Visit(node);
    710 }
    711 
    712 
    713 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
    714   Init();
    715   { IndentedScope indent("FUNC");
    716     PrintLiteralIndented("NAME", program->name(), true);
    717     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
    718     PrintParameters(program->scope());
    719     PrintDeclarations(program->scope()->declarations());
    720     PrintStatements(program->body());
    721   }
    722   return Output();
    723 }
    724 
    725 
    726 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
    727   if (declarations->length() > 0) {
    728     IndentedScope indent("DECLS");
    729     for (int i = 0; i < declarations->length(); i++) {
    730       Visit(declarations->at(i));
    731     }
    732   }
    733 }
    734 
    735 
    736 void AstPrinter::PrintParameters(Scope* scope) {
    737   if (scope->num_parameters() > 0) {
    738     IndentedScope indent("PARAMS");
    739     for (int i = 0; i < scope->num_parameters(); i++) {
    740       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
    741                                    scope->parameter(i)->name(),
    742                                    scope->parameter(i)->type(),
    743                                    Expression::kNoLabel);
    744     }
    745   }
    746 }
    747 
    748 
    749 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
    750   for (int i = 0; i < statements->length(); i++) {
    751     Visit(statements->at(i));
    752   }
    753 }
    754 
    755 
    756 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
    757   for (int i = 0; i < arguments->length(); i++) {
    758     Visit(arguments->at(i));
    759   }
    760 }
    761 
    762 
    763 void AstPrinter::PrintCaseClause(CaseClause* clause) {
    764   if (clause->is_default()) {
    765     IndentedScope indent("DEFAULT");
    766     PrintStatements(clause->statements());
    767   } else {
    768     IndentedScope indent("CASE");
    769     Visit(clause->label());
    770     PrintStatements(clause->statements());
    771   }
    772 }
    773 
    774 
    775 void AstPrinter::VisitBlock(Block* node) {
    776   const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
    777   IndentedScope indent(block_txt);
    778   PrintStatements(node->statements());
    779 }
    780 
    781 
    782 void AstPrinter::VisitDeclaration(Declaration* node) {
    783   if (node->fun() == NULL) {
    784     // var or const declarations
    785     PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
    786                                  node->proxy()->AsVariable(),
    787                                  node->proxy()->name(),
    788                                  node->proxy()->AsVariable()->type(),
    789                                  Expression::kNoLabel);
    790   } else {
    791     // function declarations
    792     PrintIndented("FUNCTION ");
    793     PrintLiteral(node->proxy()->name(), true);
    794     Print(" = function ");
    795     PrintLiteral(node->fun()->name(), false);
    796     Print("\n");
    797   }
    798 }
    799 
    800 
    801 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
    802   Visit(node->expression());
    803 }
    804 
    805 
    806 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
    807   PrintIndented("EMPTY\n");
    808 }
    809 
    810 
    811 void AstPrinter::VisitIfStatement(IfStatement* node) {
    812   PrintIndentedVisit("IF", node->condition());
    813   PrintIndentedVisit("THEN", node->then_statement());
    814   if (node->HasElseStatement()) {
    815     PrintIndentedVisit("ELSE", node->else_statement());
    816   }
    817 }
    818 
    819 
    820 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
    821   PrintLabelsIndented("CONTINUE", node->target()->labels());
    822 }
    823 
    824 
    825 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
    826   PrintLabelsIndented("BREAK", node->target()->labels());
    827 }
    828 
    829 
    830 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
    831   PrintIndentedVisit("RETURN", node->expression());
    832 }
    833 
    834 
    835 void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
    836   PrintIndentedVisit("WITH ENTER", node->expression());
    837 }
    838 
    839 
    840 void AstPrinter::VisitWithExitStatement(WithExitStatement* node) {
    841   PrintIndented("WITH EXIT\n");
    842 }
    843 
    844 
    845 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
    846   IndentedScope indent("SWITCH");
    847   PrintLabelsIndented(NULL, node->labels());
    848   PrintIndentedVisit("TAG", node->tag());
    849   for (int i = 0; i < node->cases()->length(); i++) {
    850     PrintCaseClause(node->cases()->at(i));
    851   }
    852 }
    853 
    854 
    855 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
    856   IndentedScope indent("DO");
    857   PrintLabelsIndented(NULL, node->labels());
    858   PrintIndentedVisit("BODY", node->body());
    859   PrintIndentedVisit("COND", node->cond());
    860 }
    861 
    862 
    863 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
    864   IndentedScope indent("WHILE");
    865   PrintLabelsIndented(NULL, node->labels());
    866   PrintIndentedVisit("COND", node->cond());
    867   PrintIndentedVisit("BODY", node->body());
    868 }
    869 
    870 
    871 void AstPrinter::VisitForStatement(ForStatement* node) {
    872   IndentedScope indent("FOR");
    873   PrintLabelsIndented(NULL, node->labels());
    874   if (node->init()) PrintIndentedVisit("INIT", node->init());
    875   if (node->cond()) PrintIndentedVisit("COND", node->cond());
    876   PrintIndentedVisit("BODY", node->body());
    877   if (node->next()) PrintIndentedVisit("NEXT", node->next());
    878 }
    879 
    880 
    881 void AstPrinter::VisitForInStatement(ForInStatement* node) {
    882   IndentedScope indent("FOR IN");
    883   PrintIndentedVisit("FOR", node->each());
    884   PrintIndentedVisit("IN", node->enumerable());
    885   PrintIndentedVisit("BODY", node->body());
    886 }
    887 
    888 
    889 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
    890   IndentedScope indent("TRY CATCH");
    891   PrintIndentedVisit("TRY", node->try_block());
    892   PrintIndentedVisit("CATCHVAR", node->catch_var());
    893   PrintIndentedVisit("CATCH", node->catch_block());
    894 }
    895 
    896 
    897 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    898   IndentedScope indent("TRY FINALLY");
    899   PrintIndentedVisit("TRY", node->try_block());
    900   PrintIndentedVisit("FINALLY", node->finally_block());
    901 }
    902 
    903 
    904 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
    905   IndentedScope indent("DEBUGGER");
    906 }
    907 
    908 
    909 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    910   IndentedScope indent("FUNC LITERAL");
    911   PrintLiteralIndented("NAME", node->name(), false);
    912   PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
    913   PrintParameters(node->scope());
    914   // We don't want to see the function literal in this case: it
    915   // will be printed via PrintProgram when the code for it is
    916   // generated.
    917   // PrintStatements(node->body());
    918 }
    919 
    920 
    921 void AstPrinter::VisitFunctionBoilerplateLiteral(
    922     FunctionBoilerplateLiteral* node) {
    923   IndentedScope indent("FUNC LITERAL");
    924   PrintLiteralIndented("BOILERPLATE", node->boilerplate(), true);
    925 }
    926 
    927 
    928 void AstPrinter::VisitConditional(Conditional* node) {
    929   IndentedScope indent("CONDITIONAL");
    930   PrintIndentedVisit("?", node->condition());
    931   PrintIndentedVisit("THEN", node->then_expression());
    932   PrintIndentedVisit("ELSE", node->else_expression());
    933 }
    934 
    935 
    936 void AstPrinter::VisitLiteral(Literal* node) {
    937   PrintLiteralIndented("LITERAL", node->handle(), true);
    938 }
    939 
    940 
    941 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
    942   IndentedScope indent("REGEXP LITERAL");
    943   PrintLiteralIndented("PATTERN", node->pattern(), false);
    944   PrintLiteralIndented("FLAGS", node->flags(), false);
    945 }
    946 
    947 
    948 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
    949   IndentedScope indent("OBJ LITERAL");
    950   for (int i = 0; i < node->properties()->length(); i++) {
    951     const char* prop_kind = NULL;
    952     switch (node->properties()->at(i)->kind()) {
    953       case ObjectLiteral::Property::CONSTANT:
    954         prop_kind = "PROPERTY - CONSTANT";
    955         break;
    956       case ObjectLiteral::Property::COMPUTED:
    957         prop_kind = "PROPERTY - COMPUTED";
    958         break;
    959       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
    960         prop_kind = "PROPERTY - MATERIALIZED_LITERAL";
    961         break;
    962       case ObjectLiteral::Property::PROTOTYPE:
    963         prop_kind = "PROPERTY - PROTOTYPE";
    964         break;
    965       case ObjectLiteral::Property::GETTER:
    966         prop_kind = "PROPERTY - GETTER";
    967         break;
    968       case ObjectLiteral::Property::SETTER:
    969         prop_kind = "PROPERTY - SETTER";
    970         break;
    971       default:
    972         UNREACHABLE();
    973     }
    974     IndentedScope prop(prop_kind);
    975     PrintIndentedVisit("KEY", node->properties()->at(i)->key());
    976     PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
    977   }
    978 }
    979 
    980 
    981 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
    982   IndentedScope indent("ARRAY LITERAL");
    983   if (node->values()->length() > 0) {
    984     IndentedScope indent("VALUES");
    985     for (int i = 0; i < node->values()->length(); i++) {
    986       Visit(node->values()->at(i));
    987     }
    988   }
    989 }
    990 
    991 
    992 void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
    993   IndentedScope indent("CatchExtensionObject");
    994   PrintIndentedVisit("KEY", node->key());
    995   PrintIndentedVisit("VALUE", node->value());
    996 }
    997 
    998 
    999 void AstPrinter::VisitSlot(Slot* node) {
   1000   PrintIndented("SLOT ");
   1001   switch (node->type()) {
   1002     case Slot::PARAMETER:
   1003       Print("parameter[%d]", node->index());
   1004       break;
   1005     case Slot::LOCAL:
   1006       Print("frame[%d]", node->index());
   1007       break;
   1008     case Slot::CONTEXT:
   1009       Print(".context[%d]", node->index());
   1010       break;
   1011     case Slot::LOOKUP:
   1012       Print(".context[");
   1013       PrintLiteral(node->var()->name(), false);
   1014       Print("]");
   1015       break;
   1016     default:
   1017       UNREACHABLE();
   1018   }
   1019   Print("\n");
   1020 }
   1021 
   1022 
   1023 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
   1024   PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name(),
   1025                                node->type(), node->num());
   1026   Variable* var = node->var();
   1027   if (var != NULL && var->rewrite() != NULL) {
   1028     IndentedScope indent;
   1029     Visit(var->rewrite());
   1030   }
   1031 }
   1032 
   1033 
   1034 void AstPrinter::VisitAssignment(Assignment* node) {
   1035   IndentedScope indent(Token::Name(node->op()), node);
   1036   Visit(node->target());
   1037   Visit(node->value());
   1038 }
   1039 
   1040 
   1041 void AstPrinter::VisitThrow(Throw* node) {
   1042   PrintIndentedVisit("THROW", node->exception());
   1043 }
   1044 
   1045 
   1046 void AstPrinter::VisitProperty(Property* node) {
   1047   IndentedScope indent("PROPERTY", node);
   1048   Visit(node->obj());
   1049   Literal* literal = node->key()->AsLiteral();
   1050   if (literal != NULL && literal->handle()->IsSymbol()) {
   1051     PrintLiteralIndented("NAME", literal->handle(), false);
   1052   } else {
   1053     PrintIndentedVisit("KEY", node->key());
   1054   }
   1055 }
   1056 
   1057 
   1058 void AstPrinter::VisitCall(Call* node) {
   1059   IndentedScope indent("CALL");
   1060   Visit(node->expression());
   1061   PrintArguments(node->arguments());
   1062 }
   1063 
   1064 
   1065 void AstPrinter::VisitCallNew(CallNew* node) {
   1066   IndentedScope indent("CALL NEW");
   1067   Visit(node->expression());
   1068   PrintArguments(node->arguments());
   1069 }
   1070 
   1071 
   1072 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
   1073   PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
   1074   IndentedScope indent;
   1075   PrintArguments(node->arguments());
   1076 }
   1077 
   1078 
   1079 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
   1080   PrintIndentedVisit(Token::Name(node->op()), node->expression());
   1081 }
   1082 
   1083 
   1084 void AstPrinter::VisitCountOperation(CountOperation* node) {
   1085   EmbeddedVector<char, 128> buf;
   1086   if (node->type()->IsKnown()) {
   1087     OS::SNPrintF(buf, "%s %s (type = %s)",
   1088                  (node->is_prefix() ? "PRE" : "POST"),
   1089                  Token::Name(node->op()),
   1090                  StaticType::Type2String(node->type()));
   1091   } else {
   1092     OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
   1093                  Token::Name(node->op()));
   1094   }
   1095   PrintIndentedVisit(buf.start(), node->expression());
   1096 }
   1097 
   1098 
   1099 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
   1100   IndentedScope indent(Token::Name(node->op()), node);
   1101   Visit(node->left());
   1102   Visit(node->right());
   1103 }
   1104 
   1105 
   1106 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
   1107   IndentedScope indent(Token::Name(node->op()), node);
   1108   Visit(node->left());
   1109   Visit(node->right());
   1110 }
   1111 
   1112 
   1113 void AstPrinter::VisitThisFunction(ThisFunction* node) {
   1114   IndentedScope indent("THIS-FUNCTION");
   1115 }
   1116 
   1117 
   1118 TagScope::TagScope(JsonAstBuilder* builder, const char* name)
   1119     : builder_(builder), next_(builder->tag()), has_body_(false) {
   1120   if (next_ != NULL) {
   1121     next_->use();
   1122     builder->Print(",\n");
   1123   }
   1124   builder->set_tag(this);
   1125   builder->PrintIndented("[");
   1126   builder->Print("\"%s\"", name);
   1127   builder->increase_indent(JsonAstBuilder::kTagIndentSize);
   1128 }
   1129 
   1130 
   1131 TagScope::~TagScope() {
   1132   builder_->decrease_indent(JsonAstBuilder::kTagIndentSize);
   1133   if (has_body_) {
   1134     builder_->Print("\n");
   1135     builder_->PrintIndented("]");
   1136   } else {
   1137     builder_->Print("]");
   1138   }
   1139   builder_->set_tag(next_);
   1140 }
   1141 
   1142 
   1143 AttributesScope::AttributesScope(JsonAstBuilder* builder)
   1144     : builder_(builder), attribute_count_(0) {
   1145   builder->set_attributes(this);
   1146   builder->tag()->use();
   1147   builder->Print(",\n");
   1148   builder->PrintIndented("{");
   1149   builder->increase_indent(JsonAstBuilder::kAttributesIndentSize);
   1150 }
   1151 
   1152 
   1153 AttributesScope::~AttributesScope() {
   1154   builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize);
   1155   if (attribute_count_ > 1) {
   1156     builder_->Print("\n");
   1157     builder_->PrintIndented("}");
   1158   } else {
   1159     builder_->Print("}");
   1160   }
   1161   builder_->set_attributes(NULL);
   1162 }
   1163 
   1164 
   1165 const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) {
   1166   Init();
   1167   Visit(program);
   1168   Print("\n");
   1169   return Output();
   1170 }
   1171 
   1172 
   1173 void JsonAstBuilder::AddAttributePrefix(const char* name) {
   1174   if (attributes()->is_used()) {
   1175     Print(",\n");
   1176     PrintIndented("\"");
   1177   } else {
   1178     Print("\"");
   1179   }
   1180   Print("%s\":", name);
   1181   attributes()->use();
   1182 }
   1183 
   1184 
   1185 void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) {
   1186   SmartPointer<char> value_string = value->ToCString();
   1187   AddAttributePrefix(name);
   1188   Print("\"%s\"", *value_string);
   1189 }
   1190 
   1191 
   1192 void JsonAstBuilder::AddAttribute(const char* name, const char* value) {
   1193   AddAttributePrefix(name);
   1194   Print("\"%s\"", value);
   1195 }
   1196 
   1197 
   1198 void JsonAstBuilder::AddAttribute(const char* name, int value) {
   1199   AddAttributePrefix(name);
   1200   Print("%d", value);
   1201 }
   1202 
   1203 
   1204 void JsonAstBuilder::AddAttribute(const char* name, bool value) {
   1205   AddAttributePrefix(name);
   1206   Print(value ? "true" : "false");
   1207 }
   1208 
   1209 
   1210 void JsonAstBuilder::VisitBlock(Block* stmt) {
   1211   TagScope tag(this, "Block");
   1212   VisitStatements(stmt->statements());
   1213 }
   1214 
   1215 
   1216 void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
   1217   TagScope tag(this, "ExpressionStatement");
   1218   Visit(stmt->expression());
   1219 }
   1220 
   1221 
   1222 void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
   1223   TagScope tag(this, "EmptyStatement");
   1224 }
   1225 
   1226 
   1227 void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) {
   1228   TagScope tag(this, "IfStatement");
   1229   Visit(stmt->condition());
   1230   Visit(stmt->then_statement());
   1231   Visit(stmt->else_statement());
   1232 }
   1233 
   1234 
   1235 void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) {
   1236   TagScope tag(this, "ContinueStatement");
   1237 }
   1238 
   1239 
   1240 void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) {
   1241   TagScope tag(this, "BreakStatement");
   1242 }
   1243 
   1244 
   1245 void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) {
   1246   TagScope tag(this, "ReturnStatement");
   1247   Visit(stmt->expression());
   1248 }
   1249 
   1250 
   1251 void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
   1252   TagScope tag(this, "WithEnterStatement");
   1253   Visit(stmt->expression());
   1254 }
   1255 
   1256 
   1257 void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
   1258   TagScope tag(this, "WithExitStatement");
   1259 }
   1260 
   1261 
   1262 void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
   1263   TagScope tag(this, "SwitchStatement");
   1264 }
   1265 
   1266 
   1267 void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
   1268   TagScope tag(this, "DoWhileStatement");
   1269   Visit(stmt->body());
   1270   Visit(stmt->cond());
   1271 }
   1272 
   1273 
   1274 void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) {
   1275   TagScope tag(this, "WhileStatement");
   1276   Visit(stmt->cond());
   1277   Visit(stmt->body());
   1278 }
   1279 
   1280 
   1281 void JsonAstBuilder::VisitForStatement(ForStatement* stmt) {
   1282   TagScope tag(this, "ForStatement");
   1283   if (stmt->init() != NULL) Visit(stmt->init());
   1284   if (stmt->cond() != NULL) Visit(stmt->cond());
   1285   Visit(stmt->body());
   1286   if (stmt->next() != NULL) Visit(stmt->next());
   1287 }
   1288 
   1289 
   1290 void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) {
   1291   TagScope tag(this, "ForInStatement");
   1292   Visit(stmt->each());
   1293   Visit(stmt->enumerable());
   1294   Visit(stmt->body());
   1295 }
   1296 
   1297 
   1298 void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
   1299   TagScope tag(this, "TryCatchStatement");
   1300   Visit(stmt->try_block());
   1301   Visit(stmt->catch_var());
   1302   Visit(stmt->catch_block());
   1303 }
   1304 
   1305 
   1306 void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
   1307   TagScope tag(this, "TryFinallyStatement");
   1308   Visit(stmt->try_block());
   1309   Visit(stmt->finally_block());
   1310 }
   1311 
   1312 
   1313 void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
   1314   TagScope tag(this, "DebuggerStatement");
   1315 }
   1316 
   1317 
   1318 void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
   1319   TagScope tag(this, "FunctionLiteral");
   1320   {
   1321     AttributesScope attributes(this);
   1322     AddAttribute("name", expr->name());
   1323   }
   1324   VisitDeclarations(expr->scope()->declarations());
   1325   VisitStatements(expr->body());
   1326 }
   1327 
   1328 
   1329 void JsonAstBuilder::VisitFunctionBoilerplateLiteral(
   1330     FunctionBoilerplateLiteral* expr) {
   1331   TagScope tag(this, "FunctionBoilerplateLiteral");
   1332 }
   1333 
   1334 
   1335 void JsonAstBuilder::VisitConditional(Conditional* expr) {
   1336   TagScope tag(this, "Conditional");
   1337 }
   1338 
   1339 
   1340 void JsonAstBuilder::VisitSlot(Slot* expr) {
   1341   TagScope tag(this, "Slot");
   1342   {
   1343     AttributesScope attributes(this);
   1344     switch (expr->type()) {
   1345       case Slot::PARAMETER:
   1346         AddAttribute("type", "PARAMETER");
   1347         break;
   1348       case Slot::LOCAL:
   1349         AddAttribute("type", "LOCAL");
   1350         break;
   1351       case Slot::CONTEXT:
   1352         AddAttribute("type", "CONTEXT");
   1353         break;
   1354       case Slot::LOOKUP:
   1355         AddAttribute("type", "LOOKUP");
   1356         break;
   1357     }
   1358     AddAttribute("index", expr->index());
   1359   }
   1360 }
   1361 
   1362 
   1363 void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
   1364   if (expr->var()->rewrite() == NULL) {
   1365     TagScope tag(this, "VariableProxy");
   1366     {
   1367       AttributesScope attributes(this);
   1368       AddAttribute("name", expr->name());
   1369       AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
   1370     }
   1371   } else {
   1372     Visit(expr->var()->rewrite());
   1373   }
   1374 }
   1375 
   1376 
   1377 void JsonAstBuilder::VisitLiteral(Literal* expr) {
   1378   TagScope tag(this, "Literal");
   1379   {
   1380     AttributesScope attributes(this);
   1381     Handle<Object> handle = expr->handle();
   1382     if (handle->IsString()) {
   1383       AddAttribute("handle", Handle<String>(String::cast(*handle)));
   1384     } else if (handle->IsSmi()) {
   1385       AddAttribute("handle", Smi::cast(*handle)->value());
   1386     }
   1387   }
   1388 }
   1389 
   1390 
   1391 void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
   1392   TagScope tag(this, "RegExpLiteral");
   1393 }
   1394 
   1395 
   1396 void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
   1397   TagScope tag(this, "ObjectLiteral");
   1398 }
   1399 
   1400 
   1401 void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
   1402   TagScope tag(this, "ArrayLiteral");
   1403 }
   1404 
   1405 
   1406 void JsonAstBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
   1407   TagScope tag(this, "CatchExtensionObject");
   1408   Visit(expr->key());
   1409   Visit(expr->value());
   1410 }
   1411 
   1412 
   1413 void JsonAstBuilder::VisitAssignment(Assignment* expr) {
   1414   TagScope tag(this, "Assignment");
   1415   {
   1416     AttributesScope attributes(this);
   1417     AddAttribute("op", Token::Name(expr->op()));
   1418   }
   1419   Visit(expr->target());
   1420   Visit(expr->value());
   1421 }
   1422 
   1423 
   1424 void JsonAstBuilder::VisitThrow(Throw* expr) {
   1425   TagScope tag(this, "Throw");
   1426   Visit(expr->exception());
   1427 }
   1428 
   1429 
   1430 void JsonAstBuilder::VisitProperty(Property* expr) {
   1431   TagScope tag(this, "Property");
   1432   {
   1433     AttributesScope attributes(this);
   1434     AddAttribute("type", expr->is_synthetic() ? "SYNTHETIC" : "NORMAL");
   1435   }
   1436   Visit(expr->obj());
   1437   Visit(expr->key());
   1438 }
   1439 
   1440 
   1441 void JsonAstBuilder::VisitCall(Call* expr) {
   1442   TagScope tag(this, "Call");
   1443   Visit(expr->expression());
   1444   VisitExpressions(expr->arguments());
   1445 }
   1446 
   1447 
   1448 void JsonAstBuilder::VisitCallNew(CallNew* expr) {
   1449   TagScope tag(this, "CallNew");
   1450   Visit(expr->expression());
   1451   VisitExpressions(expr->arguments());
   1452 }
   1453 
   1454 
   1455 void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) {
   1456   TagScope tag(this, "CallRuntime");
   1457   {
   1458     AttributesScope attributes(this);
   1459     AddAttribute("name", expr->name());
   1460   }
   1461   VisitExpressions(expr->arguments());
   1462 }
   1463 
   1464 
   1465 void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) {
   1466   TagScope tag(this, "UnaryOperation");
   1467   {
   1468     AttributesScope attributes(this);
   1469     AddAttribute("op", Token::Name(expr->op()));
   1470   }
   1471   Visit(expr->expression());
   1472 }
   1473 
   1474 
   1475 void JsonAstBuilder::VisitCountOperation(CountOperation* expr) {
   1476   TagScope tag(this, "CountOperation");
   1477   {
   1478     AttributesScope attributes(this);
   1479     AddAttribute("is_prefix", expr->is_prefix());
   1480     AddAttribute("op", Token::Name(expr->op()));
   1481   }
   1482   Visit(expr->expression());
   1483 }
   1484 
   1485 
   1486 void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) {
   1487   TagScope tag(this, "BinaryOperation");
   1488   {
   1489     AttributesScope attributes(this);
   1490     AddAttribute("op", Token::Name(expr->op()));
   1491   }
   1492   Visit(expr->left());
   1493   Visit(expr->right());
   1494 }
   1495 
   1496 
   1497 void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) {
   1498   TagScope tag(this, "CompareOperation");
   1499   {
   1500     AttributesScope attributes(this);
   1501     AddAttribute("op", Token::Name(expr->op()));
   1502   }
   1503   Visit(expr->left());
   1504   Visit(expr->right());
   1505 }
   1506 
   1507 
   1508 void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) {
   1509   TagScope tag(this, "ThisFunction");
   1510 }
   1511 
   1512 
   1513 void JsonAstBuilder::VisitDeclaration(Declaration* decl) {
   1514   TagScope tag(this, "Declaration");
   1515   {
   1516     AttributesScope attributes(this);
   1517     AddAttribute("mode", Variable::Mode2String(decl->mode()));
   1518   }
   1519   Visit(decl->proxy());
   1520   if (decl->fun() != NULL) Visit(decl->fun());
   1521 }
   1522 
   1523 
   1524 #endif  // DEBUG
   1525 
   1526 } }  // namespace v8::internal
   1527