LCOV - code coverage report
Current view: top level - src/ast - prettyprinter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 302 353 85.6 %
Date: 2019-02-19 Functions: 47 68 69.1 %

          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             : #include "src/string-builder-inl.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19        6409 : CallPrinter::CallPrinter(Isolate* isolate, bool is_user_js)
      20        6409 :     : builder_(new IncrementalStringBuilder(isolate)) {
      21        6409 :   isolate_ = isolate;
      22        6409 :   position_ = 0;
      23        6409 :   num_prints_ = 0;
      24        6409 :   found_ = false;
      25        6409 :   done_ = false;
      26        6409 :   is_call_error_ = false;
      27        6409 :   is_iterator_error_ = false;
      28        6409 :   is_async_iterator_error_ = false;
      29        6409 :   is_user_js_ = is_user_js;
      30        6409 :   function_kind_ = kNormalFunction;
      31             :   InitializeAstVisitor(isolate);
      32        6409 : }
      33             : 
      34             : CallPrinter::~CallPrinter() = default;
      35             : 
      36        6409 : CallPrinter::ErrorHint CallPrinter::GetErrorHint() const {
      37        6409 :   if (is_call_error_) {
      38        5762 :     if (is_iterator_error_) return ErrorHint::kCallAndNormalIterator;
      39        5688 :     if (is_async_iterator_error_) return ErrorHint::kCallAndAsyncIterator;
      40             :   } else {
      41         647 :     if (is_iterator_error_) return ErrorHint::kNormalIterator;
      42         572 :     if (is_async_iterator_error_) return ErrorHint::kAsyncIterator;
      43             :   }
      44        6251 :   return ErrorHint::kNone;
      45             : }
      46             : 
      47        6409 : Handle<String> CallPrinter::Print(FunctionLiteral* program, int position) {
      48        6409 :   num_prints_ = 0;
      49        6409 :   position_ = position;
      50        6409 :   Find(program);
      51       12818 :   return builder_->Finish().ToHandleChecked();
      52             : }
      53             : 
      54             : 
      55      197367 : void CallPrinter::Find(AstNode* node, bool print) {
      56      197367 :   if (found_) {
      57       13685 :     if (print) {
      58       11842 :       int prev_num_prints = num_prints_;
      59       11842 :       Visit(node);
      60      209209 :       if (prev_num_prints != num_prints_) return;
      61             :     }
      62        1897 :     Print("(intermediate value)");
      63             :   } else {
      64      183682 :     Visit(node);
      65             :   }
      66             : }
      67             : 
      68       94117 : void CallPrinter::Print(const char* str) {
      69      188234 :   if (!found_ || done_) return;
      70        9264 :   num_prints_++;
      71             :   builder_->AppendCString(str);
      72             : }
      73             : 
      74       96342 : void CallPrinter::Print(Handle<String> str) {
      75      192684 :   if (!found_ || done_) return;
      76        9202 :   num_prints_++;
      77        9202 :   builder_->AppendString(str);
      78             : }
      79             : 
      80           0 : void CallPrinter::VisitBlock(Block* node) {
      81       13790 :   FindStatements(node->statements());
      82           0 : }
      83             : 
      84             : 
      85           0 : void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {}
      86             : 
      87             : 
      88           0 : void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {}
      89             : 
      90             : 
      91       25666 : void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) {
      92       25666 :   Find(node->expression());
      93       25666 : }
      94             : 
      95             : 
      96           0 : void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {}
      97             : 
      98             : 
      99          36 : void CallPrinter::VisitSloppyBlockFunctionStatement(
     100          36 :     SloppyBlockFunctionStatement* node) {
     101          36 :   Find(node->statement());
     102          36 : }
     103             : 
     104             : 
     105         243 : void CallPrinter::VisitIfStatement(IfStatement* node) {
     106          81 :   Find(node->condition());
     107          81 :   Find(node->then_statement());
     108          81 :   if (node->HasElseStatement()) {
     109          18 :     Find(node->else_statement());
     110             :   }
     111          81 : }
     112             : 
     113             : 
     114           0 : void CallPrinter::VisitContinueStatement(ContinueStatement* node) {}
     115             : 
     116             : 
     117           0 : void CallPrinter::VisitBreakStatement(BreakStatement* node) {}
     118             : 
     119             : 
     120        2500 : void CallPrinter::VisitReturnStatement(ReturnStatement* node) {
     121        2500 :   Find(node->expression());
     122        2500 : }
     123             : 
     124             : 
     125          28 : void CallPrinter::VisitWithStatement(WithStatement* node) {
     126          14 :   Find(node->expression());
     127          14 :   Find(node->statement());
     128          14 : }
     129             : 
     130             : 
     131          18 : void CallPrinter::VisitSwitchStatement(SwitchStatement* node) {
     132          18 :   Find(node->tag());
     133          63 :   for (CaseClause* clause : *node->cases()) {
     134          27 :     if (!clause->is_default()) Find(clause->label());
     135          27 :     FindStatements(clause->statements());
     136             :   }
     137          18 : }
     138             : 
     139             : 
     140          18 : void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
     141           9 :   Find(node->body());
     142           9 :   Find(node->cond());
     143           9 : }
     144             : 
     145             : 
     146           9 : void CallPrinter::VisitWhileStatement(WhileStatement* node) {
     147           9 :   Find(node->cond());
     148           9 :   Find(node->body());
     149           9 : }
     150             : 
     151             : 
     152         891 : void CallPrinter::VisitForStatement(ForStatement* node) {
     153         297 :   if (node->init() != nullptr) {
     154         288 :     Find(node->init());
     155             :   }
     156         297 :   if (node->cond() != nullptr) Find(node->cond());
     157         297 :   if (node->next() != nullptr) Find(node->next());
     158         297 :   Find(node->body());
     159         297 : }
     160             : 
     161             : 
     162          27 : void CallPrinter::VisitForInStatement(ForInStatement* node) {
     163          27 :   Find(node->each());
     164          27 :   Find(node->subject());
     165          27 :   Find(node->body());
     166          27 : }
     167             : 
     168             : 
     169         838 : void CallPrinter::VisitForOfStatement(ForOfStatement* node) {
     170        1558 :   Find(node->each());
     171             : 
     172             :   // Check the subject's position in case there was a GetIterator error.
     173             :   bool was_found = false;
     174         779 :   if (node->subject()->position() == position_) {
     175          59 :     is_async_iterator_error_ = node->type() == IteratorType::kAsync;
     176          59 :     is_iterator_error_ = !is_async_iterator_error_;
     177          59 :     was_found = !found_;
     178          59 :     if (was_found) {
     179          59 :       found_ = true;
     180             :     }
     181             :   }
     182         779 :   Find(node->subject(), true);
     183         779 :   if (was_found) {
     184          59 :     done_ = true;
     185          59 :     found_ = false;
     186             :   }
     187             : 
     188         779 :   Find(node->body());
     189         779 : }
     190             : 
     191             : 
     192        4742 : void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
     193        2371 :   Find(node->try_block());
     194        2371 :   Find(node->catch_block());
     195        2371 : }
     196             : 
     197             : 
     198         288 : void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
     199         144 :   Find(node->try_block());
     200         144 :   Find(node->finally_block());
     201         144 : }
     202             : 
     203             : 
     204           0 : void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {}
     205             : 
     206             : 
     207        6812 : void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
     208        6812 :   FunctionKind last_function_kind = function_kind_;
     209        6812 :   function_kind_ = node->kind();
     210        6812 :   FindStatements(node->body());
     211        6812 :   function_kind_ = last_function_kind;
     212        6812 : }
     213             : 
     214             : 
     215        4347 : void CallPrinter::VisitClassLiteral(ClassLiteral* node) {
     216        1449 :   if (node->extends()) Find(node->extends());
     217        4347 :   for (int i = 0; i < node->properties()->length(); i++) {
     218        1449 :     Find(node->properties()->at(i)->value());
     219             :   }
     220        1449 : }
     221             : 
     222           0 : void CallPrinter::VisitInitializeClassMembersStatement(
     223           0 :     InitializeClassMembersStatement* node) {
     224           0 :   for (int i = 0; i < node->fields()->length(); i++) {
     225           0 :     Find(node->fields()->at(i)->value());
     226             :   }
     227           0 : }
     228             : 
     229           0 : void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
     230             : 
     231             : 
     232           0 : void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); }
     233             : 
     234             : 
     235         405 : void CallPrinter::VisitConditional(Conditional* node) {
     236         135 :   Find(node->condition());
     237         135 :   Find(node->then_expression());
     238         135 :   Find(node->else_expression());
     239         135 : }
     240             : 
     241             : 
     242       15658 : void CallPrinter::VisitLiteral(Literal* node) {
     243             :   // TODO(adamk): Teach Literal how to print its values without
     244             :   // allocating on the heap.
     245       15658 :   PrintLiteral(node->BuildValue(isolate_), true);
     246       15658 : }
     247             : 
     248             : 
     249        1799 : void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
     250         257 :   Print("/");
     251         257 :   PrintLiteral(node->pattern(), false);
     252         257 :   Print("/");
     253         257 :   if (node->flags() & RegExp::kGlobal) Print("g");
     254         257 :   if (node->flags() & RegExp::kIgnoreCase) Print("i");
     255         257 :   if (node->flags() & RegExp::kMultiline) Print("m");
     256         257 :   if (node->flags() & RegExp::kUnicode) Print("u");
     257         257 :   if (node->flags() & RegExp::kSticky) Print("y");
     258         257 : }
     259             : 
     260             : 
     261        2822 : void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) {
     262        2822 :   Print("{");
     263        6924 :   for (int i = 0; i < node->properties()->length(); i++) {
     264        4102 :     Find(node->properties()->at(i)->value());
     265             :   }
     266        2822 :   Print("}");
     267        2822 : }
     268             : 
     269             : 
     270        1756 : void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) {
     271        1756 :   Print("[");
     272       10979 :   for (int i = 0; i < node->values()->length(); i++) {
     273        9228 :     if (i != 0) Print(",");
     274        9228 :     Expression* subexpr = node->values()->at(i);
     275        9598 :     Spread* spread = subexpr->AsSpread();
     276        9593 :     if (spread != nullptr && !found_ &&
     277         730 :         position_ == spread->expression()->position()) {
     278           5 :       found_ = true;
     279           5 :       is_iterator_error_ = true;
     280           5 :       Find(spread->expression(), true);
     281           5 :       done_ = true;
     282        1761 :       return;
     283             :     }
     284        9223 :     Find(subexpr, true);
     285             :   }
     286        1751 :   Print("]");
     287             : }
     288             : 
     289             : 
     290       56245 : void CallPrinter::VisitVariableProxy(VariableProxy* node) {
     291       56245 :   if (is_user_js_) {
     292       56245 :     PrintLiteral(node->name(), false);
     293             :   } else {
     294             :     // Variable names of non-user code are meaningless due to minification.
     295           0 :     Print("(var)");
     296             :   }
     297       56245 : }
     298             : 
     299             : 
     300       25417 : void CallPrinter::VisitAssignment(Assignment* node) {
     301        8357 :   Find(node->target());
     302        8357 :   if (node->target()->IsArrayLiteral()) {
     303             :     // Special case the visit for destructuring array assignment.
     304             :     bool was_found = false;
     305         346 :     if (node->value()->position() == position_) {
     306          94 :       is_iterator_error_ = true;
     307          94 :       was_found = !found_;
     308          94 :       if (was_found) {
     309          94 :         found_ = true;
     310             :       }
     311             :     }
     312         346 :     Find(node->value(), true);
     313         346 :     if (was_found) {
     314          94 :       done_ = true;
     315          94 :       found_ = false;
     316             :     }
     317             :   } else {
     318        8011 :     Find(node->value());
     319             :   }
     320        8357 : }
     321             : 
     322           0 : void CallPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
     323           0 :   VisitAssignment(node);
     324           0 : }
     325             : 
     326         189 : void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
     327             : 
     328          54 : void CallPrinter::VisitYieldStar(YieldStar* node) {
     329         108 :   if (!found_ && position_ == node->expression()->position()) {
     330           0 :     found_ = true;
     331           0 :     if (IsAsyncFunction(function_kind_))
     332           0 :       is_async_iterator_error_ = true;
     333             :     else
     334           0 :       is_iterator_error_ = true;
     335           0 :     Print("yield* ");
     336             :   }
     337          54 :   Find(node->expression());
     338          54 : }
     339             : 
     340          72 : void CallPrinter::VisitAwait(Await* node) { Find(node->expression()); }
     341             : 
     342          86 : void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); }
     343             : 
     344             : 
     345       62708 : void CallPrinter::VisitProperty(Property* node) {
     346             :   Expression* key = node->key();
     347       31354 :   Literal* literal = key->AsLiteral();
     348       94062 :   if (literal != nullptr &&
     349      124159 :       literal->BuildValue(isolate_)->IsInternalizedString()) {
     350       30470 :     Find(node->obj(), true);
     351       30470 :     Print(".");
     352             :     // TODO(adamk): Teach Literal how to print its values without
     353             :     // allocating on the heap.
     354       30470 :     PrintLiteral(literal->BuildValue(isolate_), false);
     355             :   } else {
     356         884 :     Find(node->obj(), true);
     357         884 :     Print("[");
     358         884 :     Find(key, true);
     359         884 :     Print("]");
     360             :   }
     361       31354 : }
     362             : 
     363           0 : void CallPrinter::VisitResolvedProperty(ResolvedProperty* node) {}
     364             : 
     365       37374 : void CallPrinter::VisitCall(Call* node) {
     366             :   bool was_found = false;
     367       18687 :   if (node->position() == position_) {
     368        3896 :     is_call_error_ = true;
     369        3896 :     was_found = !found_;
     370             :   }
     371       18687 :   if (was_found) {
     372             :     // Bail out if the error is caused by a direct call to a variable in
     373             :     // non-user JS code. The variable name is meaningless due to minification.
     374        3827 :     if (!is_user_js_ && node->expression()->IsVariableProxy()) {
     375           0 :       done_ = true;
     376       18687 :       return;
     377             :     }
     378        3827 :     found_ = true;
     379             :   }
     380       18687 :   Find(node->expression(), true);
     381       18687 :   if (!was_found && !is_iterator_error_) Print("(...)");
     382       18687 :   FindArguments(node->arguments());
     383       18687 :   if (was_found) {
     384        3827 :     done_ = true;
     385        3827 :     found_ = false;
     386             :   }
     387             : }
     388             : 
     389             : 
     390        5102 : void CallPrinter::VisitCallNew(CallNew* node) {
     391             :   bool was_found = false;
     392        2551 :   if (node->position() == position_) {
     393        1866 :     is_call_error_ = true;
     394        1866 :     was_found = !found_;
     395             :   }
     396        2551 :   if (was_found) {
     397             :     // Bail out if the error is caused by a direct call to a variable in
     398             :     // non-user JS code. The variable name is meaningless due to minification.
     399        1861 :     if (!is_user_js_ && node->expression()->IsVariableProxy()) {
     400           0 :       done_ = true;
     401        2551 :       return;
     402             :     }
     403        1861 :     found_ = true;
     404             :   }
     405        5102 :   Find(node->expression(), was_found || is_iterator_error_);
     406        2551 :   FindArguments(node->arguments());
     407        2551 :   if (was_found) {
     408        1861 :     done_ = true;
     409        1861 :     found_ = false;
     410             :   }
     411             : }
     412             : 
     413             : 
     414         378 : void CallPrinter::VisitCallRuntime(CallRuntime* node) {
     415         378 :   FindArguments(node->arguments());
     416         378 : }
     417             : 
     418             : 
     419         846 : void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
     420             :   Token::Value op = node->op();
     421             :   bool needsSpace =
     422         423 :       op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
     423         423 :   Print("(");
     424         423 :   Print(Token::String(op));
     425         423 :   if (needsSpace) Print(" ");
     426         423 :   Find(node->expression(), true);
     427         423 :   Print(")");
     428         423 : }
     429             : 
     430             : 
     431         945 : void CallPrinter::VisitCountOperation(CountOperation* node) {
     432         315 :   Print("(");
     433         324 :   if (node->is_prefix()) Print(Token::String(node->op()));
     434         315 :   Find(node->expression(), true);
     435         621 :   if (node->is_postfix()) Print(Token::String(node->op()));
     436         315 :   Print(")");
     437         315 : }
     438             : 
     439             : 
     440        1116 : void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
     441         279 :   Print("(");
     442         279 :   Find(node->left(), true);
     443         279 :   Print(" ");
     444         279 :   Print(Token::String(node->op()));
     445         279 :   Print(" ");
     446         279 :   Find(node->right(), true);
     447         279 :   Print(")");
     448         279 : }
     449             : 
     450         180 : void CallPrinter::VisitNaryOperation(NaryOperation* node) {
     451          45 :   Print("(");
     452          45 :   Find(node->first(), true);
     453         270 :   for (size_t i = 0; i < node->subsequent_length(); ++i) {
     454          90 :     Print(" ");
     455          90 :     Print(Token::String(node->op()));
     456          90 :     Print(" ");
     457          90 :     Find(node->subsequent(i), true);
     458             :   }
     459          45 :   Print(")");
     460          45 : }
     461             : 
     462        5240 : void CallPrinter::VisitCompareOperation(CompareOperation* node) {
     463        1310 :   Print("(");
     464        1310 :   Find(node->left(), true);
     465        1310 :   Print(" ");
     466        1310 :   Print(Token::String(node->op()));
     467        1310 :   Print(" ");
     468        1310 :   Find(node->right(), true);
     469        1310 :   Print(")");
     470        1310 : }
     471             : 
     472             : 
     473         738 : void CallPrinter::VisitSpread(Spread* node) {
     474         369 :   Print("(...");
     475         369 :   Find(node->expression(), true);
     476         369 :   Print(")");
     477         369 : }
     478             : 
     479           0 : void CallPrinter::VisitStoreInArrayLiteral(StoreInArrayLiteral* node) {
     480           0 :   Find(node->array());
     481           0 :   Find(node->index());
     482           0 :   Find(node->value());
     483           0 : }
     484             : 
     485           0 : void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
     486           0 :   UNREACHABLE();
     487             : }
     488             : 
     489           0 : void CallPrinter::VisitGetTemplateObject(GetTemplateObject* node) {}
     490             : 
     491           0 : void CallPrinter::VisitTemplateLiteral(TemplateLiteral* node) {
     492           0 :   for (Expression* substitution : *node->substitutions()) {
     493           0 :     Find(substitution, true);
     494             :   }
     495           0 : }
     496             : 
     497           0 : void CallPrinter::VisitImportCallExpression(ImportCallExpression* node) {
     498           0 :   Print("ImportCall(");
     499           0 :   Find(node->argument(), true);
     500           0 :   Print(")");
     501           0 : }
     502             : 
     503          81 : void CallPrinter::VisitThisExpression(ThisExpression* node) { Print("this"); }
     504             : 
     505           0 : void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
     506             : 
     507             : 
     508           0 : void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
     509           9 :   Print("super");
     510           0 : }
     511             : 
     512             : 
     513       80195 : void CallPrinter::FindStatements(const ZonePtrList<Statement>* statements) {
     514       41258 :   if (statements == nullptr) return;
     515       98503 :   for (int i = 0; i < statements->length(); i++) {
     516       38937 :     Find(statements->at(i));
     517             :   }
     518             : }
     519             : 
     520       61974 : void CallPrinter::FindArguments(const ZonePtrList<Expression>* arguments) {
     521       43232 :   if (found_) return;
     522       65066 :   for (int i = 0; i < arguments->length(); i++) {
     523       24708 :     Find(arguments->at(i));
     524             :   }
     525             : }
     526             : 
     527      102630 : void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) {
     528      205260 :   if (value->IsString()) {
     529       91881 :     if (quote) Print("\"");
     530       91881 :     Print(Handle<String>::cast(value));
     531       91881 :     if (quote) Print("\"");
     532       32247 :   } else if (value->IsNull(isolate_)) {
     533         720 :     Print("null");
     534       30087 :   } else if (value->IsTrue(isolate_)) {
     535        2349 :     Print("true");
     536       23040 :   } else if (value->IsFalse(isolate_)) {
     537        2949 :     Print("false");
     538       14193 :   } else if (value->IsUndefined(isolate_)) {
     539         261 :     Print("undefined");
     540        8940 :   } else if (value->IsNumber()) {
     541        4461 :     Print(isolate_->factory()->NumberToString(value));
     542          18 :   } else if (value->IsSymbol()) {
     543             :     // Symbols can only occur as literals if they were inserted by the parser.
     544           0 :     PrintLiteral(handle(Handle<Symbol>::cast(value)->name(), isolate_), false);
     545             :   }
     546      102630 : }
     547             : 
     548             : 
     549           0 : void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
     550           0 :   PrintLiteral(value->string(), quote);
     551           0 : }
     552             : 
     553             : 
     554             : //-----------------------------------------------------------------------------
     555             : 
     556             : 
     557             : #ifdef DEBUG
     558             : 
     559             : const char* AstPrinter::Print(AstNode* node) {
     560             :   Init();
     561             :   Visit(node);
     562             :   return output_;
     563             : }
     564             : 
     565             : void AstPrinter::Init() {
     566             :   if (size_ == 0) {
     567             :     DCHECK_NULL(output_);
     568             :     const int initial_size = 256;
     569             :     output_ = NewArray<char>(initial_size);
     570             :     size_ = initial_size;
     571             :   }
     572             :   output_[0] = '\0';
     573             :   pos_ = 0;
     574             : }
     575             : 
     576             : void AstPrinter::Print(const char* format, ...) {
     577             :   for (;;) {
     578             :     va_list arguments;
     579             :     va_start(arguments, format);
     580             :     int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
     581             :                       format,
     582             :                       arguments);
     583             :     va_end(arguments);
     584             : 
     585             :     if (n >= 0) {
     586             :       // there was enough space - we are done
     587             :       pos_ += n;
     588             :       return;
     589             :     } else {
     590             :       // there was not enough space - allocate more and try again
     591             :       const int slack = 32;
     592             :       int new_size = size_ + (size_ >> 1) + slack;
     593             :       char* new_output = NewArray<char>(new_size);
     594             :       MemCopy(new_output, output_, pos_);
     595             :       DeleteArray(output_);
     596             :       output_ = new_output;
     597             :       size_ = new_size;
     598             :     }
     599             :   }
     600             : }
     601             : 
     602             : void AstPrinter::PrintLabels(ZonePtrList<const AstRawString>* labels) {
     603             :   if (labels != nullptr) {
     604             :     for (int i = 0; i < labels->length(); i++) {
     605             :       PrintLiteral(labels->at(i), false);
     606             :       Print(": ");
     607             :     }
     608             :   }
     609             : }
     610             : 
     611             : void AstPrinter::PrintLiteral(Literal* literal, bool quote) {
     612             :   switch (literal->type()) {
     613             :     case Literal::kString:
     614             :       PrintLiteral(literal->AsRawString(), quote);
     615             :       break;
     616             :     case Literal::kSymbol:
     617             :       const char* symbol;
     618             :       switch (literal->AsSymbol()) {
     619             :         case AstSymbol::kHomeObjectSymbol:
     620             :           symbol = "HomeObjectSymbol";
     621             :       }
     622             :       Print("%s", symbol);
     623             :       break;
     624             :     case Literal::kSmi:
     625             :       Print("%d", Smi::ToInt(literal->AsSmiLiteral()));
     626             :       break;
     627             :     case Literal::kHeapNumber:
     628             :       Print("%g", literal->AsNumber());
     629             :       break;
     630             :     case Literal::kBigInt:
     631             :       Print("%sn", literal->AsBigInt().c_str());
     632             :       break;
     633             :     case Literal::kNull:
     634             :       Print("null");
     635             :       break;
     636             :     case Literal::kUndefined:
     637             :       Print("undefined");
     638             :       break;
     639             :     case Literal::kTheHole:
     640             :       Print("the hole");
     641             :       break;
     642             :     case Literal::kBoolean:
     643             :       if (literal->ToBooleanIsTrue()) {
     644             :         Print("true");
     645             :       } else {
     646             :         Print("false");
     647             :       }
     648             :       break;
     649             :   }
     650             : }
     651             : 
     652             : void AstPrinter::PrintLiteral(const AstRawString* value, bool quote) {
     653             :   if (quote) Print("\"");
     654             :   if (value != nullptr) {
     655             :     const char* format = value->is_one_byte() ? "%c" : "%lc";
     656             :     const int increment = value->is_one_byte() ? 1 : 2;
     657             :     const unsigned char* raw_bytes = value->raw_data();
     658             :     for (int i = 0; i < value->length(); i += increment) {
     659             :       Print(format, raw_bytes[i]);
     660             :     }
     661             :   }
     662             :   if (quote) Print("\"");
     663             : }
     664             : 
     665             : void AstPrinter::PrintLiteral(const AstConsString* value, bool quote) {
     666             :   if (quote) Print("\"");
     667             :   if (value != nullptr) {
     668             :     std::forward_list<const AstRawString*> strings = value->ToRawStrings();
     669             :     for (const AstRawString* string : strings) {
     670             :       PrintLiteral(string, false);
     671             :     }
     672             :   }
     673             :   if (quote) Print("\"");
     674             : }
     675             : 
     676             : //-----------------------------------------------------------------------------
     677             : 
     678             : class IndentedScope {
     679             :  public:
     680             :   IndentedScope(AstPrinter* printer, const char* txt)
     681             :       : ast_printer_(printer) {
     682             :     ast_printer_->PrintIndented(txt);
     683             :     ast_printer_->Print("\n");
     684             :     ast_printer_->inc_indent();
     685             :   }
     686             : 
     687             :   IndentedScope(AstPrinter* printer, const char* txt, int pos)
     688             :       : ast_printer_(printer) {
     689             :     ast_printer_->PrintIndented(txt);
     690             :     ast_printer_->Print(" at %d\n", pos);
     691             :     ast_printer_->inc_indent();
     692             :   }
     693             : 
     694             :   virtual ~IndentedScope() {
     695             :     ast_printer_->dec_indent();
     696             :   }
     697             : 
     698             :  private:
     699             :   AstPrinter* ast_printer_;
     700             : };
     701             : 
     702             : 
     703             : //-----------------------------------------------------------------------------
     704             : 
     705             : AstPrinter::AstPrinter(uintptr_t stack_limit)
     706             :     : output_(nullptr), size_(0), pos_(0), indent_(0) {
     707             :   InitializeAstVisitor(stack_limit);
     708             : }
     709             : 
     710             : AstPrinter::~AstPrinter() {
     711             :   DCHECK_EQ(indent_, 0);
     712             :   DeleteArray(output_);
     713             : }
     714             : 
     715             : 
     716             : void AstPrinter::PrintIndented(const char* txt) {
     717             :   for (int i = 0; i < indent_; i++) {
     718             :     Print(". ");
     719             :   }
     720             :   Print("%s", txt);
     721             : }
     722             : 
     723             : void AstPrinter::PrintLiteralIndented(const char* info, Literal* literal,
     724             :                                       bool quote) {
     725             :   PrintIndented(info);
     726             :   Print(" ");
     727             :   PrintLiteral(literal, quote);
     728             :   Print("\n");
     729             : }
     730             : 
     731             : void AstPrinter::PrintLiteralIndented(const char* info,
     732             :                                       const AstRawString* value, bool quote) {
     733             :   PrintIndented(info);
     734             :   Print(" ");
     735             :   PrintLiteral(value, quote);
     736             :   Print("\n");
     737             : }
     738             : 
     739             : void AstPrinter::PrintLiteralIndented(const char* info,
     740             :                                       const AstConsString* value, bool quote) {
     741             :   PrintIndented(info);
     742             :   Print(" ");
     743             :   PrintLiteral(value, quote);
     744             :   Print("\n");
     745             : }
     746             : 
     747             : void AstPrinter::PrintLiteralWithModeIndented(const char* info, Variable* var,
     748             :                                               const AstRawString* value) {
     749             :   if (var == nullptr) {
     750             :     PrintLiteralIndented(info, value, true);
     751             :   } else {
     752             :     EmbeddedVector<char, 256> buf;
     753             :     int pos =
     754             :         SNPrintF(buf, "%s (%p) (mode = %s, assigned = %s", info,
     755             :                  reinterpret_cast<void*>(var), VariableMode2String(var->mode()),
     756             :                  var->maybe_assigned() == kMaybeAssigned ? "true" : "false");
     757             :     SNPrintF(buf + pos, ")");
     758             :     PrintLiteralIndented(buf.start(), value, true);
     759             :   }
     760             : }
     761             : 
     762             : void AstPrinter::PrintLabelsIndented(ZonePtrList<const AstRawString>* labels,
     763             :                                      const char* prefix) {
     764             :   if (labels == nullptr || labels->length() == 0) return;
     765             :   PrintIndented(prefix);
     766             :   Print("LABELS ");
     767             :   PrintLabels(labels);
     768             :   Print("\n");
     769             : }
     770             : 
     771             : 
     772             : void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
     773             :   if (node != nullptr) {
     774             :     IndentedScope indent(this, s, node->position());
     775             :     Visit(node);
     776             :   }
     777             : }
     778             : 
     779             : 
     780             : const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
     781             :   Init();
     782             :   { IndentedScope indent(this, "FUNC", program->position());
     783             :     PrintIndented("KIND");
     784             :     Print(" %d\n", program->kind());
     785             :     PrintIndented("LITERAL ID");
     786             :     Print(" %d\n", program->function_literal_id());
     787             :     PrintIndented("SUSPEND COUNT");
     788             :     Print(" %d\n", program->suspend_count());
     789             :     PrintLiteralIndented("NAME", program->raw_name(), true);
     790             :     if (program->raw_inferred_name()) {
     791             :       PrintLiteralIndented("INFERRED NAME", program->raw_inferred_name(), true);
     792             :     }
     793             :     if (program->requires_instance_members_initializer()) {
     794             :       Print(" REQUIRES INSTANCE FIELDS INITIALIZER\n");
     795             :     }
     796             :     PrintParameters(program->scope());
     797             :     PrintDeclarations(program->scope()->declarations());
     798             :     PrintStatements(program->body());
     799             :   }
     800             :   return output_;
     801             : }
     802             : 
     803             : 
     804             : void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) {
     805             :   AstPrinter printer(isolate->stack_guard()->real_climit());
     806             :   printer.Init();
     807             :   printer.Visit(node);
     808             :   PrintF("%s", printer.output_);
     809             : }
     810             : 
     811             : void AstPrinter::PrintDeclarations(Declaration::List* declarations) {
     812             :   if (!declarations->is_empty()) {
     813             :     IndentedScope indent(this, "DECLS");
     814             :     for (Declaration* decl : *declarations) Visit(decl);
     815             :   }
     816             : }
     817             : 
     818             : void AstPrinter::PrintParameters(DeclarationScope* scope) {
     819             :   if (scope->num_parameters() > 0) {
     820             :     IndentedScope indent(this, "PARAMS");
     821             :     for (int i = 0; i < scope->num_parameters(); i++) {
     822             :       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
     823             :                                    scope->parameter(i)->raw_name());
     824             :     }
     825             :   }
     826             : }
     827             : 
     828             : void AstPrinter::PrintStatements(const ZonePtrList<Statement>* statements) {
     829             :   for (int i = 0; i < statements->length(); i++) {
     830             :     Visit(statements->at(i));
     831             :   }
     832             : }
     833             : 
     834             : void AstPrinter::PrintArguments(const ZonePtrList<Expression>* arguments) {
     835             :   for (int i = 0; i < arguments->length(); i++) {
     836             :     Visit(arguments->at(i));
     837             :   }
     838             : }
     839             : 
     840             : 
     841             : void AstPrinter::VisitBlock(Block* node) {
     842             :   const char* block_txt =
     843             :       node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK";
     844             :   IndentedScope indent(this, block_txt, node->position());
     845             :   PrintLabelsIndented(node->labels());
     846             :   PrintStatements(node->statements());
     847             : }
     848             : 
     849             : 
     850             : // TODO(svenpanne) Start with IndentedScope.
     851             : void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
     852             :   PrintLiteralWithModeIndented("VARIABLE", node->var(),
     853             :                                node->var()->raw_name());
     854             : }
     855             : 
     856             : 
     857             : // TODO(svenpanne) Start with IndentedScope.
     858             : void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
     859             :   PrintIndented("FUNCTION ");
     860             :   PrintLiteral(node->var()->raw_name(), true);
     861             :   Print(" = function ");
     862             :   PrintLiteral(node->fun()->raw_name(), false);
     863             :   Print("\n");
     864             : }
     865             : 
     866             : 
     867             : void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
     868             :   IndentedScope indent(this, "EXPRESSION STATEMENT", node->position());
     869             :   Visit(node->expression());
     870             : }
     871             : 
     872             : 
     873             : void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
     874             :   IndentedScope indent(this, "EMPTY", node->position());
     875             : }
     876             : 
     877             : 
     878             : void AstPrinter::VisitSloppyBlockFunctionStatement(
     879             :     SloppyBlockFunctionStatement* node) {
     880             :   Visit(node->statement());
     881             : }
     882             : 
     883             : 
     884             : void AstPrinter::VisitIfStatement(IfStatement* node) {
     885             :   IndentedScope indent(this, "IF", node->position());
     886             :   PrintIndentedVisit("CONDITION", node->condition());
     887             :   PrintIndentedVisit("THEN", node->then_statement());
     888             :   if (node->HasElseStatement()) {
     889             :     PrintIndentedVisit("ELSE", node->else_statement());
     890             :   }
     891             : }
     892             : 
     893             : 
     894             : void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
     895             :   IndentedScope indent(this, "CONTINUE", node->position());
     896             :   PrintLabelsIndented(node->target()->labels());
     897             : }
     898             : 
     899             : 
     900             : void AstPrinter::VisitBreakStatement(BreakStatement* node) {
     901             :   IndentedScope indent(this, "BREAK", node->position());
     902             :   PrintLabelsIndented(node->target()->labels());
     903             : }
     904             : 
     905             : 
     906             : void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
     907             :   IndentedScope indent(this, "RETURN", node->position());
     908             :   Visit(node->expression());
     909             : }
     910             : 
     911             : 
     912             : void AstPrinter::VisitWithStatement(WithStatement* node) {
     913             :   IndentedScope indent(this, "WITH", node->position());
     914             :   PrintIndentedVisit("OBJECT", node->expression());
     915             :   PrintIndentedVisit("BODY", node->statement());
     916             : }
     917             : 
     918             : 
     919             : void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
     920             :   IndentedScope indent(this, "SWITCH", node->position());
     921             :   PrintLabelsIndented(node->labels());
     922             :   PrintIndentedVisit("TAG", node->tag());
     923             :   for (CaseClause* clause : *node->cases()) {
     924             :     if (clause->is_default()) {
     925             :       IndentedScope indent(this, "DEFAULT");
     926             :       PrintStatements(clause->statements());
     927             :     } else {
     928             :       IndentedScope indent(this, "CASE");
     929             :       Visit(clause->label());
     930             :       PrintStatements(clause->statements());
     931             :     }
     932             :   }
     933             : }
     934             : 
     935             : 
     936             : void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
     937             :   IndentedScope indent(this, "DO", node->position());
     938             :   PrintLabelsIndented(node->labels());
     939             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     940             :   PrintIndentedVisit("BODY", node->body());
     941             :   PrintIndentedVisit("COND", node->cond());
     942             : }
     943             : 
     944             : 
     945             : void AstPrinter::VisitWhileStatement(WhileStatement* node) {
     946             :   IndentedScope indent(this, "WHILE", node->position());
     947             :   PrintLabelsIndented(node->labels());
     948             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     949             :   PrintIndentedVisit("COND", node->cond());
     950             :   PrintIndentedVisit("BODY", node->body());
     951             : }
     952             : 
     953             : 
     954             : void AstPrinter::VisitForStatement(ForStatement* node) {
     955             :   IndentedScope indent(this, "FOR", node->position());
     956             :   PrintLabelsIndented(node->labels());
     957             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     958             :   if (node->init()) PrintIndentedVisit("INIT", node->init());
     959             :   if (node->cond()) PrintIndentedVisit("COND", node->cond());
     960             :   PrintIndentedVisit("BODY", node->body());
     961             :   if (node->next()) PrintIndentedVisit("NEXT", node->next());
     962             : }
     963             : 
     964             : 
     965             : void AstPrinter::VisitForInStatement(ForInStatement* node) {
     966             :   IndentedScope indent(this, "FOR IN", node->position());
     967             :   PrintLabelsIndented(node->labels());
     968             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     969             :   PrintIndentedVisit("FOR", node->each());
     970             :   PrintIndentedVisit("IN", node->subject());
     971             :   PrintIndentedVisit("BODY", node->body());
     972             : }
     973             : 
     974             : 
     975             : void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
     976             :   IndentedScope indent(this, "FOR OF", node->position());
     977             :   PrintLabelsIndented(node->labels());
     978             :   PrintLabelsIndented(node->own_labels(), "OWN ");
     979             :   const char* for_type;
     980             :   switch (node->type()) {
     981             :     case IteratorType::kNormal:
     982             :       for_type = "FOR";
     983             :       break;
     984             :     case IteratorType::kAsync:
     985             :       for_type = "FOR AWAIT";
     986             :       break;
     987             :   }
     988             :   PrintIndentedVisit(for_type, node->each());
     989             :   PrintIndentedVisit("OF", node->subject());
     990             :   PrintIndentedVisit("BODY", node->body());
     991             : }
     992             : 
     993             : 
     994             : void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
     995             :   IndentedScope indent(this, "TRY CATCH", node->position());
     996             :   PrintIndentedVisit("TRY", node->try_block());
     997             :   PrintIndented("CATCH PREDICTION");
     998             :   const char* prediction = "";
     999             :   switch (node->GetCatchPrediction(HandlerTable::UNCAUGHT)) {
    1000             :     case HandlerTable::UNCAUGHT:
    1001             :       prediction = "UNCAUGHT";
    1002             :       break;
    1003             :     case HandlerTable::CAUGHT:
    1004             :       prediction = "CAUGHT";
    1005             :       break;
    1006             :     case HandlerTable::DESUGARING:
    1007             :       prediction = "DESUGARING";
    1008             :       break;
    1009             :     case HandlerTable::ASYNC_AWAIT:
    1010             :       prediction = "ASYNC_AWAIT";
    1011             :       break;
    1012             :     case HandlerTable::PROMISE:
    1013             :       // Catch prediction resulting in promise rejections aren't
    1014             :       // parsed by the parser.
    1015             :       UNREACHABLE();
    1016             :   }
    1017             :   Print(" %s\n", prediction);
    1018             :   if (node->scope()) {
    1019             :     PrintLiteralWithModeIndented("CATCHVAR", node->scope()->catch_variable(),
    1020             :                                  node->scope()->catch_variable()->raw_name());
    1021             :   }
    1022             :   PrintIndentedVisit("CATCH", node->catch_block());
    1023             : }
    1024             : 
    1025             : void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
    1026             :   IndentedScope indent(this, "TRY FINALLY", node->position());
    1027             :   PrintIndentedVisit("TRY", node->try_block());
    1028             :   PrintIndentedVisit("FINALLY", node->finally_block());
    1029             : }
    1030             : 
    1031             : void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
    1032             :   IndentedScope indent(this, "DEBUGGER", node->position());
    1033             : }
    1034             : 
    1035             : 
    1036             : void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
    1037             :   IndentedScope indent(this, "FUNC LITERAL", node->position());
    1038             :   PrintIndented("LITERAL ID");
    1039             :   Print(" %d\n", node->function_literal_id());
    1040             :   PrintLiteralIndented("NAME", node->raw_name(), false);
    1041             :   PrintLiteralIndented("INFERRED NAME", node->raw_inferred_name(), false);
    1042             :   // We don't want to see the function literal in this case: it
    1043             :   // will be printed via PrintProgram when the code for it is
    1044             :   // generated.
    1045             :   // PrintParameters(node->scope());
    1046             :   // PrintStatements(node->body());
    1047             : }
    1048             : 
    1049             : 
    1050             : void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
    1051             :   IndentedScope indent(this, "CLASS LITERAL", node->position());
    1052             :   PrintLiteralIndented("NAME", node->constructor()->raw_name(), false);
    1053             :   if (node->extends() != nullptr) {
    1054             :     PrintIndentedVisit("EXTENDS", node->extends());
    1055             :   }
    1056             :   if (node->static_fields_initializer() != nullptr) {
    1057             :     PrintIndentedVisit("STATIC FIELDS INITIALIZER",
    1058             :                        node->static_fields_initializer());
    1059             :   }
    1060             :   if (node->instance_members_initializer_function() != nullptr) {
    1061             :     PrintIndentedVisit("INSTANCE ELEMENTS INITIALIZER",
    1062             :                        node->instance_members_initializer_function());
    1063             :   }
    1064             :   PrintClassProperties(node->properties());
    1065             : }
    1066             : 
    1067             : void AstPrinter::VisitInitializeClassMembersStatement(
    1068             :     InitializeClassMembersStatement* node) {
    1069             :   IndentedScope indent(this, "INITIALIZE CLASS ELEMENTS", node->position());
    1070             :   PrintClassProperties(node->fields());
    1071             : }
    1072             : 
    1073             : void AstPrinter::PrintClassProperties(
    1074             :     const ZonePtrList<ClassLiteral::Property>* properties) {
    1075             :   for (int i = 0; i < properties->length(); i++) {
    1076             :     ClassLiteral::Property* property = properties->at(i);
    1077             :     const char* prop_kind = nullptr;
    1078             :     switch (property->kind()) {
    1079             :       case ClassLiteral::Property::METHOD:
    1080             :         prop_kind = "METHOD";
    1081             :         break;
    1082             :       case ClassLiteral::Property::GETTER:
    1083             :         prop_kind = "GETTER";
    1084             :         break;
    1085             :       case ClassLiteral::Property::SETTER:
    1086             :         prop_kind = "SETTER";
    1087             :         break;
    1088             :       case ClassLiteral::Property::FIELD:
    1089             :         prop_kind = "FIELD";
    1090             :         break;
    1091             :     }
    1092             :     EmbeddedVector<char, 128> buf;
    1093             :     SNPrintF(buf, "PROPERTY%s%s - %s", property->is_static() ? " - STATIC" : "",
    1094             :              property->is_private() ? " - PRIVATE" : " - PUBLIC", prop_kind);
    1095             :     IndentedScope prop(this, buf.start());
    1096             :     PrintIndentedVisit("KEY", properties->at(i)->key());
    1097             :     PrintIndentedVisit("VALUE", properties->at(i)->value());
    1098             :   }
    1099             : }
    1100             : 
    1101             : 
    1102             : void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
    1103             :   IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position());
    1104             :   PrintLiteralIndented("NAME", node->raw_name(), false);
    1105             : }
    1106             : 
    1107             : 
    1108             : void AstPrinter::VisitDoExpression(DoExpression* node) {
    1109             :   IndentedScope indent(this, "DO EXPRESSION", node->position());
    1110             :   PrintStatements(node->block()->statements());
    1111             : }
    1112             : 
    1113             : 
    1114             : void AstPrinter::VisitConditional(Conditional* node) {
    1115             :   IndentedScope indent(this, "CONDITIONAL", node->position());
    1116             :   PrintIndentedVisit("CONDITION", node->condition());
    1117             :   PrintIndentedVisit("THEN", node->then_expression());
    1118             :   PrintIndentedVisit("ELSE", node->else_expression());
    1119             : }
    1120             : 
    1121             : 
    1122             : void AstPrinter::VisitLiteral(Literal* node) {
    1123             :   PrintLiteralIndented("LITERAL", node, true);
    1124             : }
    1125             : 
    1126             : 
    1127             : void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
    1128             :   IndentedScope indent(this, "REGEXP LITERAL", node->position());
    1129             :   PrintLiteralIndented("PATTERN", node->raw_pattern(), false);
    1130             :   int i = 0;
    1131             :   EmbeddedVector<char, 128> buf;
    1132             :   if (node->flags() & RegExp::kGlobal) buf[i++] = 'g';
    1133             :   if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i';
    1134             :   if (node->flags() & RegExp::kMultiline) buf[i++] = 'm';
    1135             :   if (node->flags() & RegExp::kUnicode) buf[i++] = 'u';
    1136             :   if (node->flags() & RegExp::kSticky) buf[i++] = 'y';
    1137             :   buf[i] = '\0';
    1138             :   PrintIndented("FLAGS ");
    1139             :   Print("%s", buf.start());
    1140             :   Print("\n");
    1141             : }
    1142             : 
    1143             : 
    1144             : void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
    1145             :   IndentedScope indent(this, "OBJ LITERAL", node->position());
    1146             :   PrintObjectProperties(node->properties());
    1147             : }
    1148             : 
    1149             : void AstPrinter::PrintObjectProperties(
    1150             :     const ZonePtrList<ObjectLiteral::Property>* properties) {
    1151             :   for (int i = 0; i < properties->length(); i++) {
    1152             :     ObjectLiteral::Property* property = properties->at(i);
    1153             :     const char* prop_kind = nullptr;
    1154             :     switch (property->kind()) {
    1155             :       case ObjectLiteral::Property::CONSTANT:
    1156             :         prop_kind = "CONSTANT";
    1157             :         break;
    1158             :       case ObjectLiteral::Property::COMPUTED:
    1159             :         prop_kind = "COMPUTED";
    1160             :         break;
    1161             :       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
    1162             :         prop_kind = "MATERIALIZED_LITERAL";
    1163             :         break;
    1164             :       case ObjectLiteral::Property::PROTOTYPE:
    1165             :         prop_kind = "PROTOTYPE";
    1166             :         break;
    1167             :       case ObjectLiteral::Property::GETTER:
    1168             :         prop_kind = "GETTER";
    1169             :         break;
    1170             :       case ObjectLiteral::Property::SETTER:
    1171             :         prop_kind = "SETTER";
    1172             :         break;
    1173             :       case ObjectLiteral::Property::SPREAD:
    1174             :         prop_kind = "SPREAD";
    1175             :         break;
    1176             :     }
    1177             :     EmbeddedVector<char, 128> buf;
    1178             :     SNPrintF(buf, "PROPERTY - %s", prop_kind);
    1179             :     IndentedScope prop(this, buf.start());
    1180             :     PrintIndentedVisit("KEY", properties->at(i)->key());
    1181             :     PrintIndentedVisit("VALUE", properties->at(i)->value());
    1182             :   }
    1183             : }
    1184             : 
    1185             : 
    1186             : void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
    1187             :   IndentedScope indent(this, "ARRAY LITERAL", node->position());
    1188             :   if (node->values()->length() > 0) {
    1189             :     IndentedScope indent(this, "VALUES", node->position());
    1190             :     for (int i = 0; i < node->values()->length(); i++) {
    1191             :       Visit(node->values()->at(i));
    1192             :     }
    1193             :   }
    1194             : }
    1195             : 
    1196             : 
    1197             : void AstPrinter::VisitVariableProxy(VariableProxy* node) {
    1198             :   EmbeddedVector<char, 128> buf;
    1199             :   int pos = SNPrintF(buf, "VAR PROXY");
    1200             : 
    1201             :   if (!node->is_resolved()) {
    1202             :     SNPrintF(buf + pos, " unresolved");
    1203             :     PrintLiteralWithModeIndented(buf.start(), nullptr, node->raw_name());
    1204             :   } else {
    1205             :     Variable* var = node->var();
    1206             :     switch (var->location()) {
    1207             :       case VariableLocation::UNALLOCATED:
    1208             :         SNPrintF(buf + pos, " unallocated");
    1209             :         break;
    1210             :       case VariableLocation::PARAMETER:
    1211             :         SNPrintF(buf + pos, " parameter[%d]", var->index());
    1212             :         break;
    1213             :       case VariableLocation::LOCAL:
    1214             :         SNPrintF(buf + pos, " local[%d]", var->index());
    1215             :         break;
    1216             :       case VariableLocation::CONTEXT:
    1217             :         SNPrintF(buf + pos, " context[%d]", var->index());
    1218             :         break;
    1219             :       case VariableLocation::LOOKUP:
    1220             :         SNPrintF(buf + pos, " lookup");
    1221             :         break;
    1222             :       case VariableLocation::MODULE:
    1223             :         SNPrintF(buf + pos, " module");
    1224             :         break;
    1225             :     }
    1226             :     PrintLiteralWithModeIndented(buf.start(), var, node->raw_name());
    1227             :   }
    1228             : }
    1229             : 
    1230             : 
    1231             : void AstPrinter::VisitAssignment(Assignment* node) {
    1232             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1233             :   Visit(node->target());
    1234             :   Visit(node->value());
    1235             : }
    1236             : 
    1237             : void AstPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
    1238             :   VisitAssignment(node);
    1239             : }
    1240             : 
    1241             : void AstPrinter::VisitYield(Yield* node) {
    1242             :   EmbeddedVector<char, 128> buf;
    1243             :   SNPrintF(buf, "YIELD");
    1244             :   IndentedScope indent(this, buf.start(), node->position());
    1245             :   Visit(node->expression());
    1246             : }
    1247             : 
    1248             : void AstPrinter::VisitYieldStar(YieldStar* node) {
    1249             :   EmbeddedVector<char, 128> buf;
    1250             :   SNPrintF(buf, "YIELD_STAR");
    1251             :   IndentedScope indent(this, buf.start(), node->position());
    1252             :   Visit(node->expression());
    1253             : }
    1254             : 
    1255             : void AstPrinter::VisitAwait(Await* node) {
    1256             :   EmbeddedVector<char, 128> buf;
    1257             :   SNPrintF(buf, "AWAIT");
    1258             :   IndentedScope indent(this, buf.start(), node->position());
    1259             :   Visit(node->expression());
    1260             : }
    1261             : 
    1262             : void AstPrinter::VisitThrow(Throw* node) {
    1263             :   IndentedScope indent(this, "THROW", node->position());
    1264             :   Visit(node->exception());
    1265             : }
    1266             : 
    1267             : void AstPrinter::VisitProperty(Property* node) {
    1268             :   EmbeddedVector<char, 128> buf;
    1269             :   SNPrintF(buf, "PROPERTY");
    1270             :   IndentedScope indent(this, buf.start(), node->position());
    1271             : 
    1272             :   Visit(node->obj());
    1273             :   AssignType property_kind = Property::GetAssignType(node);
    1274             :   if (property_kind == NAMED_PROPERTY ||
    1275             :       property_kind == NAMED_SUPER_PROPERTY) {
    1276             :     PrintLiteralIndented("NAME", node->key()->AsLiteral(), false);
    1277             :   } else {
    1278             :     DCHECK(property_kind == KEYED_PROPERTY ||
    1279             :            property_kind == KEYED_SUPER_PROPERTY);
    1280             :     PrintIndentedVisit("KEY", node->key());
    1281             :   }
    1282             : }
    1283             : 
    1284             : void AstPrinter::VisitResolvedProperty(ResolvedProperty* node) {
    1285             :   EmbeddedVector<char, 128> buf;
    1286             :   SNPrintF(buf, "RESOLVED-PROPERTY");
    1287             :   IndentedScope indent(this, buf.start(), node->position());
    1288             : 
    1289             :   PrintIndentedVisit("RECEIVER", node->object());
    1290             :   PrintIndentedVisit("PROPERTY", node->property());
    1291             : }
    1292             : 
    1293             : void AstPrinter::VisitCall(Call* node) {
    1294             :   EmbeddedVector<char, 128> buf;
    1295             :   SNPrintF(buf, "CALL");
    1296             :   IndentedScope indent(this, buf.start());
    1297             : 
    1298             :   Visit(node->expression());
    1299             :   PrintArguments(node->arguments());
    1300             : }
    1301             : 
    1302             : 
    1303             : void AstPrinter::VisitCallNew(CallNew* node) {
    1304             :   IndentedScope indent(this, "CALL NEW", node->position());
    1305             :   Visit(node->expression());
    1306             :   PrintArguments(node->arguments());
    1307             : }
    1308             : 
    1309             : 
    1310             : void AstPrinter::VisitCallRuntime(CallRuntime* node) {
    1311             :   EmbeddedVector<char, 128> buf;
    1312             :   SNPrintF(buf, "CALL RUNTIME %s%s", node->debug_name(),
    1313             :            node->is_jsruntime() ? " (JS function)" : "");
    1314             :   IndentedScope indent(this, buf.start(), node->position());
    1315             :   PrintArguments(node->arguments());
    1316             : }
    1317             : 
    1318             : 
    1319             : void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
    1320             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1321             :   Visit(node->expression());
    1322             : }
    1323             : 
    1324             : 
    1325             : void AstPrinter::VisitCountOperation(CountOperation* node) {
    1326             :   EmbeddedVector<char, 128> buf;
    1327             :   SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
    1328             :            Token::Name(node->op()));
    1329             :   IndentedScope indent(this, buf.start(), node->position());
    1330             :   Visit(node->expression());
    1331             : }
    1332             : 
    1333             : 
    1334             : void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
    1335             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1336             :   Visit(node->left());
    1337             :   Visit(node->right());
    1338             : }
    1339             : 
    1340             : void AstPrinter::VisitNaryOperation(NaryOperation* node) {
    1341             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1342             :   Visit(node->first());
    1343             :   for (size_t i = 0; i < node->subsequent_length(); ++i) {
    1344             :     Visit(node->subsequent(i));
    1345             :   }
    1346             : }
    1347             : 
    1348             : void AstPrinter::VisitCompareOperation(CompareOperation* node) {
    1349             :   IndentedScope indent(this, Token::Name(node->op()), node->position());
    1350             :   Visit(node->left());
    1351             :   Visit(node->right());
    1352             : }
    1353             : 
    1354             : 
    1355             : void AstPrinter::VisitSpread(Spread* node) {
    1356             :   IndentedScope indent(this, "SPREAD", node->position());
    1357             :   Visit(node->expression());
    1358             : }
    1359             : 
    1360             : void AstPrinter::VisitStoreInArrayLiteral(StoreInArrayLiteral* node) {
    1361             :   IndentedScope indent(this, "STORE IN ARRAY LITERAL", node->position());
    1362             :   PrintIndentedVisit("ARRAY", node->array());
    1363             :   PrintIndentedVisit("INDEX", node->index());
    1364             :   PrintIndentedVisit("VALUE", node->value());
    1365             : }
    1366             : 
    1367             : void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
    1368             :   IndentedScope indent(this, "()", node->position());
    1369             : }
    1370             : 
    1371             : void AstPrinter::VisitGetTemplateObject(GetTemplateObject* node) {
    1372             :   IndentedScope indent(this, "GET-TEMPLATE-OBJECT", node->position());
    1373             : }
    1374             : 
    1375             : void AstPrinter::VisitTemplateLiteral(TemplateLiteral* node) {
    1376             :   IndentedScope indent(this, "TEMPLATE-LITERAL", node->position());
    1377             :   const AstRawString* string = node->string_parts()->first();
    1378             :   if (!string->IsEmpty()) PrintLiteralIndented("SPAN", string, true);
    1379             :   for (int i = 0; i < node->substitutions()->length();) {
    1380             :     PrintIndentedVisit("EXPR", node->substitutions()->at(i++));
    1381             :     if (i < node->string_parts()->length()) {
    1382             :       string = node->string_parts()->at(i);
    1383             :       if (!string->IsEmpty()) PrintLiteralIndented("SPAN", string, true);
    1384             :     }
    1385             :   }
    1386             : }
    1387             : 
    1388             : void AstPrinter::VisitImportCallExpression(ImportCallExpression* node) {
    1389             :   IndentedScope indent(this, "IMPORT-CALL", node->position());
    1390             :   Visit(node->argument());
    1391             : }
    1392             : 
    1393             : void AstPrinter::VisitThisExpression(ThisExpression* node) {
    1394             :   IndentedScope indent(this, "THIS-EXPRESSION", node->position());
    1395             : }
    1396             : 
    1397             : void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
    1398             :   IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position());
    1399             : }
    1400             : 
    1401             : 
    1402             : void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
    1403             :   IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position());
    1404             : }
    1405             : 
    1406             : 
    1407             : #endif  // DEBUG
    1408             : 
    1409             : }  // namespace internal
    1410      178779 : }  // namespace v8

Generated by: LCOV version 1.10