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