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