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::VisitSharedFunctionInfoLiteral(
    231     SharedFunctionInfoLiteral* node) {
    232   Print("(");
    233   PrintLiteral(node->shared_function_info(), 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("local[%d]", node->index());
    301       break;
    302     case Slot::CONTEXT:
    303       Print("context[%d]", node->index());
    304       break;
    305     case Slot::LOOKUP:
    306       Print("lookup[");
    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::VisitCompareToNull(CompareToNull* node) {
    407   Print("(");
    408   Visit(node->expression());
    409   Print("%s null)", Token::String(node->op()));
    410 }
    411 
    412 
    413 void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
    414   Print("<this-function>");
    415 }
    416 
    417 
    418 const char* PrettyPrinter::Print(AstNode* node) {
    419   Init();
    420   Visit(node);
    421   return output_;
    422 }
    423 
    424 
    425 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
    426   Init();
    427   ExpressionStatement* statement =
    428     program->body()->at(0)->AsExpressionStatement();
    429   Visit(statement->expression());
    430   return output_;
    431 }
    432 
    433 
    434 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
    435   Init();
    436   PrintStatements(program->body());
    437   Print("\n");
    438   return output_;
    439 }
    440 
    441 
    442 void PrettyPrinter::PrintOut(AstNode* node) {
    443   PrettyPrinter printer;
    444   PrintF("%s", printer.Print(node));
    445 }
    446 
    447 
    448 void PrettyPrinter::Init() {
    449   if (size_ == 0) {
    450     ASSERT(output_ == NULL);
    451     const int initial_size = 256;
    452     output_ = NewArray<char>(initial_size);
    453     size_ = initial_size;
    454   }
    455   output_[0] = '\0';
    456   pos_ = 0;
    457 }
    458 
    459 
    460 void PrettyPrinter::Print(const char* format, ...) {
    461   for (;;) {
    462     va_list arguments;
    463     va_start(arguments, format);
    464     int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_,
    465                           format,
    466                           arguments);
    467     va_end(arguments);
    468 
    469     if (n >= 0) {
    470       // there was enough space - we are done
    471       pos_ += n;
    472       return;
    473     } else {
    474       // there was not enough space - allocate more and try again
    475       const int slack = 32;
    476       int new_size = size_ + (size_ >> 1) + slack;
    477       char* new_output = NewArray<char>(new_size);
    478       memcpy(new_output, output_, pos_);
    479       DeleteArray(output_);
    480       output_ = new_output;
    481       size_ = new_size;
    482     }
    483   }
    484 }
    485 
    486 
    487 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
    488   for (int i = 0; i < statements->length(); i++) {
    489     if (i != 0) Print(" ");
    490     Visit(statements->at(i));
    491   }
    492 }
    493 
    494 
    495 void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
    496   if (labels != NULL) {
    497     for (int i = 0; i < labels->length(); i++) {
    498       PrintLiteral(labels->at(i), false);
    499       Print(": ");
    500     }
    501   }
    502 }
    503 
    504 
    505 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
    506   Print("(");
    507   for (int i = 0; i < arguments->length(); i++) {
    508     if (i != 0) Print(", ");
    509     Visit(arguments->at(i));
    510   }
    511   Print(")");
    512 }
    513 
    514 
    515 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
    516   Object* object = *value;
    517   if (object->IsString()) {
    518     String* string = String::cast(object);
    519     if (quote) Print("\"");
    520     for (int i = 0; i < string->length(); i++) {
    521       Print("%c", string->Get(i));
    522     }
    523     if (quote) Print("\"");
    524   } else if (object->IsNull()) {
    525     Print("null");
    526   } else if (object->IsTrue()) {
    527     Print("true");
    528   } else if (object->IsFalse()) {
    529     Print("false");
    530   } else if (object->IsUndefined()) {
    531     Print("undefined");
    532   } else if (object->IsNumber()) {
    533     Print("%g", object->Number());
    534   } else if (object->IsJSObject()) {
    535     // regular expression
    536     if (object->IsJSFunction()) {
    537       Print("JS-Function");
    538     } else if (object->IsJSArray()) {
    539       Print("JS-array[%u]", JSArray::cast(object)->length());
    540     } else if (object->IsJSObject()) {
    541       Print("JS-Object");
    542     } else {
    543       Print("?UNKNOWN?");
    544     }
    545   } else if (object->IsFixedArray()) {
    546     Print("FixedArray");
    547   } else {
    548     Print("<unknown literal %p>", object);
    549   }
    550 }
    551 
    552 
    553 void PrettyPrinter::PrintParameters(Scope* scope) {
    554   Print("(");
    555   for (int i = 0; i < scope->num_parameters(); i++) {
    556     if (i  > 0) Print(", ");
    557     PrintLiteral(scope->parameter(i)->name(), false);
    558   }
    559   Print(")");
    560 }
    561 
    562 
    563 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
    564   for (int i = 0; i < declarations->length(); i++) {
    565     if (i > 0) Print(" ");
    566     Visit(declarations->at(i));
    567   }
    568 }
    569 
    570 
    571 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
    572   Print("function ");
    573   PrintLiteral(function->name(), false);
    574   PrintParameters(function->scope());
    575   Print(" { ");
    576   PrintDeclarations(function->scope()->declarations());
    577   PrintStatements(function->body());
    578   Print(" }");
    579 }
    580 
    581 
    582 void PrettyPrinter::PrintCaseClause(CaseClause* clause) {
    583   if (clause->is_default()) {
    584     Print("default");
    585   } else {
    586     Print("case ");
    587     Visit(clause->label());
    588   }
    589   Print(": ");
    590   PrintStatements(clause->statements());
    591   if (clause->statements()->length() > 0)
    592     Print(" ");
    593 }
    594 
    595 
    596 //-----------------------------------------------------------------------------
    597 
    598 class IndentedScope BASE_EMBEDDED {
    599  public:
    600   explicit IndentedScope(AstPrinter* printer) : ast_printer_(printer) {
    601     ast_printer_->inc_indent();
    602   }
    603 
    604   IndentedScope(AstPrinter* printer, const char* txt, AstNode* node = NULL)
    605       : ast_printer_(printer) {
    606     ast_printer_->PrintIndented(txt);
    607     ast_printer_->Print("\n");
    608     ast_printer_->inc_indent();
    609   }
    610 
    611   virtual ~IndentedScope() {
    612     ast_printer_->dec_indent();
    613   }
    614 
    615  private:
    616   AstPrinter* ast_printer_;
    617 };
    618 
    619 
    620 //-----------------------------------------------------------------------------
    621 
    622 
    623 AstPrinter::AstPrinter() : indent_(0) {
    624 }
    625 
    626 
    627 AstPrinter::~AstPrinter() {
    628   ASSERT(indent_ == 0);
    629 }
    630 
    631 
    632 void AstPrinter::PrintIndented(const char* txt) {
    633   for (int i = 0; i < indent_; i++) {
    634     Print(". ");
    635   }
    636   Print(txt);
    637 }
    638 
    639 
    640 void AstPrinter::PrintLiteralIndented(const char* info,
    641                                       Handle<Object> value,
    642                                       bool quote) {
    643   PrintIndented(info);
    644   Print(" ");
    645   PrintLiteral(value, quote);
    646   Print("\n");
    647 }
    648 
    649 
    650 void AstPrinter::PrintLiteralWithModeIndented(const char* info,
    651                                               Variable* var,
    652                                               Handle<Object> value) {
    653   if (var == NULL) {
    654     PrintLiteralIndented(info, value, true);
    655   } else {
    656     EmbeddedVector<char, 256> buf;
    657     int pos = OS::SNPrintF(buf, "%s (mode = %s", info,
    658                            Variable::Mode2String(var->mode()));
    659     OS::SNPrintF(buf + pos, ")");
    660     PrintLiteralIndented(buf.start(), value, true);
    661   }
    662 }
    663 
    664 
    665 void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) {
    666   if (labels != NULL && labels->length() > 0) {
    667     if (info == NULL) {
    668       PrintIndented("LABELS ");
    669     } else {
    670       PrintIndented(info);
    671       Print(" ");
    672     }
    673     PrintLabels(labels);
    674   } else if (info != NULL) {
    675     PrintIndented(info);
    676   }
    677   Print("\n");
    678 }
    679 
    680 
    681 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
    682   IndentedScope indent(this, s, node);
    683   Visit(node);
    684 }
    685 
    686 
    687 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
    688   Init();
    689   { IndentedScope indent(this, "FUNC");
    690     PrintLiteralIndented("NAME", program->name(), true);
    691     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
    692     PrintParameters(program->scope());
    693     PrintDeclarations(program->scope()->declarations());
    694     PrintStatements(program->body());
    695   }
    696   return Output();
    697 }
    698 
    699 
    700 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
    701   if (declarations->length() > 0) {
    702     IndentedScope indent(this, "DECLS");
    703     for (int i = 0; i < declarations->length(); i++) {
    704       Visit(declarations->at(i));
    705     }
    706   }
    707 }
    708 
    709 
    710 void AstPrinter::PrintParameters(Scope* scope) {
    711   if (scope->num_parameters() > 0) {
    712     IndentedScope indent(this, "PARAMS");
    713     for (int i = 0; i < scope->num_parameters(); i++) {
    714       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
    715                                    scope->parameter(i)->name());
    716     }
    717   }
    718 }
    719 
    720 
    721 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
    722   for (int i = 0; i < statements->length(); i++) {
    723     Visit(statements->at(i));
    724   }
    725 }
    726 
    727 
    728 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
    729   for (int i = 0; i < arguments->length(); i++) {
    730     Visit(arguments->at(i));
    731   }
    732 }
    733 
    734 
    735 void AstPrinter::PrintCaseClause(CaseClause* clause) {
    736   if (clause->is_default()) {
    737     IndentedScope indent(this, "DEFAULT");
    738     PrintStatements(clause->statements());
    739   } else {
    740     IndentedScope indent(this, "CASE");
    741     Visit(clause->label());
    742     PrintStatements(clause->statements());
    743   }
    744 }
    745 
    746 
    747 void AstPrinter::VisitBlock(Block* node) {
    748   const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
    749   IndentedScope indent(this, block_txt);
    750   PrintStatements(node->statements());
    751 }
    752 
    753 
    754 void AstPrinter::VisitDeclaration(Declaration* node) {
    755   if (node->fun() == NULL) {
    756     // var or const declarations
    757     PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
    758                                  node->proxy()->AsVariable(),
    759                                  node->proxy()->name());
    760   } else {
    761     // function declarations
    762     PrintIndented("FUNCTION ");
    763     PrintLiteral(node->proxy()->name(), true);
    764     Print(" = function ");
    765     PrintLiteral(node->fun()->name(), false);
    766     Print("\n");
    767   }
    768 }
    769 
    770 
    771 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
    772   Visit(node->expression());
    773 }
    774 
    775 
    776 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
    777   PrintIndented("EMPTY\n");
    778 }
    779 
    780 
    781 void AstPrinter::VisitIfStatement(IfStatement* node) {
    782   PrintIndentedVisit("IF", node->condition());
    783   PrintIndentedVisit("THEN", node->then_statement());
    784   if (node->HasElseStatement()) {
    785     PrintIndentedVisit("ELSE", node->else_statement());
    786   }
    787 }
    788 
    789 
    790 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
    791   PrintLabelsIndented("CONTINUE", node->target()->labels());
    792 }
    793 
    794 
    795 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
    796   PrintLabelsIndented("BREAK", node->target()->labels());
    797 }
    798 
    799 
    800 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
    801   PrintIndentedVisit("RETURN", node->expression());
    802 }
    803 
    804 
    805 void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
    806   PrintIndentedVisit("WITH ENTER", node->expression());
    807 }
    808 
    809 
    810 void AstPrinter::VisitWithExitStatement(WithExitStatement* node) {
    811   PrintIndented("WITH EXIT\n");
    812 }
    813 
    814 
    815 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
    816   IndentedScope indent(this, "SWITCH");
    817   PrintLabelsIndented(NULL, node->labels());
    818   PrintIndentedVisit("TAG", node->tag());
    819   for (int i = 0; i < node->cases()->length(); i++) {
    820     PrintCaseClause(node->cases()->at(i));
    821   }
    822 }
    823 
    824 
    825 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
    826   IndentedScope indent(this, "DO");
    827   PrintLabelsIndented(NULL, node->labels());
    828   PrintIndentedVisit("BODY", node->body());
    829   PrintIndentedVisit("COND", node->cond());
    830 }
    831 
    832 
    833 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
    834   IndentedScope indent(this, "WHILE");
    835   PrintLabelsIndented(NULL, node->labels());
    836   PrintIndentedVisit("COND", node->cond());
    837   PrintIndentedVisit("BODY", node->body());
    838 }
    839 
    840 
    841 void AstPrinter::VisitForStatement(ForStatement* node) {
    842   IndentedScope indent(this, "FOR");
    843   PrintLabelsIndented(NULL, node->labels());
    844   if (node->init()) PrintIndentedVisit("INIT", node->init());
    845   if (node->cond()) PrintIndentedVisit("COND", node->cond());
    846   PrintIndentedVisit("BODY", node->body());
    847   if (node->next()) PrintIndentedVisit("NEXT", node->next());
    848 }
    849 
    850 
    851 void AstPrinter::VisitForInStatement(ForInStatement* node) {
    852   IndentedScope indent(this, "FOR IN");
    853   PrintIndentedVisit("FOR", node->each());
    854   PrintIndentedVisit("IN", node->enumerable());
    855   PrintIndentedVisit("BODY", node->body());
    856 }
    857 
    858 
    859 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
    860   IndentedScope indent(this, "TRY CATCH");
    861   PrintIndentedVisit("TRY", node->try_block());
    862   PrintIndentedVisit("CATCHVAR", node->catch_var());
    863   PrintIndentedVisit("CATCH", node->catch_block());
    864 }
    865 
    866 
    867 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    868   IndentedScope indent(this, "TRY FINALLY");
    869   PrintIndentedVisit("TRY", node->try_block());
    870   PrintIndentedVisit("FINALLY", node->finally_block());
    871 }
    872 
    873 
    874 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
    875   IndentedScope indent(this, "DEBUGGER");
    876 }
    877 
    878 
    879 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    880   IndentedScope indent(this, "FUNC LITERAL");
    881   PrintLiteralIndented("NAME", node->name(), false);
    882   PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
    883   PrintParameters(node->scope());
    884   // We don't want to see the function literal in this case: it
    885   // will be printed via PrintProgram when the code for it is
    886   // generated.
    887   // PrintStatements(node->body());
    888 }
    889 
    890 
    891 void AstPrinter::VisitSharedFunctionInfoLiteral(
    892     SharedFunctionInfoLiteral* node) {
    893   IndentedScope indent(this, "FUNC LITERAL");
    894   PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true);
    895 }
    896 
    897 
    898 void AstPrinter::VisitConditional(Conditional* node) {
    899   IndentedScope indent(this, "CONDITIONAL");
    900   PrintIndentedVisit("?", node->condition());
    901   PrintIndentedVisit("THEN", node->then_expression());
    902   PrintIndentedVisit("ELSE", node->else_expression());
    903 }
    904 
    905 
    906 void AstPrinter::VisitLiteral(Literal* node) {
    907   PrintLiteralIndented("LITERAL", node->handle(), true);
    908 }
    909 
    910 
    911 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
    912   IndentedScope indent(this, "REGEXP LITERAL");
    913   PrintLiteralIndented("PATTERN", node->pattern(), false);
    914   PrintLiteralIndented("FLAGS", node->flags(), false);
    915 }
    916 
    917 
    918 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
    919   IndentedScope indent(this, "OBJ LITERAL");
    920   for (int i = 0; i < node->properties()->length(); i++) {
    921     const char* prop_kind = NULL;
    922     switch (node->properties()->at(i)->kind()) {
    923       case ObjectLiteral::Property::CONSTANT:
    924         prop_kind = "PROPERTY - CONSTANT";
    925         break;
    926       case ObjectLiteral::Property::COMPUTED:
    927         prop_kind = "PROPERTY - COMPUTED";
    928         break;
    929       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
    930         prop_kind = "PROPERTY - MATERIALIZED_LITERAL";
    931         break;
    932       case ObjectLiteral::Property::PROTOTYPE:
    933         prop_kind = "PROPERTY - PROTOTYPE";
    934         break;
    935       case ObjectLiteral::Property::GETTER:
    936         prop_kind = "PROPERTY - GETTER";
    937         break;
    938       case ObjectLiteral::Property::SETTER:
    939         prop_kind = "PROPERTY - SETTER";
    940         break;
    941       default:
    942         UNREACHABLE();
    943     }
    944     IndentedScope prop(this, prop_kind);
    945     PrintIndentedVisit("KEY", node->properties()->at(i)->key());
    946     PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
    947   }
    948 }
    949 
    950 
    951 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
    952   IndentedScope indent(this, "ARRAY LITERAL");
    953   if (node->values()->length() > 0) {
    954     IndentedScope indent(this, "VALUES");
    955     for (int i = 0; i < node->values()->length(); i++) {
    956       Visit(node->values()->at(i));
    957     }
    958   }
    959 }
    960 
    961 
    962 void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
    963   IndentedScope indent(this, "CatchExtensionObject");
    964   PrintIndentedVisit("KEY", node->key());
    965   PrintIndentedVisit("VALUE", node->value());
    966 }
    967 
    968 
    969 void AstPrinter::VisitSlot(Slot* node) {
    970   PrintIndented("SLOT ");
    971   PrettyPrinter::VisitSlot(node);
    972   Print("\n");
    973 }
    974 
    975 
    976 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
    977   PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name());
    978   Variable* var = node->var();
    979   if (var != NULL && var->rewrite() != NULL) {
    980     IndentedScope indent(this);
    981     Visit(var->rewrite());
    982   }
    983 }
    984 
    985 
    986 void AstPrinter::VisitAssignment(Assignment* node) {
    987   IndentedScope indent(this, Token::Name(node->op()), node);
    988   Visit(node->target());
    989   Visit(node->value());
    990 }
    991 
    992 
    993 void AstPrinter::VisitThrow(Throw* node) {
    994   PrintIndentedVisit("THROW", node->exception());
    995 }
    996 
    997 
    998 void AstPrinter::VisitProperty(Property* node) {
    999   IndentedScope indent(this, "PROPERTY", node);
   1000   Visit(node->obj());
   1001   Literal* literal = node->key()->AsLiteral();
   1002   if (literal != NULL && literal->handle()->IsSymbol()) {
   1003     PrintLiteralIndented("NAME", literal->handle(), false);
   1004   } else {
   1005     PrintIndentedVisit("KEY", node->key());
   1006   }
   1007 }
   1008 
   1009 
   1010 void AstPrinter::VisitCall(Call* node) {
   1011   IndentedScope indent(this, "CALL");
   1012   Visit(node->expression());
   1013   PrintArguments(node->arguments());
   1014 }
   1015 
   1016 
   1017 void AstPrinter::VisitCallNew(CallNew* node) {
   1018   IndentedScope indent(this, "CALL NEW");
   1019   Visit(node->expression());
   1020   PrintArguments(node->arguments());
   1021 }
   1022 
   1023 
   1024 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
   1025   PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
   1026   IndentedScope indent(this);
   1027   PrintArguments(node->arguments());
   1028 }
   1029 
   1030 
   1031 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
   1032   PrintIndentedVisit(Token::Name(node->op()), node->expression());
   1033 }
   1034 
   1035 
   1036 void AstPrinter::VisitCountOperation(CountOperation* node) {
   1037   EmbeddedVector<char, 128> buf;
   1038   OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
   1039                Token::Name(node->op()));
   1040   PrintIndentedVisit(buf.start(), node->expression());
   1041 }
   1042 
   1043 
   1044 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
   1045   IndentedScope indent(this, Token::Name(node->op()), node);
   1046   Visit(node->left());
   1047   Visit(node->right());
   1048 }
   1049 
   1050 
   1051 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
   1052   IndentedScope indent(this, Token::Name(node->op()), node);
   1053   Visit(node->left());
   1054   Visit(node->right());
   1055 }
   1056 
   1057 
   1058 void AstPrinter::VisitCompareToNull(CompareToNull* node) {
   1059   const char* name = node->is_strict()
   1060       ? "COMPARE-TO-NULL-STRICT"
   1061       : "COMPARE-TO-NULL";
   1062   IndentedScope indent(this, name, node);
   1063   Visit(node->expression());
   1064 }
   1065 
   1066 
   1067 void AstPrinter::VisitThisFunction(ThisFunction* node) {
   1068   IndentedScope indent(this, "THIS-FUNCTION");
   1069 }
   1070 
   1071 
   1072 TagScope::TagScope(JsonAstBuilder* builder, const char* name)
   1073     : builder_(builder), next_(builder->tag()), has_body_(false) {
   1074   if (next_ != NULL) {
   1075     next_->use();
   1076     builder->Print(",\n");
   1077   }
   1078   builder->set_tag(this);
   1079   builder->PrintIndented("[");
   1080   builder->Print("\"%s\"", name);
   1081   builder->increase_indent(JsonAstBuilder::kTagIndentSize);
   1082 }
   1083 
   1084 
   1085 TagScope::~TagScope() {
   1086   builder_->decrease_indent(JsonAstBuilder::kTagIndentSize);
   1087   if (has_body_) {
   1088     builder_->Print("\n");
   1089     builder_->PrintIndented("]");
   1090   } else {
   1091     builder_->Print("]");
   1092   }
   1093   builder_->set_tag(next_);
   1094 }
   1095 
   1096 
   1097 AttributesScope::AttributesScope(JsonAstBuilder* builder)
   1098     : builder_(builder), attribute_count_(0) {
   1099   builder->set_attributes(this);
   1100   builder->tag()->use();
   1101   builder->Print(",\n");
   1102   builder->PrintIndented("{");
   1103   builder->increase_indent(JsonAstBuilder::kAttributesIndentSize);
   1104 }
   1105 
   1106 
   1107 AttributesScope::~AttributesScope() {
   1108   builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize);
   1109   if (attribute_count_ > 1) {
   1110     builder_->Print("\n");
   1111     builder_->PrintIndented("}");
   1112   } else {
   1113     builder_->Print("}");
   1114   }
   1115   builder_->set_attributes(NULL);
   1116 }
   1117 
   1118 
   1119 const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) {
   1120   Init();
   1121   Visit(program);
   1122   Print("\n");
   1123   return Output();
   1124 }
   1125 
   1126 
   1127 void JsonAstBuilder::AddAttributePrefix(const char* name) {
   1128   if (attributes()->is_used()) {
   1129     Print(",\n");
   1130     PrintIndented("\"");
   1131   } else {
   1132     Print("\"");
   1133   }
   1134   Print("%s\":", name);
   1135   attributes()->use();
   1136 }
   1137 
   1138 
   1139 void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) {
   1140   SmartPointer<char> value_string = value->ToCString();
   1141   AddAttributePrefix(name);
   1142   Print("\"%s\"", *value_string);
   1143 }
   1144 
   1145 
   1146 void JsonAstBuilder::AddAttribute(const char* name, const char* value) {
   1147   AddAttributePrefix(name);
   1148   Print("\"%s\"", value);
   1149 }
   1150 
   1151 
   1152 void JsonAstBuilder::AddAttribute(const char* name, int value) {
   1153   AddAttributePrefix(name);
   1154   Print("%d", value);
   1155 }
   1156 
   1157 
   1158 void JsonAstBuilder::AddAttribute(const char* name, bool value) {
   1159   AddAttributePrefix(name);
   1160   Print(value ? "true" : "false");
   1161 }
   1162 
   1163 
   1164 void JsonAstBuilder::VisitBlock(Block* stmt) {
   1165   TagScope tag(this, "Block");
   1166   VisitStatements(stmt->statements());
   1167 }
   1168 
   1169 
   1170 void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
   1171   TagScope tag(this, "ExpressionStatement");
   1172   Visit(stmt->expression());
   1173 }
   1174 
   1175 
   1176 void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
   1177   TagScope tag(this, "EmptyStatement");
   1178 }
   1179 
   1180 
   1181 void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) {
   1182   TagScope tag(this, "IfStatement");
   1183   Visit(stmt->condition());
   1184   Visit(stmt->then_statement());
   1185   Visit(stmt->else_statement());
   1186 }
   1187 
   1188 
   1189 void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) {
   1190   TagScope tag(this, "ContinueStatement");
   1191 }
   1192 
   1193 
   1194 void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) {
   1195   TagScope tag(this, "BreakStatement");
   1196 }
   1197 
   1198 
   1199 void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) {
   1200   TagScope tag(this, "ReturnStatement");
   1201   Visit(stmt->expression());
   1202 }
   1203 
   1204 
   1205 void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
   1206   TagScope tag(this, "WithEnterStatement");
   1207   Visit(stmt->expression());
   1208 }
   1209 
   1210 
   1211 void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
   1212   TagScope tag(this, "WithExitStatement");
   1213 }
   1214 
   1215 
   1216 void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
   1217   TagScope tag(this, "SwitchStatement");
   1218 }
   1219 
   1220 
   1221 void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
   1222   TagScope tag(this, "DoWhileStatement");
   1223   Visit(stmt->body());
   1224   Visit(stmt->cond());
   1225 }
   1226 
   1227 
   1228 void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) {
   1229   TagScope tag(this, "WhileStatement");
   1230   Visit(stmt->cond());
   1231   Visit(stmt->body());
   1232 }
   1233 
   1234 
   1235 void JsonAstBuilder::VisitForStatement(ForStatement* stmt) {
   1236   TagScope tag(this, "ForStatement");
   1237   if (stmt->init() != NULL) Visit(stmt->init());
   1238   if (stmt->cond() != NULL) Visit(stmt->cond());
   1239   Visit(stmt->body());
   1240   if (stmt->next() != NULL) Visit(stmt->next());
   1241 }
   1242 
   1243 
   1244 void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) {
   1245   TagScope tag(this, "ForInStatement");
   1246   Visit(stmt->each());
   1247   Visit(stmt->enumerable());
   1248   Visit(stmt->body());
   1249 }
   1250 
   1251 
   1252 void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
   1253   TagScope tag(this, "TryCatchStatement");
   1254   Visit(stmt->try_block());
   1255   Visit(stmt->catch_var());
   1256   Visit(stmt->catch_block());
   1257 }
   1258 
   1259 
   1260 void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
   1261   TagScope tag(this, "TryFinallyStatement");
   1262   Visit(stmt->try_block());
   1263   Visit(stmt->finally_block());
   1264 }
   1265 
   1266 
   1267 void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
   1268   TagScope tag(this, "DebuggerStatement");
   1269 }
   1270 
   1271 
   1272 void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
   1273   TagScope tag(this, "FunctionLiteral");
   1274   {
   1275     AttributesScope attributes(this);
   1276     AddAttribute("name", expr->name());
   1277   }
   1278   VisitDeclarations(expr->scope()->declarations());
   1279   VisitStatements(expr->body());
   1280 }
   1281 
   1282 
   1283 void JsonAstBuilder::VisitSharedFunctionInfoLiteral(
   1284     SharedFunctionInfoLiteral* expr) {
   1285   TagScope tag(this, "SharedFunctionInfoLiteral");
   1286 }
   1287 
   1288 
   1289 void JsonAstBuilder::VisitConditional(Conditional* expr) {
   1290   TagScope tag(this, "Conditional");
   1291 }
   1292 
   1293 
   1294 void JsonAstBuilder::VisitSlot(Slot* expr) {
   1295   TagScope tag(this, "Slot");
   1296   {
   1297     AttributesScope attributes(this);
   1298     switch (expr->type()) {
   1299       case Slot::PARAMETER:
   1300         AddAttribute("type", "PARAMETER");
   1301         break;
   1302       case Slot::LOCAL:
   1303         AddAttribute("type", "LOCAL");
   1304         break;
   1305       case Slot::CONTEXT:
   1306         AddAttribute("type", "CONTEXT");
   1307         break;
   1308       case Slot::LOOKUP:
   1309         AddAttribute("type", "LOOKUP");
   1310         break;
   1311     }
   1312     AddAttribute("index", expr->index());
   1313   }
   1314 }
   1315 
   1316 
   1317 void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
   1318   if (expr->var()->rewrite() == NULL) {
   1319     TagScope tag(this, "VariableProxy");
   1320     {
   1321       AttributesScope attributes(this);
   1322       AddAttribute("name", expr->name());
   1323       AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
   1324     }
   1325   } else {
   1326     Visit(expr->var()->rewrite());
   1327   }
   1328 }
   1329 
   1330 
   1331 void JsonAstBuilder::VisitLiteral(Literal* expr) {
   1332   TagScope tag(this, "Literal");
   1333   {
   1334     AttributesScope attributes(this);
   1335     Handle<Object> handle = expr->handle();
   1336     if (handle->IsString()) {
   1337       AddAttribute("handle", Handle<String>(String::cast(*handle)));
   1338     } else if (handle->IsSmi()) {
   1339       AddAttribute("handle", Smi::cast(*handle)->value());
   1340     }
   1341   }
   1342 }
   1343 
   1344 
   1345 void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
   1346   TagScope tag(this, "RegExpLiteral");
   1347 }
   1348 
   1349 
   1350 void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
   1351   TagScope tag(this, "ObjectLiteral");
   1352 }
   1353 
   1354 
   1355 void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
   1356   TagScope tag(this, "ArrayLiteral");
   1357 }
   1358 
   1359 
   1360 void JsonAstBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
   1361   TagScope tag(this, "CatchExtensionObject");
   1362   Visit(expr->key());
   1363   Visit(expr->value());
   1364 }
   1365 
   1366 
   1367 void JsonAstBuilder::VisitAssignment(Assignment* expr) {
   1368   TagScope tag(this, "Assignment");
   1369   {
   1370     AttributesScope attributes(this);
   1371     AddAttribute("op", Token::Name(expr->op()));
   1372   }
   1373   Visit(expr->target());
   1374   Visit(expr->value());
   1375 }
   1376 
   1377 
   1378 void JsonAstBuilder::VisitThrow(Throw* expr) {
   1379   TagScope tag(this, "Throw");
   1380   Visit(expr->exception());
   1381 }
   1382 
   1383 
   1384 void JsonAstBuilder::VisitProperty(Property* expr) {
   1385   TagScope tag(this, "Property");
   1386   {
   1387     AttributesScope attributes(this);
   1388     AddAttribute("type", expr->is_synthetic() ? "SYNTHETIC" : "NORMAL");
   1389   }
   1390   Visit(expr->obj());
   1391   Visit(expr->key());
   1392 }
   1393 
   1394 
   1395 void JsonAstBuilder::VisitCall(Call* expr) {
   1396   TagScope tag(this, "Call");
   1397   Visit(expr->expression());
   1398   VisitExpressions(expr->arguments());
   1399 }
   1400 
   1401 
   1402 void JsonAstBuilder::VisitCallNew(CallNew* expr) {
   1403   TagScope tag(this, "CallNew");
   1404   Visit(expr->expression());
   1405   VisitExpressions(expr->arguments());
   1406 }
   1407 
   1408 
   1409 void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) {
   1410   TagScope tag(this, "CallRuntime");
   1411   {
   1412     AttributesScope attributes(this);
   1413     AddAttribute("name", expr->name());
   1414   }
   1415   VisitExpressions(expr->arguments());
   1416 }
   1417 
   1418 
   1419 void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) {
   1420   TagScope tag(this, "UnaryOperation");
   1421   {
   1422     AttributesScope attributes(this);
   1423     AddAttribute("op", Token::Name(expr->op()));
   1424   }
   1425   Visit(expr->expression());
   1426 }
   1427 
   1428 
   1429 void JsonAstBuilder::VisitCountOperation(CountOperation* expr) {
   1430   TagScope tag(this, "CountOperation");
   1431   {
   1432     AttributesScope attributes(this);
   1433     AddAttribute("is_prefix", expr->is_prefix());
   1434     AddAttribute("op", Token::Name(expr->op()));
   1435   }
   1436   Visit(expr->expression());
   1437 }
   1438 
   1439 
   1440 void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) {
   1441   TagScope tag(this, "BinaryOperation");
   1442   {
   1443     AttributesScope attributes(this);
   1444     AddAttribute("op", Token::Name(expr->op()));
   1445   }
   1446   Visit(expr->left());
   1447   Visit(expr->right());
   1448 }
   1449 
   1450 
   1451 void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) {
   1452   TagScope tag(this, "CompareOperation");
   1453   {
   1454     AttributesScope attributes(this);
   1455     AddAttribute("op", Token::Name(expr->op()));
   1456   }
   1457   Visit(expr->left());
   1458   Visit(expr->right());
   1459 }
   1460 
   1461 
   1462 void JsonAstBuilder::VisitCompareToNull(CompareToNull* expr) {
   1463   TagScope tag(this, "CompareToNull");
   1464   {
   1465     AttributesScope attributes(this);
   1466     AddAttribute("is_strict", expr->is_strict());
   1467   }
   1468   Visit(expr->expression());
   1469 }
   1470 
   1471 
   1472 void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) {
   1473   TagScope tag(this, "ThisFunction");
   1474 }
   1475 
   1476 
   1477 void JsonAstBuilder::VisitDeclaration(Declaration* decl) {
   1478   TagScope tag(this, "Declaration");
   1479   {
   1480     AttributesScope attributes(this);
   1481     AddAttribute("mode", Variable::Mode2String(decl->mode()));
   1482   }
   1483   Visit(decl->proxy());
   1484   if (decl->fun() != NULL) Visit(decl->fun());
   1485 }
   1486 
   1487 
   1488 #endif  // DEBUG
   1489 
   1490 } }  // namespace v8::internal
   1491