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
36namespace v8 {
37namespace internal {
38
39#ifdef DEBUG
40
41PrettyPrinter::PrettyPrinter() {
42  output_ = NULL;
43  size_ = 0;
44  pos_ = 0;
45}
46
47
48PrettyPrinter::~PrettyPrinter() {
49  DeleteArray(output_);
50}
51
52
53void 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
61void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
62  Print("var ");
63  PrintLiteral(node->proxy()->name(), false);
64  Print(";");
65}
66
67
68void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
69  Print("function ");
70  PrintLiteral(node->proxy()->name(), false);
71  Print(" = ");
72  PrintFunctionLiteral(node->fun());
73  Print(";");
74}
75
76
77void PrettyPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
78  Print("module ");
79  PrintLiteral(node->proxy()->name(), false);
80  Print(" = ");
81  Visit(node->module());
82  Print(";");
83}
84
85
86void 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
95void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) {
96  Print("export ");
97  PrintLiteral(node->proxy()->name(), false);
98  Print(";");
99}
100
101
102void PrettyPrinter::VisitModuleLiteral(ModuleLiteral* node) {
103  VisitBlock(node->body());
104}
105
106
107void PrettyPrinter::VisitModuleVariable(ModuleVariable* node) {
108  Visit(node->proxy());
109}
110
111
112void PrettyPrinter::VisitModulePath(ModulePath* node) {
113  Visit(node->module());
114  Print(".");
115  PrintLiteral(node->name(), false);
116}
117
118
119void PrettyPrinter::VisitModuleUrl(ModuleUrl* node) {
120  Print("at ");
121  PrintLiteral(node->url(), true);
122}
123
124
125void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
126  Visit(node->expression());
127  Print(";");
128}
129
130
131void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
132  Print(";");
133}
134
135
136void 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
148void 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
160void 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
172void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
173  Print("return ");
174  Visit(node->expression());
175  Print(";");
176}
177
178
179void PrettyPrinter::VisitWithStatement(WithStatement* node) {
180  Print("with (");
181  Visit(node->expression());
182  Print(") ");
183  Visit(node->statement());
184}
185
186
187void 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
199void 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
209void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
210  PrintLabels(node->labels());
211  Print("while (");
212  Visit(node->cond());
213  Print(") ");
214  Visit(node->body());
215}
216
217
218void 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
238void 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
249void 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
260void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
261  Print("try ");
262  Visit(node->try_block());
263  Print(" finally ");
264  Visit(node->finally_block());
265}
266
267
268void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
269  Print("debugger ");
270}
271
272
273void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
274  Print("(");
275  PrintFunctionLiteral(node);
276  Print(")");
277}
278
279
280void PrettyPrinter::VisitSharedFunctionInfoLiteral(
281    SharedFunctionInfoLiteral* node) {
282  Print("(");
283  PrintLiteral(node->shared_function_info(), true);
284  Print(")");
285}
286
287
288void 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
297void PrettyPrinter::VisitLiteral(Literal* node) {
298  PrintLiteral(node->handle(), true);
299}
300
301
302void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
303  Print(" RegExp(");
304  PrintLiteral(node->pattern(), false);
305  Print(",");
306  PrintLiteral(node->flags(), false);
307  Print(") ");
308}
309
310
311void 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
325void 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
335void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
336  PrintLiteral(node->name(), false);
337}
338
339
340void PrettyPrinter::VisitAssignment(Assignment* node) {
341  Visit(node->target());
342  Print(" %s ", Token::String(node->op()));
343  Visit(node->value());
344}
345
346
347void PrettyPrinter::VisitThrow(Throw* node) {
348  Print("throw ");
349  Visit(node->exception());
350}
351
352
353void 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
370void PrettyPrinter::VisitCall(Call* node) {
371  Visit(node->expression());
372  PrintArguments(node->arguments());
373}
374
375
376void PrettyPrinter::VisitCallNew(CallNew* node) {
377  Print("new (");
378  Visit(node->expression());
379  Print(")");
380  PrintArguments(node->arguments());
381}
382
383
384void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
385  Print("%%");
386  PrintLiteral(node->name(), false);
387  PrintArguments(node->arguments());
388}
389
390
391void 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
401void 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
410void 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
419void 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
428void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
429  Print("<this-function>");
430}
431
432
433const char* PrettyPrinter::Print(AstNode* node) {
434  Init();
435  Visit(node);
436  return output_;
437}
438
439
440const 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
449const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
450  Init();
451  PrintStatements(program->body());
452  Print("\n");
453  return output_;
454}
455
456
457void PrettyPrinter::PrintOut(AstNode* node) {
458  PrettyPrinter printer;
459  PrintF("%s", printer.Print(node));
460}
461
462
463void 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
475void 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
502void 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
511void 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
521void 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
531void 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
569void 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
579void 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
587void 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
598void 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
614class IndentedScope BASE_EMBEDDED {
615 public:
616  explicit IndentedScope(AstPrinter* printer) : ast_printer_(printer) {
617    ast_printer_->inc_indent();
618  }
619
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
627  virtual ~IndentedScope() {
628    ast_printer_->dec_indent();
629  }
630
631 private:
632  AstPrinter* ast_printer_;
633};
634
635
636//-----------------------------------------------------------------------------
637
638
639AstPrinter::AstPrinter() : indent_(0) {
640}
641
642
643AstPrinter::~AstPrinter() {
644  ASSERT(indent_ == 0);
645}
646
647
648void AstPrinter::PrintIndented(const char* txt) {
649  for (int i = 0; i < indent_; i++) {
650    Print(". ");
651  }
652  Print(txt);
653}
654
655
656void 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
666void 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
681void 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
694void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
695  IndentedScope indent(this, s, node);
696  Visit(node);
697}
698
699
700const 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
713void 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
723void 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
734void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
735  for (int i = 0; i < statements->length(); i++) {
736    Visit(statements->at(i));
737  }
738}
739
740
741void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
742  for (int i = 0; i < arguments->length(); i++) {
743    Visit(arguments->at(i));
744  }
745}
746
747
748void 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
760void 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
767void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
768  PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
769                               node->proxy()->var(),
770                               node->proxy()->name());
771}
772
773
774void 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
783void AstPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
784  IndentedScope indent(this, "MODULE");
785  PrintLiteralIndented("NAME", node->proxy()->name(), true);
786  Visit(node->module());
787}
788
789
790void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
791  IndentedScope indent(this, "IMPORT");
792  PrintLiteralIndented("NAME", node->proxy()->name(), true);
793  Visit(node->module());
794}
795
796
797void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
798  IndentedScope indent(this, "EXPORT ");
799  PrintLiteral(node->proxy()->name(), true);
800}
801
802
803void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) {
804  VisitBlock(node->body());
805}
806
807
808void AstPrinter::VisitModuleVariable(ModuleVariable* node) {
809  Visit(node->proxy());
810}
811
812
813void AstPrinter::VisitModulePath(ModulePath* node) {
814  IndentedScope indent(this, "PATH");
815  PrintIndentedVisit("MODULE", node->module());
816  PrintLiteralIndented("NAME", node->name(), false);
817}
818
819
820void AstPrinter::VisitModuleUrl(ModuleUrl* node) {
821  PrintLiteralIndented("URL", node->url(), true);
822}
823
824
825void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
826  Visit(node->expression());
827}
828
829
830void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
831  PrintIndented("EMPTY\n");
832}
833
834
835void 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
844void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
845  PrintLabelsIndented("CONTINUE", node->target()->labels());
846}
847
848
849void AstPrinter::VisitBreakStatement(BreakStatement* node) {
850  PrintLabelsIndented("BREAK", node->target()->labels());
851}
852
853
854void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
855  PrintIndentedVisit("RETURN", node->expression());
856}
857
858
859void AstPrinter::VisitWithStatement(WithStatement* node) {
860  IndentedScope indent(this, "WITH");
861  PrintIndentedVisit("OBJECT", node->expression());
862  PrintIndentedVisit("BODY", node->statement());
863}
864
865
866void 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
876void 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
884void 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
892void 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
902void 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
910void 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
920void 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
927void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
928  IndentedScope indent(this, "DEBUGGER");
929}
930
931
932void 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
944void AstPrinter::VisitSharedFunctionInfoLiteral(
945    SharedFunctionInfoLiteral* node) {
946  IndentedScope indent(this, "FUNC LITERAL");
947  PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true);
948}
949
950
951void 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
959void AstPrinter::VisitLiteral(Literal* node) {
960  PrintLiteralIndented("LITERAL", node->handle(), true);
961}
962
963
964void 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
971void 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
1004void 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
1015void 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
1039void AstPrinter::VisitAssignment(Assignment* node) {
1040  IndentedScope indent(this, Token::Name(node->op()), node);
1041  Visit(node->target());
1042  Visit(node->value());
1043}
1044
1045
1046void AstPrinter::VisitThrow(Throw* node) {
1047  PrintIndentedVisit("THROW", node->exception());
1048}
1049
1050
1051void 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
1063void AstPrinter::VisitCall(Call* node) {
1064  IndentedScope indent(this, "CALL");
1065  Visit(node->expression());
1066  PrintArguments(node->arguments());
1067}
1068
1069
1070void AstPrinter::VisitCallNew(CallNew* node) {
1071  IndentedScope indent(this, "CALL NEW");
1072  Visit(node->expression());
1073  PrintArguments(node->arguments());
1074}
1075
1076
1077void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1078  PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
1079  IndentedScope indent(this);
1080  PrintArguments(node->arguments());
1081}
1082
1083
1084void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1085  PrintIndentedVisit(Token::Name(node->op()), node->expression());
1086}
1087
1088
1089void 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
1097void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1098  IndentedScope indent(this, Token::Name(node->op()), node);
1099  Visit(node->left());
1100  Visit(node->right());
1101}
1102
1103
1104void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1105  IndentedScope indent(this, Token::Name(node->op()), node);
1106  Visit(node->left());
1107  Visit(node->right());
1108}
1109
1110
1111void AstPrinter::VisitThisFunction(ThisFunction* node) {
1112  IndentedScope indent(this, "THIS-FUNCTION");
1113}
1114
1115#endif  // DEBUG
1116
1117} }  // namespace v8::internal
1118