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