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