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