• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/ast/prettyprinter.h"
6 
7 #include <stdarg.h>
8 
9 #include "src/ast/ast-value-factory.h"
10 #include "src/ast/scopes.h"
11 #include "src/base/platform/platform.h"
12 
13 namespace v8 {
14 namespace internal {
15 
CallPrinter(Isolate * isolate,bool is_builtin)16 CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin) {
17   isolate_ = isolate;
18   output_ = NULL;
19   size_ = 0;
20   pos_ = 0;
21   position_ = 0;
22   found_ = false;
23   done_ = false;
24   is_builtin_ = is_builtin;
25   InitializeAstVisitor(isolate);
26 }
27 
28 
~CallPrinter()29 CallPrinter::~CallPrinter() { DeleteArray(output_); }
30 
31 
Print(FunctionLiteral * program,int position)32 const char* CallPrinter::Print(FunctionLiteral* program, int position) {
33   Init();
34   position_ = position;
35   Find(program);
36   return output_;
37 }
38 
39 
Find(AstNode * node,bool print)40 void CallPrinter::Find(AstNode* node, bool print) {
41   if (done_) return;
42   if (found_) {
43     if (print) {
44       int start = pos_;
45       Visit(node);
46       if (start != pos_) return;
47     }
48     Print("(intermediate value)");
49   } else {
50     Visit(node);
51   }
52 }
53 
54 
Init()55 void CallPrinter::Init() {
56   if (size_ == 0) {
57     DCHECK(output_ == NULL);
58     const int initial_size = 256;
59     output_ = NewArray<char>(initial_size);
60     size_ = initial_size;
61   }
62   output_[0] = '\0';
63   pos_ = 0;
64 }
65 
66 
Print(const char * format,...)67 void CallPrinter::Print(const char* format, ...) {
68   if (!found_ || done_) return;
69   for (;;) {
70     va_list arguments;
71     va_start(arguments, format);
72     int n = VSNPrintF(Vector<char>(output_, size_) + pos_, format, arguments);
73     va_end(arguments);
74 
75     if (n >= 0) {
76       // there was enough space - we are done
77       pos_ += n;
78       return;
79     } else {
80       // there was not enough space - allocate more and try again
81       const int slack = 32;
82       int new_size = size_ + (size_ >> 1) + slack;
83       char* new_output = NewArray<char>(new_size);
84       MemCopy(new_output, output_, pos_);
85       DeleteArray(output_);
86       output_ = new_output;
87       size_ = new_size;
88     }
89   }
90 }
91 
92 
VisitBlock(Block * node)93 void CallPrinter::VisitBlock(Block* node) {
94   FindStatements(node->statements());
95 }
96 
97 
VisitVariableDeclaration(VariableDeclaration * node)98 void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {}
99 
100 
VisitFunctionDeclaration(FunctionDeclaration * node)101 void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {}
102 
103 
VisitImportDeclaration(ImportDeclaration * node)104 void CallPrinter::VisitImportDeclaration(ImportDeclaration* node) {
105 }
106 
107 
VisitExportDeclaration(ExportDeclaration * node)108 void CallPrinter::VisitExportDeclaration(ExportDeclaration* node) {}
109 
110 
VisitExpressionStatement(ExpressionStatement * node)111 void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) {
112   Find(node->expression());
113 }
114 
115 
VisitEmptyStatement(EmptyStatement * node)116 void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {}
117 
118 
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * node)119 void CallPrinter::VisitSloppyBlockFunctionStatement(
120     SloppyBlockFunctionStatement* node) {
121   Find(node->statement());
122 }
123 
124 
VisitIfStatement(IfStatement * node)125 void CallPrinter::VisitIfStatement(IfStatement* node) {
126   Find(node->condition());
127   Find(node->then_statement());
128   if (node->HasElseStatement()) {
129     Find(node->else_statement());
130   }
131 }
132 
133 
VisitContinueStatement(ContinueStatement * node)134 void CallPrinter::VisitContinueStatement(ContinueStatement* node) {}
135 
136 
VisitBreakStatement(BreakStatement * node)137 void CallPrinter::VisitBreakStatement(BreakStatement* node) {}
138 
139 
VisitReturnStatement(ReturnStatement * node)140 void CallPrinter::VisitReturnStatement(ReturnStatement* node) {
141   Find(node->expression());
142 }
143 
144 
VisitWithStatement(WithStatement * node)145 void CallPrinter::VisitWithStatement(WithStatement* node) {
146   Find(node->expression());
147   Find(node->statement());
148 }
149 
150 
VisitSwitchStatement(SwitchStatement * node)151 void CallPrinter::VisitSwitchStatement(SwitchStatement* node) {
152   Find(node->tag());
153   ZoneList<CaseClause*>* cases = node->cases();
154   for (int i = 0; i < cases->length(); i++) Find(cases->at(i));
155 }
156 
157 
VisitCaseClause(CaseClause * clause)158 void CallPrinter::VisitCaseClause(CaseClause* clause) {
159   if (!clause->is_default()) {
160     Find(clause->label());
161   }
162   FindStatements(clause->statements());
163 }
164 
165 
VisitDoWhileStatement(DoWhileStatement * node)166 void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
167   Find(node->body());
168   Find(node->cond());
169 }
170 
171 
VisitWhileStatement(WhileStatement * node)172 void CallPrinter::VisitWhileStatement(WhileStatement* node) {
173   Find(node->cond());
174   Find(node->body());
175 }
176 
177 
VisitForStatement(ForStatement * node)178 void CallPrinter::VisitForStatement(ForStatement* node) {
179   if (node->init() != NULL) {
180     Find(node->init());
181   }
182   if (node->cond() != NULL) Find(node->cond());
183   if (node->next() != NULL) Find(node->next());
184   Find(node->body());
185 }
186 
187 
VisitForInStatement(ForInStatement * node)188 void CallPrinter::VisitForInStatement(ForInStatement* node) {
189   Find(node->each());
190   Find(node->enumerable());
191   Find(node->body());
192 }
193 
194 
VisitForOfStatement(ForOfStatement * node)195 void CallPrinter::VisitForOfStatement(ForOfStatement* node) {
196   Find(node->assign_iterator());
197   Find(node->next_result());
198   Find(node->result_done());
199   Find(node->assign_each());
200   Find(node->body());
201 }
202 
203 
VisitTryCatchStatement(TryCatchStatement * node)204 void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
205   Find(node->try_block());
206   Find(node->catch_block());
207 }
208 
209 
VisitTryFinallyStatement(TryFinallyStatement * node)210 void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
211   Find(node->try_block());
212   Find(node->finally_block());
213 }
214 
215 
VisitDebuggerStatement(DebuggerStatement * node)216 void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {}
217 
218 
VisitFunctionLiteral(FunctionLiteral * node)219 void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
220   FindStatements(node->body());
221 }
222 
223 
VisitClassLiteral(ClassLiteral * node)224 void CallPrinter::VisitClassLiteral(ClassLiteral* node) {
225   if (node->extends()) Find(node->extends());
226   for (int i = 0; i < node->properties()->length(); i++) {
227     Find(node->properties()->at(i)->value());
228   }
229 }
230 
231 
VisitNativeFunctionLiteral(NativeFunctionLiteral * node)232 void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
233 
234 
VisitDoExpression(DoExpression * node)235 void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); }
236 
237 
VisitConditional(Conditional * node)238 void CallPrinter::VisitConditional(Conditional* node) {
239   Find(node->condition());
240   Find(node->then_expression());
241   Find(node->else_expression());
242 }
243 
244 
VisitLiteral(Literal * node)245 void CallPrinter::VisitLiteral(Literal* node) {
246   PrintLiteral(*node->value(), true);
247 }
248 
249 
VisitRegExpLiteral(RegExpLiteral * node)250 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
251   Print("/");
252   PrintLiteral(*node->pattern(), false);
253   Print("/");
254   if (node->flags() & RegExp::kGlobal) Print("g");
255   if (node->flags() & RegExp::kIgnoreCase) Print("i");
256   if (node->flags() & RegExp::kMultiline) Print("m");
257   if (node->flags() & RegExp::kUnicode) Print("u");
258   if (node->flags() & RegExp::kSticky) Print("y");
259 }
260 
261 
VisitObjectLiteral(ObjectLiteral * node)262 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) {
263   for (int i = 0; i < node->properties()->length(); i++) {
264     Find(node->properties()->at(i)->value());
265   }
266 }
267 
268 
VisitArrayLiteral(ArrayLiteral * node)269 void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) {
270   Print("[");
271   for (int i = 0; i < node->values()->length(); i++) {
272     if (i != 0) Print(",");
273     Find(node->values()->at(i), true);
274   }
275   Print("]");
276 }
277 
278 
VisitVariableProxy(VariableProxy * node)279 void CallPrinter::VisitVariableProxy(VariableProxy* node) {
280   if (is_builtin_) {
281     // Variable names of builtins are meaningless due to minification.
282     Print("(var)");
283   } else {
284     PrintLiteral(*node->name(), false);
285   }
286 }
287 
288 
VisitAssignment(Assignment * node)289 void CallPrinter::VisitAssignment(Assignment* node) {
290   Find(node->target());
291   Find(node->value());
292 }
293 
294 
VisitYield(Yield * node)295 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
296 
297 
VisitThrow(Throw * node)298 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); }
299 
300 
VisitProperty(Property * node)301 void CallPrinter::VisitProperty(Property* node) {
302   Expression* key = node->key();
303   Literal* literal = key->AsLiteral();
304   if (literal != NULL && literal->value()->IsInternalizedString()) {
305     Find(node->obj(), true);
306     Print(".");
307     PrintLiteral(*literal->value(), false);
308   } else {
309     Find(node->obj(), true);
310     Print("[");
311     Find(key, true);
312     Print("]");
313   }
314 }
315 
316 
VisitCall(Call * node)317 void CallPrinter::VisitCall(Call* node) {
318   bool was_found = !found_ && node->position() == position_;
319   if (was_found) {
320     // Bail out if the error is caused by a direct call to a variable in builtin
321     // code. The variable name is meaningless due to minification.
322     if (is_builtin_ && node->expression()->IsVariableProxy()) {
323       done_ = true;
324       return;
325     }
326     found_ = true;
327   }
328   Find(node->expression(), true);
329   if (!was_found) Print("(...)");
330   FindArguments(node->arguments());
331   if (was_found) done_ = true;
332 }
333 
334 
VisitCallNew(CallNew * node)335 void CallPrinter::VisitCallNew(CallNew* node) {
336   bool was_found = !found_ && node->position() == position_;
337   if (was_found) {
338     // Bail out if the error is caused by a direct call to a variable in builtin
339     // code. The variable name is meaningless due to minification.
340     if (is_builtin_ && node->expression()->IsVariableProxy()) {
341       done_ = true;
342       return;
343     }
344     found_ = true;
345   }
346   Find(node->expression(), was_found);
347   FindArguments(node->arguments());
348   if (was_found) done_ = true;
349 }
350 
351 
VisitCallRuntime(CallRuntime * node)352 void CallPrinter::VisitCallRuntime(CallRuntime* node) {
353   FindArguments(node->arguments());
354 }
355 
356 
VisitUnaryOperation(UnaryOperation * node)357 void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
358   Token::Value op = node->op();
359   bool needsSpace =
360       op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
361   Print("(%s%s", Token::String(op), needsSpace ? " " : "");
362   Find(node->expression(), true);
363   Print(")");
364 }
365 
366 
VisitCountOperation(CountOperation * node)367 void CallPrinter::VisitCountOperation(CountOperation* node) {
368   Print("(");
369   if (node->is_prefix()) Print("%s", Token::String(node->op()));
370   Find(node->expression(), true);
371   if (node->is_postfix()) Print("%s", Token::String(node->op()));
372   Print(")");
373 }
374 
375 
VisitBinaryOperation(BinaryOperation * node)376 void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
377   Print("(");
378   Find(node->left(), true);
379   Print(" %s ", Token::String(node->op()));
380   Find(node->right(), true);
381   Print(")");
382 }
383 
384 
VisitCompareOperation(CompareOperation * node)385 void CallPrinter::VisitCompareOperation(CompareOperation* node) {
386   Print("(");
387   Find(node->left(), true);
388   Print(" %s ", Token::String(node->op()));
389   Find(node->right(), true);
390   Print(")");
391 }
392 
393 
VisitSpread(Spread * node)394 void CallPrinter::VisitSpread(Spread* node) {
395   Print("(...");
396   Find(node->expression(), true);
397   Print(")");
398 }
399 
400 
VisitEmptyParentheses(EmptyParentheses * node)401 void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
402   UNREACHABLE();
403 }
404 
405 
VisitThisFunction(ThisFunction * node)406 void CallPrinter::VisitThisFunction(ThisFunction* node) {}
407 
408 
VisitSuperPropertyReference(SuperPropertyReference * node)409 void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
410 
411 
VisitSuperCallReference(SuperCallReference * node)412 void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
413   Print("super");
414 }
415 
416 
VisitRewritableExpression(RewritableExpression * node)417 void CallPrinter::VisitRewritableExpression(RewritableExpression* node) {
418   Find(node->expression());
419 }
420 
421 
FindStatements(ZoneList<Statement * > * statements)422 void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {
423   if (statements == NULL) return;
424   for (int i = 0; i < statements->length(); i++) {
425     Find(statements->at(i));
426   }
427 }
428 
429 
FindArguments(ZoneList<Expression * > * arguments)430 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) {
431   if (found_) return;
432   for (int i = 0; i < arguments->length(); i++) {
433     Find(arguments->at(i));
434   }
435 }
436 
437 
PrintLiteral(Object * value,bool quote)438 void CallPrinter::PrintLiteral(Object* value, bool quote) {
439   Object* object = value;
440   if (object->IsString()) {
441     if (quote) Print("\"");
442     Print("%s", String::cast(object)->ToCString().get());
443     if (quote) Print("\"");
444   } else if (object->IsNull(isolate_)) {
445     Print("null");
446   } else if (object->IsTrue(isolate_)) {
447     Print("true");
448   } else if (object->IsFalse(isolate_)) {
449     Print("false");
450   } else if (object->IsUndefined(isolate_)) {
451     Print("undefined");
452   } else if (object->IsNumber()) {
453     Print("%g", object->Number());
454   } else if (object->IsSymbol()) {
455     // Symbols can only occur as literals if they were inserted by the parser.
456     PrintLiteral(Symbol::cast(object)->name(), false);
457   }
458 }
459 
460 
PrintLiteral(const AstRawString * value,bool quote)461 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
462   PrintLiteral(*value->string(), quote);
463 }
464 
465 
466 //-----------------------------------------------------------------------------
467 
468 
469 #ifdef DEBUG
470 
471 // A helper for ast nodes that use FeedbackVectorSlots.
FormatSlotNode(Vector<char> * buf,Expression * node,const char * node_name,FeedbackVectorSlot slot)472 static int FormatSlotNode(Vector<char>* buf, Expression* node,
473                           const char* node_name, FeedbackVectorSlot slot) {
474   int pos = SNPrintF(*buf, "%s", node_name);
475   if (!slot.IsInvalid()) {
476     pos += SNPrintF(*buf + pos, " Slot(%d)", slot.ToInt());
477   }
478   return pos;
479 }
480 
481 
PrettyPrinter(Isolate * isolate)482 PrettyPrinter::PrettyPrinter(Isolate* isolate) {
483   isolate_ = isolate;
484   output_ = NULL;
485   size_ = 0;
486   pos_ = 0;
487   InitializeAstVisitor(isolate);
488 }
489 
490 
~PrettyPrinter()491 PrettyPrinter::~PrettyPrinter() {
492   DeleteArray(output_);
493 }
494 
495 
VisitBlock(Block * node)496 void PrettyPrinter::VisitBlock(Block* node) {
497   if (!node->ignore_completion_value()) Print("{ ");
498   PrintStatements(node->statements());
499   if (node->statements()->length() > 0) Print(" ");
500   if (!node->ignore_completion_value()) Print("}");
501 }
502 
503 
VisitVariableDeclaration(VariableDeclaration * node)504 void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
505   Print("var ");
506   PrintLiteral(node->proxy()->name(), false);
507   Print(";");
508 }
509 
510 
VisitFunctionDeclaration(FunctionDeclaration * node)511 void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
512   Print("function ");
513   PrintLiteral(node->proxy()->name(), false);
514   Print(" = ");
515   PrintFunctionLiteral(node->fun());
516   Print(";");
517 }
518 
519 
VisitImportDeclaration(ImportDeclaration * node)520 void PrettyPrinter::VisitImportDeclaration(ImportDeclaration* node) {
521   Print("import ");
522   PrintLiteral(node->proxy()->name(), false);
523   Print(" from ");
524   PrintLiteral(node->module_specifier()->string(), true);
525   Print(";");
526 }
527 
528 
VisitExportDeclaration(ExportDeclaration * node)529 void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) {
530   Print("export ");
531   PrintLiteral(node->proxy()->name(), false);
532   Print(";");
533 }
534 
535 
VisitExpressionStatement(ExpressionStatement * node)536 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
537   Visit(node->expression());
538   Print(";");
539 }
540 
541 
VisitEmptyStatement(EmptyStatement * node)542 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
543   Print(";");
544 }
545 
546 
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * node)547 void PrettyPrinter::VisitSloppyBlockFunctionStatement(
548     SloppyBlockFunctionStatement* node) {
549   Visit(node->statement());
550 }
551 
552 
VisitIfStatement(IfStatement * node)553 void PrettyPrinter::VisitIfStatement(IfStatement* node) {
554   Print("if (");
555   Visit(node->condition());
556   Print(") ");
557   Visit(node->then_statement());
558   if (node->HasElseStatement()) {
559     Print(" else ");
560     Visit(node->else_statement());
561   }
562 }
563 
564 
VisitContinueStatement(ContinueStatement * node)565 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
566   Print("continue");
567   ZoneList<const AstRawString*>* labels = node->target()->labels();
568   if (labels != NULL) {
569     Print(" ");
570     DCHECK(labels->length() > 0);  // guaranteed to have at least one entry
571     PrintLiteral(labels->at(0), false);  // any label from the list is fine
572   }
573   Print(";");
574 }
575 
576 
VisitBreakStatement(BreakStatement * node)577 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
578   Print("break");
579   ZoneList<const AstRawString*>* labels = node->target()->labels();
580   if (labels != NULL) {
581     Print(" ");
582     DCHECK(labels->length() > 0);  // guaranteed to have at least one entry
583     PrintLiteral(labels->at(0), false);  // any label from the list is fine
584   }
585   Print(";");
586 }
587 
588 
VisitReturnStatement(ReturnStatement * node)589 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
590   Print("return ");
591   Visit(node->expression());
592   Print(";");
593 }
594 
595 
VisitWithStatement(WithStatement * node)596 void PrettyPrinter::VisitWithStatement(WithStatement* node) {
597   Print("with (");
598   Visit(node->expression());
599   Print(") ");
600   Visit(node->statement());
601 }
602 
603 
VisitSwitchStatement(SwitchStatement * node)604 void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) {
605   PrintLabels(node->labels());
606   Print("switch (");
607   Visit(node->tag());
608   Print(") { ");
609   ZoneList<CaseClause*>* cases = node->cases();
610   for (int i = 0; i < cases->length(); i++)
611     Visit(cases->at(i));
612   Print("}");
613 }
614 
615 
VisitCaseClause(CaseClause * clause)616 void PrettyPrinter::VisitCaseClause(CaseClause* clause) {
617   if (clause->is_default()) {
618     Print("default");
619   } else {
620     Print("case ");
621     Visit(clause->label());
622   }
623   Print(": ");
624   PrintStatements(clause->statements());
625   if (clause->statements()->length() > 0)
626     Print(" ");
627 }
628 
629 
VisitDoWhileStatement(DoWhileStatement * node)630 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
631   PrintLabels(node->labels());
632   Print("do ");
633   Visit(node->body());
634   Print(" while (");
635   Visit(node->cond());
636   Print(");");
637 }
638 
639 
VisitWhileStatement(WhileStatement * node)640 void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
641   PrintLabels(node->labels());
642   Print("while (");
643   Visit(node->cond());
644   Print(") ");
645   Visit(node->body());
646 }
647 
648 
VisitForStatement(ForStatement * node)649 void PrettyPrinter::VisitForStatement(ForStatement* node) {
650   PrintLabels(node->labels());
651   Print("for (");
652   if (node->init() != NULL) {
653     Visit(node->init());
654     Print(" ");
655   } else {
656     Print("; ");
657   }
658   if (node->cond() != NULL) Visit(node->cond());
659   Print("; ");
660   if (node->next() != NULL) {
661     Visit(node->next());  // prints extra ';', unfortunately
662     // to fix: should use Expression for next
663   }
664   Print(") ");
665   Visit(node->body());
666 }
667 
668 
VisitForInStatement(ForInStatement * node)669 void PrettyPrinter::VisitForInStatement(ForInStatement* node) {
670   PrintLabels(node->labels());
671   Print("for (");
672   Visit(node->each());
673   Print(" in ");
674   Visit(node->enumerable());
675   Print(") ");
676   Visit(node->body());
677 }
678 
679 
VisitForOfStatement(ForOfStatement * node)680 void PrettyPrinter::VisitForOfStatement(ForOfStatement* node) {
681   // TODO(adamk): ForOf is largely desugared as part of parsing,
682   // so it's hard to display useful stuff here. Should likely
683   // either bite the bullet and display less or try harder
684   // to preserve more.
685   PrintLabels(node->labels());
686   // The <each> is embedded inside a do-expression by the time we get here.
687   Print("for (<each> of ");
688   if (node->assign_iterator()->IsAssignment() &&
689       node->assign_iterator()->AsAssignment()->value()->IsCall() &&
690       node->assign_iterator()
691           ->AsAssignment()
692           ->value()
693           ->AsCall()
694           ->expression()
695           ->IsProperty() &&
696       node->assign_iterator()
697           ->AsAssignment()
698           ->value()
699           ->AsCall()
700           ->expression()
701           ->IsProperty()) {
702     Visit(node->assign_iterator()
703               ->AsAssignment()
704               ->value()
705               ->AsCall()
706               ->expression()
707               ->AsProperty()
708               ->obj());
709   } else {
710     Print("<iterable>");
711   }
712   Print(") ");
713   Visit(node->body());
714 }
715 
716 
VisitTryCatchStatement(TryCatchStatement * node)717 void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
718   Print("try ");
719   Visit(node->try_block());
720   Print(" catch (");
721   const bool quote = false;
722   PrintLiteral(node->variable()->name(), quote);
723   Print(") ");
724   Visit(node->catch_block());
725 }
726 
727 
VisitTryFinallyStatement(TryFinallyStatement * node)728 void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
729   Print("try ");
730   Visit(node->try_block());
731   Print(" finally ");
732   Visit(node->finally_block());
733 }
734 
735 
VisitDebuggerStatement(DebuggerStatement * node)736 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
737   Print("debugger ");
738 }
739 
740 
VisitFunctionLiteral(FunctionLiteral * node)741 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
742   Print("(");
743   PrintFunctionLiteral(node);
744   Print(")");
745 }
746 
747 
VisitClassLiteral(ClassLiteral * node)748 void PrettyPrinter::VisitClassLiteral(ClassLiteral* node) {
749   Print("(class ");
750   PrintLiteral(node->constructor()->name(), false);
751   if (node->extends()) {
752     Print(" extends ");
753     Visit(node->extends());
754   }
755   Print(" { ");
756   for (int i = 0; i < node->properties()->length(); i++) {
757     PrintObjectLiteralProperty(node->properties()->at(i));
758   }
759   Print(" })");
760 }
761 
762 
VisitNativeFunctionLiteral(NativeFunctionLiteral * node)763 void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
764   Print("(");
765   PrintLiteral(node->name(), false);
766   Print(")");
767 }
768 
769 
VisitDoExpression(DoExpression * node)770 void PrettyPrinter::VisitDoExpression(DoExpression* node) {
771   Print("(do {");
772   PrintStatements(node->block()->statements());
773   Print("})");
774 }
775 
776 
VisitConditional(Conditional * node)777 void PrettyPrinter::VisitConditional(Conditional* node) {
778   Visit(node->condition());
779   Print(" ? ");
780   Visit(node->then_expression());
781   Print(" : ");
782   Visit(node->else_expression());
783 }
784 
785 
VisitLiteral(Literal * node)786 void PrettyPrinter::VisitLiteral(Literal* node) {
787   PrintLiteral(node->value(), true);
788 }
789 
790 
VisitRegExpLiteral(RegExpLiteral * node)791 void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
792   Print(" RegExp(");
793   PrintLiteral(node->pattern(), false);
794   Print(",");
795   if (node->flags() & RegExp::kGlobal) Print("g");
796   if (node->flags() & RegExp::kIgnoreCase) Print("i");
797   if (node->flags() & RegExp::kMultiline) Print("m");
798   if (node->flags() & RegExp::kUnicode) Print("u");
799   if (node->flags() & RegExp::kSticky) Print("y");
800   Print(") ");
801 }
802 
803 
VisitObjectLiteral(ObjectLiteral * node)804 void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
805   Print("{ ");
806   for (int i = 0; i < node->properties()->length(); i++) {
807     if (i != 0) Print(",");
808     PrintObjectLiteralProperty(node->properties()->at(i));
809   }
810   Print(" }");
811 }
812 
813 
PrintObjectLiteralProperty(ObjectLiteralProperty * property)814 void PrettyPrinter::PrintObjectLiteralProperty(
815     ObjectLiteralProperty* property) {
816   // TODO(arv): Better printing of methods etc.
817   Print(" ");
818   Visit(property->key());
819   Print(": ");
820   Visit(property->value());
821 }
822 
823 
VisitArrayLiteral(ArrayLiteral * node)824 void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
825   Print("[ ");
826   Print(" literal_index = %d", node->literal_index());
827   for (int i = 0; i < node->values()->length(); i++) {
828     if (i != 0) Print(",");
829     Visit(node->values()->at(i));
830   }
831   Print(" ]");
832 }
833 
834 
VisitVariableProxy(VariableProxy * node)835 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
836   PrintLiteral(node->name(), false);
837 }
838 
839 
VisitAssignment(Assignment * node)840 void PrettyPrinter::VisitAssignment(Assignment* node) {
841   Visit(node->target());
842   Print(" %s ", Token::String(node->op()));
843   Visit(node->value());
844 }
845 
846 
VisitYield(Yield * node)847 void PrettyPrinter::VisitYield(Yield* node) {
848   Print("yield ");
849   Visit(node->expression());
850 }
851 
852 
VisitThrow(Throw * node)853 void PrettyPrinter::VisitThrow(Throw* node) {
854   Print("throw ");
855   Visit(node->exception());
856 }
857 
858 
VisitProperty(Property * node)859 void PrettyPrinter::VisitProperty(Property* node) {
860   Expression* key = node->key();
861   Literal* literal = key->AsLiteral();
862   if (literal != NULL && literal->value()->IsInternalizedString()) {
863     Print("(");
864     Visit(node->obj());
865     Print(").");
866     PrintLiteral(literal->value(), false);
867   } else {
868     Visit(node->obj());
869     Print("[");
870     Visit(key);
871     Print("]");
872   }
873 }
874 
875 
VisitCall(Call * node)876 void PrettyPrinter::VisitCall(Call* node) {
877   Visit(node->expression());
878   PrintArguments(node->arguments());
879 }
880 
881 
VisitCallNew(CallNew * node)882 void PrettyPrinter::VisitCallNew(CallNew* node) {
883   Print("new (");
884   Visit(node->expression());
885   Print(")");
886   PrintArguments(node->arguments());
887 }
888 
889 
VisitCallRuntime(CallRuntime * node)890 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
891   Print("%%%s\n", node->debug_name());
892   PrintArguments(node->arguments());
893 }
894 
895 
VisitUnaryOperation(UnaryOperation * node)896 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) {
897   Token::Value op = node->op();
898   bool needsSpace =
899       op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
900   Print("(%s%s", Token::String(op), needsSpace ? " " : "");
901   Visit(node->expression());
902   Print(")");
903 }
904 
905 
VisitCountOperation(CountOperation * node)906 void PrettyPrinter::VisitCountOperation(CountOperation* node) {
907   Print("(");
908   if (node->is_prefix()) Print("%s", Token::String(node->op()));
909   Visit(node->expression());
910   if (node->is_postfix()) Print("%s", Token::String(node->op()));
911   Print(")");
912 }
913 
914 
VisitBinaryOperation(BinaryOperation * node)915 void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) {
916   Print("(");
917   Visit(node->left());
918   Print(" %s ", Token::String(node->op()));
919   Visit(node->right());
920   Print(")");
921 }
922 
923 
VisitCompareOperation(CompareOperation * node)924 void PrettyPrinter::VisitCompareOperation(CompareOperation* node) {
925   Print("(");
926   Visit(node->left());
927   Print(" %s ", Token::String(node->op()));
928   Visit(node->right());
929   Print(")");
930 }
931 
932 
VisitSpread(Spread * node)933 void PrettyPrinter::VisitSpread(Spread* node) {
934   Print("(...");
935   Visit(node->expression());
936   Print(")");
937 }
938 
939 
VisitEmptyParentheses(EmptyParentheses * node)940 void PrettyPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
941   Print("()");
942 }
943 
944 
VisitThisFunction(ThisFunction * node)945 void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
946   Print("<this-function>");
947 }
948 
949 
VisitSuperPropertyReference(SuperPropertyReference * node)950 void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
951   Print("<super-property-reference>");
952 }
953 
954 
VisitSuperCallReference(SuperCallReference * node)955 void PrettyPrinter::VisitSuperCallReference(SuperCallReference* node) {
956   Print("<super-call-reference>");
957 }
958 
959 
VisitRewritableExpression(RewritableExpression * node)960 void PrettyPrinter::VisitRewritableExpression(RewritableExpression* node) {
961   Visit(node->expression());
962 }
963 
964 
Print(AstNode * node)965 const char* PrettyPrinter::Print(AstNode* node) {
966   Init();
967   Visit(node);
968   return output_;
969 }
970 
971 
PrintExpression(FunctionLiteral * program)972 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
973   Init();
974   ExpressionStatement* statement =
975     program->body()->at(0)->AsExpressionStatement();
976   Visit(statement->expression());
977   return output_;
978 }
979 
980 
PrintProgram(FunctionLiteral * program)981 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
982   Init();
983   PrintStatements(program->body());
984   Print("\n");
985   return output_;
986 }
987 
988 
PrintOut(Isolate * isolate,AstNode * node)989 void PrettyPrinter::PrintOut(Isolate* isolate, AstNode* node) {
990   PrettyPrinter printer(isolate);
991   PrintF("%s\n", printer.Print(node));
992 }
993 
994 
Init()995 void PrettyPrinter::Init() {
996   if (size_ == 0) {
997     DCHECK(output_ == NULL);
998     const int initial_size = 256;
999     output_ = NewArray<char>(initial_size);
1000     size_ = initial_size;
1001   }
1002   output_[0] = '\0';
1003   pos_ = 0;
1004 }
1005 
1006 
Print(const char * format,...)1007 void PrettyPrinter::Print(const char* format, ...) {
1008   for (;;) {
1009     va_list arguments;
1010     va_start(arguments, format);
1011     int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
1012                       format,
1013                       arguments);
1014     va_end(arguments);
1015 
1016     if (n >= 0) {
1017       // there was enough space - we are done
1018       pos_ += n;
1019       return;
1020     } else {
1021       // there was not enough space - allocate more and try again
1022       const int slack = 32;
1023       int new_size = size_ + (size_ >> 1) + slack;
1024       char* new_output = NewArray<char>(new_size);
1025       MemCopy(new_output, output_, pos_);
1026       DeleteArray(output_);
1027       output_ = new_output;
1028       size_ = new_size;
1029     }
1030   }
1031 }
1032 
1033 
PrintStatements(ZoneList<Statement * > * statements)1034 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
1035   if (statements == NULL) return;
1036   for (int i = 0; i < statements->length(); i++) {
1037     if (i != 0) Print(" ");
1038     Visit(statements->at(i));
1039   }
1040 }
1041 
1042 
PrintLabels(ZoneList<const AstRawString * > * labels)1043 void PrettyPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) {
1044   if (labels != NULL) {
1045     for (int i = 0; i < labels->length(); i++) {
1046       PrintLiteral(labels->at(i), false);
1047       Print(": ");
1048     }
1049   }
1050 }
1051 
1052 
PrintArguments(ZoneList<Expression * > * arguments)1053 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
1054   Print("(");
1055   for (int i = 0; i < arguments->length(); i++) {
1056     if (i != 0) Print(", ");
1057     Visit(arguments->at(i));
1058   }
1059   Print(")");
1060 }
1061 
1062 
PrintLiteral(Handle<Object> value,bool quote)1063 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
1064   Object* object = *value;
1065   if (object->IsString()) {
1066     String* string = String::cast(object);
1067     if (quote) Print("\"");
1068     for (int i = 0; i < string->length(); i++) {
1069       Print("%c", string->Get(i));
1070     }
1071     if (quote) Print("\"");
1072   } else if (object->IsNull(isolate_)) {
1073     Print("null");
1074   } else if (object->IsTrue(isolate_)) {
1075     Print("true");
1076   } else if (object->IsFalse(isolate_)) {
1077     Print("false");
1078   } else if (object->IsUndefined(isolate_)) {
1079     Print("undefined");
1080   } else if (object->IsNumber()) {
1081     Print("%g", object->Number());
1082   } else if (object->IsJSObject()) {
1083     // regular expression
1084     if (object->IsJSFunction()) {
1085       Print("JS-Function");
1086     } else if (object->IsJSArray()) {
1087       Print("JS-array[%u]",
1088             Smi::cast(JSArray::cast(object)->length())->value());
1089     } else if (object->IsJSObject()) {
1090       Print("JS-Object");
1091     } else {
1092       Print("?UNKNOWN?");
1093     }
1094   } else if (object->IsFixedArray()) {
1095     Print("FixedArray");
1096   } else {
1097     Print("<unknown literal %p>", static_cast<void*>(object));
1098   }
1099 }
1100 
1101 
PrintLiteral(const AstRawString * value,bool quote)1102 void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) {
1103   PrintLiteral(value->string(), quote);
1104 }
1105 
1106 
PrintParameters(Scope * scope)1107 void PrettyPrinter::PrintParameters(Scope* scope) {
1108   Print("(");
1109   for (int i = 0; i < scope->num_parameters(); i++) {
1110     if (i  > 0) Print(", ");
1111     PrintLiteral(scope->parameter(i)->name(), false);
1112   }
1113   Print(")");
1114 }
1115 
1116 
PrintDeclarations(ZoneList<Declaration * > * declarations)1117 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
1118   for (int i = 0; i < declarations->length(); i++) {
1119     if (i > 0) Print(" ");
1120     Visit(declarations->at(i));
1121   }
1122 }
1123 
1124 
PrintFunctionLiteral(FunctionLiteral * function)1125 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
1126   Print("function ");
1127   PrintLiteral(function->name(), false);
1128   PrintParameters(function->scope());
1129   Print(" { ");
1130   PrintDeclarations(function->scope()->declarations());
1131   PrintStatements(function->body());
1132   Print(" }");
1133 }
1134 
1135 
1136 //-----------------------------------------------------------------------------
1137 
1138 class IndentedScope BASE_EMBEDDED {
1139  public:
IndentedScope(AstPrinter * printer,const char * txt)1140   IndentedScope(AstPrinter* printer, const char* txt)
1141       : ast_printer_(printer) {
1142     ast_printer_->PrintIndented(txt);
1143     ast_printer_->Print("\n");
1144     ast_printer_->inc_indent();
1145   }
1146 
IndentedScope(AstPrinter * printer,const char * txt,int pos)1147   IndentedScope(AstPrinter* printer, const char* txt, int pos)
1148       : ast_printer_(printer) {
1149     ast_printer_->PrintIndented(txt);
1150     ast_printer_->Print(" at %d\n", pos);
1151     ast_printer_->inc_indent();
1152   }
1153 
~IndentedScope()1154   virtual ~IndentedScope() {
1155     ast_printer_->dec_indent();
1156   }
1157 
1158  private:
1159   AstPrinter* ast_printer_;
1160 };
1161 
1162 
1163 //-----------------------------------------------------------------------------
1164 
1165 
AstPrinter(Isolate * isolate)1166 AstPrinter::AstPrinter(Isolate* isolate) : PrettyPrinter(isolate), indent_(0) {}
1167 
1168 
~AstPrinter()1169 AstPrinter::~AstPrinter() {
1170   DCHECK(indent_ == 0);
1171 }
1172 
1173 
PrintIndented(const char * txt)1174 void AstPrinter::PrintIndented(const char* txt) {
1175   for (int i = 0; i < indent_; i++) {
1176     Print(". ");
1177   }
1178   Print("%s", txt);
1179 }
1180 
1181 
PrintLiteralIndented(const char * info,Handle<Object> value,bool quote)1182 void AstPrinter::PrintLiteralIndented(const char* info,
1183                                       Handle<Object> value,
1184                                       bool quote) {
1185   PrintIndented(info);
1186   Print(" ");
1187   PrintLiteral(value, quote);
1188   Print("\n");
1189 }
1190 
1191 
PrintLiteralWithModeIndented(const char * info,Variable * var,Handle<Object> value)1192 void AstPrinter::PrintLiteralWithModeIndented(const char* info,
1193                                               Variable* var,
1194                                               Handle<Object> value) {
1195   if (var == NULL) {
1196     PrintLiteralIndented(info, value, true);
1197   } else {
1198     EmbeddedVector<char, 256> buf;
1199     int pos = SNPrintF(buf, "%s (mode = %s", info,
1200                        Variable::Mode2String(var->mode()));
1201     SNPrintF(buf + pos, ")");
1202     PrintLiteralIndented(buf.start(), value, true);
1203   }
1204 }
1205 
1206 
PrintLabelsIndented(ZoneList<const AstRawString * > * labels)1207 void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) {
1208   if (labels == NULL || labels->length() == 0) return;
1209   PrintIndented("LABELS ");
1210   PrintLabels(labels);
1211   Print("\n");
1212 }
1213 
1214 
PrintIndentedVisit(const char * s,AstNode * node)1215 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
1216   IndentedScope indent(this, s, node->position());
1217   Visit(node);
1218 }
1219 
1220 
PrintProgram(FunctionLiteral * program)1221 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
1222   Init();
1223   { IndentedScope indent(this, "FUNC", program->position());
1224     PrintIndented("KIND");
1225     Print(" %d\n", program->kind());
1226     PrintIndented("YIELD COUNT");
1227     Print(" %d\n", program->yield_count());
1228     PrintLiteralIndented("NAME", program->name(), true);
1229     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
1230     PrintParameters(program->scope());
1231     PrintDeclarations(program->scope()->declarations());
1232     PrintStatements(program->body());
1233   }
1234   return Output();
1235 }
1236 
1237 
PrintOut(Isolate * isolate,AstNode * node)1238 void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) {
1239   AstPrinter printer(isolate);
1240   printer.Init();
1241   printer.Visit(node);
1242   PrintF("%s", printer.Output());
1243 }
1244 
1245 
PrintDeclarations(ZoneList<Declaration * > * declarations)1246 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
1247   if (declarations->length() > 0) {
1248     IndentedScope indent(this, "DECLS");
1249     for (int i = 0; i < declarations->length(); i++) {
1250       Visit(declarations->at(i));
1251     }
1252   }
1253 }
1254 
1255 
PrintParameters(Scope * scope)1256 void AstPrinter::PrintParameters(Scope* scope) {
1257   if (scope->num_parameters() > 0) {
1258     IndentedScope indent(this, "PARAMS");
1259     for (int i = 0; i < scope->num_parameters(); i++) {
1260       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
1261                                    scope->parameter(i)->name());
1262     }
1263   }
1264 }
1265 
1266 
PrintStatements(ZoneList<Statement * > * statements)1267 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
1268   for (int i = 0; i < statements->length(); i++) {
1269     Visit(statements->at(i));
1270   }
1271 }
1272 
1273 
PrintArguments(ZoneList<Expression * > * arguments)1274 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
1275   for (int i = 0; i < arguments->length(); i++) {
1276     Visit(arguments->at(i));
1277   }
1278 }
1279 
1280 
VisitBlock(Block * node)1281 void AstPrinter::VisitBlock(Block* node) {
1282   const char* block_txt =
1283       node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK";
1284   IndentedScope indent(this, block_txt, node->position());
1285   PrintStatements(node->statements());
1286 }
1287 
1288 
1289 // TODO(svenpanne) Start with IndentedScope.
VisitVariableDeclaration(VariableDeclaration * node)1290 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
1291   PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
1292                                node->proxy()->var(),
1293                                node->proxy()->name());
1294 }
1295 
1296 
1297 // TODO(svenpanne) Start with IndentedScope.
VisitFunctionDeclaration(FunctionDeclaration * node)1298 void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
1299   PrintIndented("FUNCTION ");
1300   PrintLiteral(node->proxy()->name(), true);
1301   Print(" = function ");
1302   PrintLiteral(node->fun()->name(), false);
1303   Print("\n");
1304 }
1305 
1306 
VisitImportDeclaration(ImportDeclaration * node)1307 void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
1308   IndentedScope indent(this, "IMPORT", node->position());
1309   PrintLiteralIndented("NAME", node->proxy()->name(), true);
1310   PrintLiteralIndented("FROM", node->module_specifier()->string(), true);
1311 }
1312 
1313 
VisitExportDeclaration(ExportDeclaration * node)1314 void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
1315   IndentedScope indent(this, "EXPORT", node->position());
1316   PrintLiteral(node->proxy()->name(), true);
1317 }
1318 
1319 
VisitExpressionStatement(ExpressionStatement * node)1320 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
1321   IndentedScope indent(this, "EXPRESSION STATEMENT", node->position());
1322   Visit(node->expression());
1323 }
1324 
1325 
VisitEmptyStatement(EmptyStatement * node)1326 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
1327   IndentedScope indent(this, "EMPTY", node->position());
1328 }
1329 
1330 
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * node)1331 void AstPrinter::VisitSloppyBlockFunctionStatement(
1332     SloppyBlockFunctionStatement* node) {
1333   Visit(node->statement());
1334 }
1335 
1336 
VisitIfStatement(IfStatement * node)1337 void AstPrinter::VisitIfStatement(IfStatement* node) {
1338   IndentedScope indent(this, "IF", node->position());
1339   PrintIndentedVisit("CONDITION", node->condition());
1340   PrintIndentedVisit("THEN", node->then_statement());
1341   if (node->HasElseStatement()) {
1342     PrintIndentedVisit("ELSE", node->else_statement());
1343   }
1344 }
1345 
1346 
VisitContinueStatement(ContinueStatement * node)1347 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
1348   IndentedScope indent(this, "CONTINUE", node->position());
1349   PrintLabelsIndented(node->target()->labels());
1350 }
1351 
1352 
VisitBreakStatement(BreakStatement * node)1353 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
1354   IndentedScope indent(this, "BREAK", node->position());
1355   PrintLabelsIndented(node->target()->labels());
1356 }
1357 
1358 
VisitReturnStatement(ReturnStatement * node)1359 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
1360   IndentedScope indent(this, "RETURN", node->position());
1361   Visit(node->expression());
1362 }
1363 
1364 
VisitWithStatement(WithStatement * node)1365 void AstPrinter::VisitWithStatement(WithStatement* node) {
1366   IndentedScope indent(this, "WITH", node->position());
1367   PrintIndentedVisit("OBJECT", node->expression());
1368   PrintIndentedVisit("BODY", node->statement());
1369 }
1370 
1371 
VisitSwitchStatement(SwitchStatement * node)1372 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
1373   IndentedScope indent(this, "SWITCH", node->position());
1374   PrintLabelsIndented(node->labels());
1375   PrintIndentedVisit("TAG", node->tag());
1376   for (int i = 0; i < node->cases()->length(); i++) {
1377     Visit(node->cases()->at(i));
1378   }
1379 }
1380 
1381 
VisitCaseClause(CaseClause * clause)1382 void AstPrinter::VisitCaseClause(CaseClause* clause) {
1383   if (clause->is_default()) {
1384     IndentedScope indent(this, "DEFAULT", clause->position());
1385     PrintStatements(clause->statements());
1386   } else {
1387     IndentedScope indent(this, "CASE", clause->position());
1388     Visit(clause->label());
1389     PrintStatements(clause->statements());
1390   }
1391 }
1392 
1393 
VisitDoWhileStatement(DoWhileStatement * node)1394 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
1395   IndentedScope indent(this, "DO", node->position());
1396   PrintIndented("YIELD COUNT");
1397   Print(" %d\n", node->yield_count());
1398   PrintLabelsIndented(node->labels());
1399   PrintIndentedVisit("BODY", node->body());
1400   PrintIndentedVisit("COND", node->cond());
1401 }
1402 
1403 
VisitWhileStatement(WhileStatement * node)1404 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
1405   IndentedScope indent(this, "WHILE", node->position());
1406   PrintIndented("YIELD COUNT");
1407   Print(" %d\n", node->yield_count());
1408   PrintLabelsIndented(node->labels());
1409   PrintIndentedVisit("COND", node->cond());
1410   PrintIndentedVisit("BODY", node->body());
1411 }
1412 
1413 
VisitForStatement(ForStatement * node)1414 void AstPrinter::VisitForStatement(ForStatement* node) {
1415   IndentedScope indent(this, "FOR", node->position());
1416   PrintIndented("YIELD COUNT");
1417   Print(" %d\n", node->yield_count());
1418   PrintLabelsIndented(node->labels());
1419   if (node->init()) PrintIndentedVisit("INIT", node->init());
1420   if (node->cond()) PrintIndentedVisit("COND", node->cond());
1421   PrintIndentedVisit("BODY", node->body());
1422   if (node->next()) PrintIndentedVisit("NEXT", node->next());
1423 }
1424 
1425 
VisitForInStatement(ForInStatement * node)1426 void AstPrinter::VisitForInStatement(ForInStatement* node) {
1427   IndentedScope indent(this, "FOR IN", node->position());
1428   PrintIndented("YIELD COUNT");
1429   Print(" %d\n", node->yield_count());
1430   PrintIndentedVisit("FOR", node->each());
1431   PrintIndentedVisit("IN", node->enumerable());
1432   PrintIndentedVisit("BODY", node->body());
1433 }
1434 
1435 
VisitForOfStatement(ForOfStatement * node)1436 void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
1437   IndentedScope indent(this, "FOR OF", node->position());
1438   PrintIndented("YIELD COUNT");
1439   Print(" %d\n", node->yield_count());
1440   PrintIndentedVisit("INIT", node->assign_iterator());
1441   PrintIndentedVisit("NEXT", node->next_result());
1442   PrintIndentedVisit("DONE", node->result_done());
1443   PrintIndentedVisit("EACH", node->assign_each());
1444   PrintIndentedVisit("BODY", node->body());
1445 }
1446 
1447 
VisitTryCatchStatement(TryCatchStatement * node)1448 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
1449   IndentedScope indent(this, "TRY CATCH", node->position());
1450   PrintIndentedVisit("TRY", node->try_block());
1451   PrintLiteralWithModeIndented("CATCHVAR",
1452                                node->variable(),
1453                                node->variable()->name());
1454   PrintIndentedVisit("CATCH", node->catch_block());
1455 }
1456 
1457 
VisitTryFinallyStatement(TryFinallyStatement * node)1458 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
1459   IndentedScope indent(this, "TRY FINALLY", node->position());
1460   PrintIndentedVisit("TRY", node->try_block());
1461   PrintIndentedVisit("FINALLY", node->finally_block());
1462 }
1463 
1464 
VisitDebuggerStatement(DebuggerStatement * node)1465 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
1466   IndentedScope indent(this, "DEBUGGER", node->position());
1467 }
1468 
1469 
VisitFunctionLiteral(FunctionLiteral * node)1470 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
1471   IndentedScope indent(this, "FUNC LITERAL", node->position());
1472   PrintLiteralIndented("NAME", node->name(), false);
1473   PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
1474   PrintParameters(node->scope());
1475   // We don't want to see the function literal in this case: it
1476   // will be printed via PrintProgram when the code for it is
1477   // generated.
1478   // PrintStatements(node->body());
1479 }
1480 
1481 
VisitClassLiteral(ClassLiteral * node)1482 void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
1483   IndentedScope indent(this, "CLASS LITERAL", node->position());
1484   PrintLiteralIndented("NAME", node->constructor()->name(), false);
1485   if (node->extends() != nullptr) {
1486     PrintIndentedVisit("EXTENDS", node->extends());
1487   }
1488   PrintProperties(node->properties());
1489 }
1490 
1491 
PrintProperties(ZoneList<ObjectLiteral::Property * > * properties)1492 void AstPrinter::PrintProperties(
1493     ZoneList<ObjectLiteral::Property*>* properties) {
1494   for (int i = 0; i < properties->length(); i++) {
1495     ObjectLiteral::Property* property = properties->at(i);
1496     const char* prop_kind = nullptr;
1497     switch (property->kind()) {
1498       case ObjectLiteral::Property::CONSTANT:
1499         prop_kind = "CONSTANT";
1500         break;
1501       case ObjectLiteral::Property::COMPUTED:
1502         prop_kind = "COMPUTED";
1503         break;
1504       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1505         prop_kind = "MATERIALIZED_LITERAL";
1506         break;
1507       case ObjectLiteral::Property::PROTOTYPE:
1508         prop_kind = "PROTOTYPE";
1509         break;
1510       case ObjectLiteral::Property::GETTER:
1511         prop_kind = "GETTER";
1512         break;
1513       case ObjectLiteral::Property::SETTER:
1514         prop_kind = "SETTER";
1515         break;
1516     }
1517     EmbeddedVector<char, 128> buf;
1518     SNPrintF(buf, "PROPERTY%s - %s", property->is_static() ? " - STATIC" : "",
1519              prop_kind);
1520     IndentedScope prop(this, buf.start());
1521     PrintIndentedVisit("KEY", properties->at(i)->key());
1522     PrintIndentedVisit("VALUE", properties->at(i)->value());
1523   }
1524 }
1525 
1526 
VisitNativeFunctionLiteral(NativeFunctionLiteral * node)1527 void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
1528   IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position());
1529   PrintLiteralIndented("NAME", node->name(), false);
1530 }
1531 
1532 
VisitDoExpression(DoExpression * node)1533 void AstPrinter::VisitDoExpression(DoExpression* node) {
1534   IndentedScope indent(this, "DO EXPRESSION", node->position());
1535   PrintStatements(node->block()->statements());
1536 }
1537 
1538 
VisitConditional(Conditional * node)1539 void AstPrinter::VisitConditional(Conditional* node) {
1540   IndentedScope indent(this, "CONDITIONAL", node->position());
1541   PrintIndentedVisit("CONDITION", node->condition());
1542   PrintIndentedVisit("THEN", node->then_expression());
1543   PrintIndentedVisit("ELSE", node->else_expression());
1544 }
1545 
1546 
1547 // TODO(svenpanne) Start with IndentedScope.
VisitLiteral(Literal * node)1548 void AstPrinter::VisitLiteral(Literal* node) {
1549   PrintLiteralIndented("LITERAL", node->value(), true);
1550 }
1551 
1552 
VisitRegExpLiteral(RegExpLiteral * node)1553 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
1554   IndentedScope indent(this, "REGEXP LITERAL", node->position());
1555   EmbeddedVector<char, 128> buf;
1556   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
1557   PrintIndented(buf.start());
1558   PrintLiteralIndented("PATTERN", node->pattern(), false);
1559   int i = 0;
1560   if (node->flags() & RegExp::kGlobal) buf[i++] = 'g';
1561   if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i';
1562   if (node->flags() & RegExp::kMultiline) buf[i++] = 'm';
1563   if (node->flags() & RegExp::kUnicode) buf[i++] = 'u';
1564   if (node->flags() & RegExp::kSticky) buf[i++] = 'y';
1565   buf[i] = '\0';
1566   PrintIndented("FLAGS ");
1567   Print("%s", buf.start());
1568   Print("\n");
1569 }
1570 
1571 
VisitObjectLiteral(ObjectLiteral * node)1572 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
1573   IndentedScope indent(this, "OBJ LITERAL", node->position());
1574   EmbeddedVector<char, 128> buf;
1575   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
1576   PrintIndented(buf.start());
1577   PrintProperties(node->properties());
1578 }
1579 
1580 
VisitArrayLiteral(ArrayLiteral * node)1581 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
1582   IndentedScope indent(this, "ARRAY LITERAL", node->position());
1583 
1584   EmbeddedVector<char, 128> buf;
1585   SNPrintF(buf, "literal_index = %d\n", node->literal_index());
1586   PrintIndented(buf.start());
1587   if (node->values()->length() > 0) {
1588     IndentedScope indent(this, "VALUES", node->position());
1589     for (int i = 0; i < node->values()->length(); i++) {
1590       Visit(node->values()->at(i));
1591     }
1592   }
1593 }
1594 
1595 
VisitVariableProxy(VariableProxy * node)1596 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
1597   EmbeddedVector<char, 128> buf;
1598   int pos =
1599       FormatSlotNode(&buf, node, "VAR PROXY", node->VariableFeedbackSlot());
1600 
1601   if (!node->is_resolved()) {
1602     SNPrintF(buf + pos, " unresolved");
1603     PrintLiteralWithModeIndented(buf.start(), nullptr, node->name());
1604   } else {
1605     Variable* var = node->var();
1606     switch (var->location()) {
1607       case VariableLocation::UNALLOCATED:
1608         SNPrintF(buf + pos, " unallocated");
1609         break;
1610       case VariableLocation::PARAMETER:
1611         SNPrintF(buf + pos, " parameter[%d]", var->index());
1612         break;
1613       case VariableLocation::LOCAL:
1614         SNPrintF(buf + pos, " local[%d]", var->index());
1615         break;
1616       case VariableLocation::CONTEXT:
1617         SNPrintF(buf + pos, " context[%d]", var->index());
1618         break;
1619       case VariableLocation::GLOBAL:
1620         SNPrintF(buf + pos, " global[%d]", var->index());
1621         break;
1622       case VariableLocation::LOOKUP:
1623         SNPrintF(buf + pos, " lookup");
1624         break;
1625     }
1626     PrintLiteralWithModeIndented(buf.start(), var, node->name());
1627   }
1628 }
1629 
1630 
VisitAssignment(Assignment * node)1631 void AstPrinter::VisitAssignment(Assignment* node) {
1632   IndentedScope indent(this, Token::Name(node->op()), node->position());
1633   Visit(node->target());
1634   Visit(node->value());
1635 }
1636 
1637 
VisitYield(Yield * node)1638 void AstPrinter::VisitYield(Yield* node) {
1639   EmbeddedVector<char, 128> buf;
1640   SNPrintF(buf, "YIELD id %d", node->yield_id());
1641   IndentedScope indent(this, buf.start(), node->position());
1642   Visit(node->expression());
1643 }
1644 
1645 
VisitThrow(Throw * node)1646 void AstPrinter::VisitThrow(Throw* node) {
1647   IndentedScope indent(this, "THROW", node->position());
1648   Visit(node->exception());
1649 }
1650 
1651 
VisitProperty(Property * node)1652 void AstPrinter::VisitProperty(Property* node) {
1653   EmbeddedVector<char, 128> buf;
1654   FormatSlotNode(&buf, node, "PROPERTY", node->PropertyFeedbackSlot());
1655   IndentedScope indent(this, buf.start(), node->position());
1656 
1657   Visit(node->obj());
1658   Literal* literal = node->key()->AsLiteral();
1659   if (literal != NULL && literal->value()->IsInternalizedString()) {
1660     PrintLiteralIndented("NAME", literal->value(), false);
1661   } else {
1662     PrintIndentedVisit("KEY", node->key());
1663   }
1664 }
1665 
1666 
VisitCall(Call * node)1667 void AstPrinter::VisitCall(Call* node) {
1668   EmbeddedVector<char, 128> buf;
1669   const char* name =
1670       node->tail_call_mode() == TailCallMode::kAllow ? "TAIL CALL" : "CALL";
1671   FormatSlotNode(&buf, node, name, node->CallFeedbackICSlot());
1672   IndentedScope indent(this, buf.start());
1673 
1674   Visit(node->expression());
1675   PrintArguments(node->arguments());
1676 }
1677 
1678 
VisitCallNew(CallNew * node)1679 void AstPrinter::VisitCallNew(CallNew* node) {
1680   IndentedScope indent(this, "CALL NEW", node->position());
1681   Visit(node->expression());
1682   PrintArguments(node->arguments());
1683 }
1684 
1685 
VisitCallRuntime(CallRuntime * node)1686 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1687   EmbeddedVector<char, 128> buf;
1688   SNPrintF(buf, "CALL RUNTIME %s", node->debug_name());
1689   IndentedScope indent(this, buf.start(), node->position());
1690   PrintArguments(node->arguments());
1691 }
1692 
1693 
VisitUnaryOperation(UnaryOperation * node)1694 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1695   IndentedScope indent(this, Token::Name(node->op()), node->position());
1696   Visit(node->expression());
1697 }
1698 
1699 
VisitCountOperation(CountOperation * node)1700 void AstPrinter::VisitCountOperation(CountOperation* node) {
1701   EmbeddedVector<char, 128> buf;
1702   SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1703            Token::Name(node->op()));
1704   IndentedScope indent(this, buf.start(), node->position());
1705   Visit(node->expression());
1706 }
1707 
1708 
VisitBinaryOperation(BinaryOperation * node)1709 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1710   IndentedScope indent(this, Token::Name(node->op()), node->position());
1711   Visit(node->left());
1712   Visit(node->right());
1713 }
1714 
1715 
VisitCompareOperation(CompareOperation * node)1716 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1717   IndentedScope indent(this, Token::Name(node->op()), node->position());
1718   Visit(node->left());
1719   Visit(node->right());
1720 }
1721 
1722 
VisitSpread(Spread * node)1723 void AstPrinter::VisitSpread(Spread* node) {
1724   IndentedScope indent(this, "...", node->position());
1725   Visit(node->expression());
1726 }
1727 
1728 
VisitEmptyParentheses(EmptyParentheses * node)1729 void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
1730   IndentedScope indent(this, "()", node->position());
1731 }
1732 
1733 
VisitThisFunction(ThisFunction * node)1734 void AstPrinter::VisitThisFunction(ThisFunction* node) {
1735   IndentedScope indent(this, "THIS-FUNCTION", node->position());
1736 }
1737 
1738 
VisitSuperPropertyReference(SuperPropertyReference * node)1739 void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
1740   IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position());
1741 }
1742 
1743 
VisitSuperCallReference(SuperCallReference * node)1744 void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
1745   IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position());
1746 }
1747 
1748 
VisitRewritableExpression(RewritableExpression * node)1749 void AstPrinter::VisitRewritableExpression(RewritableExpression* node) {
1750   Visit(node->expression());
1751 }
1752 
1753 
1754 #endif  // DEBUG
1755 
1756 }  // namespace internal
1757 }  // namespace v8
1758