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