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