v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
prettyprinter.cc
Go to the documentation of this file.
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  OS::SNPrintF(buf + pos, ")");
676  PrintLiteralIndented(buf.start(), value, true);
677  }
678 }
679 
680 
681 void 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 
694 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
695  IndentedScope indent(this, s, node);
696  Visit(node);
697 }
698 
699 
700 const 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 
713 void 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 
723 void 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 
734 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
735  for (int i = 0; i < statements->length(); i++) {
736  Visit(statements->at(i));
737  }
738 }
739 
740 
741 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
742  for (int i = 0; i < arguments->length(); i++) {
743  Visit(arguments->at(i));
744  }
745 }
746 
747 
748 void 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 
760 void 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 
767 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
768  PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
769  node->proxy()->var(),
770  node->proxy()->name());
771 }
772 
773 
774 void 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 
783 void AstPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
784  IndentedScope indent(this, "MODULE");
785  PrintLiteralIndented("NAME", node->proxy()->name(), true);
786  Visit(node->module());
787 }
788 
789 
790 void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
791  IndentedScope indent(this, "IMPORT");
792  PrintLiteralIndented("NAME", node->proxy()->name(), true);
793  Visit(node->module());
794 }
795 
796 
797 void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
798  IndentedScope indent(this, "EXPORT ");
799  PrintLiteral(node->proxy()->name(), true);
800 }
801 
802 
803 void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) {
804  VisitBlock(node->body());
805 }
806 
807 
808 void AstPrinter::VisitModuleVariable(ModuleVariable* node) {
809  Visit(node->proxy());
810 }
811 
812 
813 void AstPrinter::VisitModulePath(ModulePath* node) {
814  IndentedScope indent(this, "PATH");
815  PrintIndentedVisit("MODULE", node->module());
816  PrintLiteralIndented("NAME", node->name(), false);
817 }
818 
819 
820 void AstPrinter::VisitModuleUrl(ModuleUrl* node) {
821  PrintLiteralIndented("URL", node->url(), true);
822 }
823 
824 
825 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
826  Visit(node->expression());
827 }
828 
829 
830 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
831  PrintIndented("EMPTY\n");
832 }
833 
834 
835 void 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 
844 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
845  PrintLabelsIndented("CONTINUE", node->target()->labels());
846 }
847 
848 
849 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
850  PrintLabelsIndented("BREAK", node->target()->labels());
851 }
852 
853 
854 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
855  PrintIndentedVisit("RETURN", node->expression());
856 }
857 
858 
859 void AstPrinter::VisitWithStatement(WithStatement* node) {
860  IndentedScope indent(this, "WITH");
861  PrintIndentedVisit("OBJECT", node->expression());
862  PrintIndentedVisit("BODY", node->statement());
863 }
864 
865 
866 void 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 
876 void 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 
884 void 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 
892 void 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 
902 void 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 
910 void 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 
920 void 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 
927 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
928  IndentedScope indent(this, "DEBUGGER");
929 }
930 
931 
932 void 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 
944 void AstPrinter::VisitSharedFunctionInfoLiteral(
945  SharedFunctionInfoLiteral* node) {
946  IndentedScope indent(this, "FUNC LITERAL");
947  PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true);
948 }
949 
950 
951 void 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 
959 void AstPrinter::VisitLiteral(Literal* node) {
960  PrintLiteralIndented("LITERAL", node->handle(), true);
961 }
962 
963 
964 void 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 
971 void 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 
1004 void 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 
1015 void 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 
1039 void AstPrinter::VisitAssignment(Assignment* node) {
1040  IndentedScope indent(this, Token::Name(node->op()), node);
1041  Visit(node->target());
1042  Visit(node->value());
1043 }
1044 
1045 
1046 void AstPrinter::VisitThrow(Throw* node) {
1047  PrintIndentedVisit("THROW", node->exception());
1048 }
1049 
1050 
1051 void 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 
1063 void AstPrinter::VisitCall(Call* node) {
1064  IndentedScope indent(this, "CALL");
1065  Visit(node->expression());
1066  PrintArguments(node->arguments());
1067 }
1068 
1069 
1070 void AstPrinter::VisitCallNew(CallNew* node) {
1071  IndentedScope indent(this, "CALL NEW");
1072  Visit(node->expression());
1073  PrintArguments(node->arguments());
1074 }
1075 
1076 
1077 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1078  PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
1079  IndentedScope indent(this);
1080  PrintArguments(node->arguments());
1081 }
1082 
1083 
1084 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1085  PrintIndentedVisit(Token::Name(node->op()), node->expression());
1086 }
1087 
1088 
1089 void 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 
1097 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1098  IndentedScope indent(this, Token::Name(node->op()), node);
1099  Visit(node->left());
1100  Visit(node->right());
1101 }
1102 
1103 
1104 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1105  IndentedScope indent(this, Token::Name(node->op()), node);
1106  Visit(node->left());
1107  Visit(node->right());
1108 }
1109 
1110 
1111 void AstPrinter::VisitThisFunction(ThisFunction* node) {
1112  IndentedScope indent(this, "THIS-FUNCTION");
1113 }
1114 
1115 #endif // DEBUG
1116 
1117 } } // namespace v8::internal
void PrintF(const char *format,...)
Definition: v8utils.cc:40
static int VSNPrintF(Vector< char > str, const char *format, va_list args)
static String * cast(Object *obj)
#define ASSERT(condition)
Definition: checks.h:270
v8::Handle< v8::Value > Print(const v8::Arguments &args)
#define UNREACHABLE()
Definition: checks.h:50
static const char * String(Value tok)
Definition: token.h:275
#define BASE_EMBEDDED
Definition: allocation.h:68
static JSArray * cast(Object *obj)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
ZoneList< Handle< String > > ZoneStringList
Definition: ast.h:155
void DeleteArray(T *array)
Definition: allocation.h:91
#define VOID