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