LCOV - code coverage report
Current view: top level - src/ast - prettyprinter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 269 305 88.2 %
Date: 2017-10-20 Functions: 45 63 71.4 %

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

Generated by: LCOV version 1.10