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
14namespace v8 {
15namespace internal {
16
17#ifdef DEBUG
18
19PrettyPrinter::PrettyPrinter(Zone* zone) {
20  output_ = NULL;
21  size_ = 0;
22  pos_ = 0;
23  InitializeAstVisitor(zone);
24}
25
26
27PrettyPrinter::~PrettyPrinter() {
28  DeleteArray(output_);
29}
30
31
32void 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
40void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
41  Print("var ");
42  PrintLiteral(node->proxy()->name(), false);
43  Print(";");
44}
45
46
47void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
48  Print("function ");
49  PrintLiteral(node->proxy()->name(), false);
50  Print(" = ");
51  PrintFunctionLiteral(node->fun());
52  Print(";");
53}
54
55
56void PrettyPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
57  Print("module ");
58  PrintLiteral(node->proxy()->name(), false);
59  Print(" = ");
60  Visit(node->module());
61  Print(";");
62}
63
64
65void 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
74void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) {
75  Print("export ");
76  PrintLiteral(node->proxy()->name(), false);
77  Print(";");
78}
79
80
81void PrettyPrinter::VisitModuleLiteral(ModuleLiteral* node) {
82  VisitBlock(node->body());
83}
84
85
86void PrettyPrinter::VisitModuleVariable(ModuleVariable* node) {
87  Visit(node->proxy());
88}
89
90
91void PrettyPrinter::VisitModulePath(ModulePath* node) {
92  Visit(node->module());
93  Print(".");
94  PrintLiteral(node->name(), false);
95}
96
97
98void PrettyPrinter::VisitModuleUrl(ModuleUrl* node) {
99  Print("at ");
100  PrintLiteral(node->url(), true);
101}
102
103
104void PrettyPrinter::VisitModuleStatement(ModuleStatement* node) {
105  Print("module ");
106  PrintLiteral(node->proxy()->name(), false);
107  Print(" ");
108  Visit(node->body());
109}
110
111
112void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
113  Visit(node->expression());
114  Print(";");
115}
116
117
118void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
119  Print(";");
120}
121
122
123void 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
135void 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
147void 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
159void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
160  Print("return ");
161  Visit(node->expression());
162  Print(";");
163}
164
165
166void PrettyPrinter::VisitWithStatement(WithStatement* node) {
167  Print("with (");
168  Visit(node->expression());
169  Print(") ");
170  Visit(node->statement());
171}
172
173
174void 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
186void 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
200void 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
210void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
211  PrintLabels(node->labels());
212  Print("while (");
213  Visit(node->cond());
214  Print(") ");
215  Visit(node->body());
216}
217
218
219void 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
239void 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
250void 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
261void 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
272void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
273  Print("try ");
274  Visit(node->try_block());
275  Print(" finally ");
276  Visit(node->finally_block());
277}
278
279
280void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
281  Print("debugger ");
282}
283
284
285void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
286  Print("(");
287  PrintFunctionLiteral(node);
288  Print(")");
289}
290
291
292void 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
307void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
308  Print("(");
309  PrintLiteral(node->name(), false);
310  Print(")");
311}
312
313
314void 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
323void PrettyPrinter::VisitLiteral(Literal* node) {
324  PrintLiteral(node->value(), true);
325}
326
327
328void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
329  Print(" RegExp(");
330  PrintLiteral(node->pattern(), false);
331  Print(",");
332  PrintLiteral(node->flags(), false);
333  Print(") ");
334}
335
336
337void 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
347void 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
357void 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
367void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
368  PrintLiteral(node->name(), false);
369}
370
371
372void PrettyPrinter::VisitAssignment(Assignment* node) {
373  Visit(node->target());
374  Print(" %s ", Token::String(node->op()));
375  Visit(node->value());
376}
377
378
379void PrettyPrinter::VisitYield(Yield* node) {
380  Print("yield ");
381  Visit(node->expression());
382}
383
384
385void PrettyPrinter::VisitThrow(Throw* node) {
386  Print("throw ");
387  Visit(node->exception());
388}
389
390
391void 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
408void PrettyPrinter::VisitCall(Call* node) {
409  Visit(node->expression());
410  PrintArguments(node->arguments());
411}
412
413
414void PrettyPrinter::VisitCallNew(CallNew* node) {
415  Print("new (");
416  Visit(node->expression());
417  Print(")");
418  PrintArguments(node->arguments());
419}
420
421
422void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
423  Print("%%");
424  PrintLiteral(node->name(), false);
425  PrintArguments(node->arguments());
426}
427
428
429void 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
439void 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
448void 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
457void 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
466void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
467  Print("<this-function>");
468}
469
470
471void PrettyPrinter::VisitSuperReference(SuperReference* node) {
472  Print("<super-reference>");
473}
474
475
476const char* PrettyPrinter::Print(AstNode* node) {
477  Init();
478  Visit(node);
479  return output_;
480}
481
482
483const 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
492const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
493  Init();
494  PrintStatements(program->body());
495  Print("\n");
496  return output_;
497}
498
499
500void PrettyPrinter::PrintOut(Zone* zone, AstNode* node) {
501  PrettyPrinter printer(zone);
502  PrintF("%s", printer.Print(node));
503}
504
505
506void 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
518void 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
545void 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
554void 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
564void 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
574void 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
612void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) {
613  PrintLiteral(value->string(), quote);
614}
615
616
617void 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
627void 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
635void 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
648class IndentedScope BASE_EMBEDDED {
649 public:
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
657  virtual ~IndentedScope() {
658    ast_printer_->dec_indent();
659  }
660
661 private:
662  AstPrinter* ast_printer_;
663};
664
665
666//-----------------------------------------------------------------------------
667
668
669AstPrinter::AstPrinter(Zone* zone) : PrettyPrinter(zone), indent_(0) {
670}
671
672
673AstPrinter::~AstPrinter() {
674  DCHECK(indent_ == 0);
675}
676
677
678void AstPrinter::PrintIndented(const char* txt) {
679  for (int i = 0; i < indent_; i++) {
680    Print(". ");
681  }
682  Print(txt);
683}
684
685
686void 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
696void 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
711void 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
719void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
720  IndentedScope indent(this, s);
721  Visit(node);
722}
723
724
725const 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
738void 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
748void 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
759void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
760  for (int i = 0; i < statements->length(); i++) {
761    Visit(statements->at(i));
762  }
763}
764
765
766void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
767  for (int i = 0; i < arguments->length(); i++) {
768    Visit(arguments->at(i));
769  }
770}
771
772
773void 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.
781void 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.
789void 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
798void AstPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
799  IndentedScope indent(this, "MODULE");
800  PrintLiteralIndented("NAME", node->proxy()->name(), true);
801  Visit(node->module());
802}
803
804
805void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
806  IndentedScope indent(this, "IMPORT");
807  PrintLiteralIndented("NAME", node->proxy()->name(), true);
808  Visit(node->module());
809}
810
811
812void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
813  IndentedScope indent(this, "EXPORT ");
814  PrintLiteral(node->proxy()->name(), true);
815}
816
817
818void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) {
819  IndentedScope indent(this, "MODULE LITERAL");
820  VisitBlock(node->body());
821}
822
823
824void AstPrinter::VisitModuleVariable(ModuleVariable* node) {
825  IndentedScope indent(this, "MODULE VARIABLE");
826  Visit(node->proxy());
827}
828
829
830void 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
837void AstPrinter::VisitModuleUrl(ModuleUrl* node) {
838  PrintLiteralIndented("URL", node->url(), true);
839}
840
841
842void 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
849void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
850  IndentedScope indent(this, "EXPRESSION STATEMENT");
851  Visit(node->expression());
852}
853
854
855void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
856  IndentedScope indent(this, "EMPTY");
857}
858
859
860void 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
870void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
871  IndentedScope indent(this, "CONTINUE");
872  PrintLabelsIndented(node->target()->labels());
873}
874
875
876void AstPrinter::VisitBreakStatement(BreakStatement* node) {
877  IndentedScope indent(this, "BREAK");
878  PrintLabelsIndented(node->target()->labels());
879}
880
881
882void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
883  IndentedScope indent(this, "RETURN");
884  Visit(node->expression());
885}
886
887
888void AstPrinter::VisitWithStatement(WithStatement* node) {
889  IndentedScope indent(this, "WITH");
890  PrintIndentedVisit("OBJECT", node->expression());
891  PrintIndentedVisit("BODY", node->statement());
892}
893
894
895void 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
905void 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
917void 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
925void 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
933void 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
943void 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
951void 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
959void 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
969void 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
976void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
977  IndentedScope indent(this, "DEBUGGER");
978}
979
980
981void 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
993void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
994  IndentedScope indent(this, "CLASS LITERAL");
995  PrintLiteralIndented("NAME", node->name(), false);
996}
997
998
999void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
1000  IndentedScope indent(this, "NATIVE FUNC LITERAL");
1001  PrintLiteralIndented("NAME", node->name(), false);
1002}
1003
1004
1005void 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.
1014void AstPrinter::VisitLiteral(Literal* node) {
1015  PrintLiteralIndented("LITERAL", node->value(), true);
1016}
1017
1018
1019void 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
1026void 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
1059void 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.
1071void 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
1095void AstPrinter::VisitAssignment(Assignment* node) {
1096  IndentedScope indent(this, Token::Name(node->op()));
1097  Visit(node->target());
1098  Visit(node->value());
1099}
1100
1101
1102void AstPrinter::VisitYield(Yield* node) {
1103  IndentedScope indent(this, "YIELD");
1104  Visit(node->expression());
1105}
1106
1107
1108void AstPrinter::VisitThrow(Throw* node) {
1109  IndentedScope indent(this, "THROW");
1110  Visit(node->exception());
1111}
1112
1113
1114void 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
1126void AstPrinter::VisitCall(Call* node) {
1127  IndentedScope indent(this, "CALL");
1128  Visit(node->expression());
1129  PrintArguments(node->arguments());
1130}
1131
1132
1133void AstPrinter::VisitCallNew(CallNew* node) {
1134  IndentedScope indent(this, "CALL NEW");
1135  Visit(node->expression());
1136  PrintArguments(node->arguments());
1137}
1138
1139
1140void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1141  IndentedScope indent(this, "CALL RUNTIME");
1142  PrintLiteralIndented("NAME", node->name(), false);
1143  PrintArguments(node->arguments());
1144}
1145
1146
1147void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1148  IndentedScope indent(this, Token::Name(node->op()));
1149  Visit(node->expression());
1150}
1151
1152
1153void 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
1162void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1163  IndentedScope indent(this, Token::Name(node->op()));
1164  Visit(node->left());
1165  Visit(node->right());
1166}
1167
1168
1169void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1170  IndentedScope indent(this, Token::Name(node->op()));
1171  Visit(node->left());
1172  Visit(node->right());
1173}
1174
1175
1176void AstPrinter::VisitThisFunction(ThisFunction* node) {
1177  IndentedScope indent(this, "THIS-FUNCTION");
1178}
1179
1180
1181void AstPrinter::VisitSuperReference(SuperReference* node) {
1182  IndentedScope indent(this, "SUPER-REFERENCE");
1183}
1184
1185#endif  // DEBUG
1186
1187} }  // namespace v8::internal
1188