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
13namespace v8 {
14namespace internal {
15
16CallPrinter::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
28CallPrinter::~CallPrinter() { DeleteArray(output_); }
29
30
31const char* CallPrinter::Print(FunctionLiteral* program, int position) {
32  Init();
33  position_ = position;
34  Find(program);
35  return output_;
36}
37
38
39void 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
54void 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
66void 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
92void CallPrinter::VisitBlock(Block* node) {
93  FindStatements(node->statements());
94}
95
96
97void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {}
98
99
100void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {}
101
102
103void CallPrinter::VisitImportDeclaration(ImportDeclaration* node) {
104}
105
106
107void CallPrinter::VisitExportDeclaration(ExportDeclaration* node) {}
108
109
110void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) {
111  Find(node->expression());
112}
113
114
115void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {}
116
117
118void CallPrinter::VisitSloppyBlockFunctionStatement(
119    SloppyBlockFunctionStatement* node) {
120  Find(node->statement());
121}
122
123
124void 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
133void CallPrinter::VisitContinueStatement(ContinueStatement* node) {}
134
135
136void CallPrinter::VisitBreakStatement(BreakStatement* node) {}
137
138
139void CallPrinter::VisitReturnStatement(ReturnStatement* node) {
140  Find(node->expression());
141}
142
143
144void CallPrinter::VisitWithStatement(WithStatement* node) {
145  Find(node->expression());
146  Find(node->statement());
147}
148
149
150void 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
157void CallPrinter::VisitCaseClause(CaseClause* clause) {
158  if (!clause->is_default()) {
159    Find(clause->label());
160  }
161  FindStatements(clause->statements());
162}
163
164
165void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
166  Find(node->body());
167  Find(node->cond());
168}
169
170
171void CallPrinter::VisitWhileStatement(WhileStatement* node) {
172  Find(node->cond());
173  Find(node->body());
174}
175
176
177void 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
187void CallPrinter::VisitForInStatement(ForInStatement* node) {
188  Find(node->each());
189  Find(node->enumerable());
190  Find(node->body());
191}
192
193
194void 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
202void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
203  Find(node->try_block());
204  Find(node->catch_block());
205}
206
207
208void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
209  Find(node->try_block());
210  Find(node->finally_block());
211}
212
213
214void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {}
215
216
217void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
218  FindStatements(node->body());
219}
220
221
222void 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
230void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
231
232
233void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); }
234
235
236void CallPrinter::VisitConditional(Conditional* node) {
237  Find(node->condition());
238  Find(node->then_expression());
239  Find(node->else_expression());
240}
241
242
243void CallPrinter::VisitLiteral(Literal* node) {
244  PrintLiteral(*node->value(), true);
245}
246
247
248void 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
260void 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
267void 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
277void 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
287void CallPrinter::VisitAssignment(Assignment* node) {
288  Find(node->target());
289  Find(node->value());
290}
291
292
293void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
294
295
296void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); }
297
298
299void 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
315void 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
333void 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
350void CallPrinter::VisitCallRuntime(CallRuntime* node) {
351  FindArguments(node->arguments());
352}
353
354
355void 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
365void 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
374void 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
383void 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
392void CallPrinter::VisitSpread(Spread* node) {
393  Print("(...");
394  Find(node->expression(), true);
395  Print(")");
396}
397
398
399void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
400  UNREACHABLE();
401}
402
403
404void CallPrinter::VisitThisFunction(ThisFunction* node) {}
405
406
407void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
408
409
410void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
411  Print("super");
412}
413
414
415void CallPrinter::VisitRewritableAssignmentExpression(
416    RewritableAssignmentExpression* node) {
417  Find(node->expression());
418}
419
420
421void 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
429void 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
437void 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
460void 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.
471static 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
481PrettyPrinter::PrettyPrinter(Isolate* isolate) {
482  output_ = NULL;
483  size_ = 0;
484  pos_ = 0;
485  InitializeAstVisitor(isolate);
486}
487
488
489PrettyPrinter::~PrettyPrinter() {
490  DeleteArray(output_);
491}
492
493
494void 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
502void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
503  Print("var ");
504  PrintLiteral(node->proxy()->name(), false);
505  Print(";");
506}
507
508
509void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
510  Print("function ");
511  PrintLiteral(node->proxy()->name(), false);
512  Print(" = ");
513  PrintFunctionLiteral(node->fun());
514  Print(";");
515}
516
517
518void 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
527void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) {
528  Print("export ");
529  PrintLiteral(node->proxy()->name(), false);
530  Print(";");
531}
532
533
534void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
535  Visit(node->expression());
536  Print(";");
537}
538
539
540void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
541  Print(";");
542}
543
544
545void PrettyPrinter::VisitSloppyBlockFunctionStatement(
546    SloppyBlockFunctionStatement* node) {
547  Visit(node->statement());
548}
549
550
551void 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
563void 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
575void 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
587void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
588  Print("return ");
589  Visit(node->expression());
590  Print(";");
591}
592
593
594void PrettyPrinter::VisitWithStatement(WithStatement* node) {
595  Print("with (");
596  Visit(node->expression());
597  Print(") ");
598  Visit(node->statement());
599}
600
601
602void 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
614void 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
628void 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
638void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
639  PrintLabels(node->labels());
640  Print("while (");
641  Visit(node->cond());
642  Print(") ");
643  Visit(node->body());
644}
645
646
647void 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
667void 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
678void 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
689void 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
700void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
701  Print("try ");
702  Visit(node->try_block());
703  Print(" finally ");
704  Visit(node->finally_block());
705}
706
707
708void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
709  Print("debugger ");
710}
711
712
713void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
714  Print("(");
715  PrintFunctionLiteral(node);
716  Print(")");
717}
718
719
720void 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
735void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
736  Print("(");
737  PrintLiteral(node->name(), false);
738  Print(")");
739}
740
741
742void PrettyPrinter::VisitDoExpression(DoExpression* node) {
743  Print("(do {");
744  PrintStatements(node->block()->statements());
745  Print("})");
746}
747
748
749void 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
758void PrettyPrinter::VisitLiteral(Literal* node) {
759  PrintLiteral(node->value(), true);
760}
761
762
763void 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
776void 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
786void 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
796void 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
807void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
808  PrintLiteral(node->name(), false);
809}
810
811
812void PrettyPrinter::VisitAssignment(Assignment* node) {
813  Visit(node->target());
814  Print(" %s ", Token::String(node->op()));
815  Visit(node->value());
816}
817
818
819void PrettyPrinter::VisitYield(Yield* node) {
820  Print("yield ");
821  Visit(node->expression());
822}
823
824
825void PrettyPrinter::VisitThrow(Throw* node) {
826  Print("throw ");
827  Visit(node->exception());
828}
829
830
831void 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
848void PrettyPrinter::VisitCall(Call* node) {
849  Visit(node->expression());
850  PrintArguments(node->arguments());
851}
852
853
854void PrettyPrinter::VisitCallNew(CallNew* node) {
855  Print("new (");
856  Visit(node->expression());
857  Print(")");
858  PrintArguments(node->arguments());
859}
860
861
862void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
863  Print("%%%s\n", node->debug_name());
864  PrintArguments(node->arguments());
865}
866
867
868void 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
878void 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
887void 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
896void 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
905void PrettyPrinter::VisitSpread(Spread* node) {
906  Print("(...");
907  Visit(node->expression());
908  Print(")");
909}
910
911
912void PrettyPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
913  Print("()");
914}
915
916
917void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
918  Print("<this-function>");
919}
920
921
922void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
923  Print("<super-property-reference>");
924}
925
926
927void PrettyPrinter::VisitSuperCallReference(SuperCallReference* node) {
928  Print("<super-call-reference>");
929}
930
931
932void PrettyPrinter::VisitRewritableAssignmentExpression(
933    RewritableAssignmentExpression* node) {
934  Visit(node->expression());
935}
936
937
938const char* PrettyPrinter::Print(AstNode* node) {
939  Init();
940  Visit(node);
941  return output_;
942}
943
944
945const 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
954const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
955  Init();
956  PrintStatements(program->body());
957  Print("\n");
958  return output_;
959}
960
961
962void PrettyPrinter::PrintOut(Isolate* isolate, AstNode* node) {
963  PrettyPrinter printer(isolate);
964  PrintF("%s\n", printer.Print(node));
965}
966
967
968void 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
980void 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
1007void 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
1016void 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
1026void 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
1036void 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
1074void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) {
1075  PrintLiteral(value->string(), quote);
1076}
1077
1078
1079void 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
1089void 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
1097void 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
1110class IndentedScope BASE_EMBEDDED {
1111 public:
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
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
1126  virtual ~IndentedScope() {
1127    ast_printer_->dec_indent();
1128  }
1129
1130 private:
1131  AstPrinter* ast_printer_;
1132};
1133
1134
1135//-----------------------------------------------------------------------------
1136
1137
1138AstPrinter::AstPrinter(Isolate* isolate) : PrettyPrinter(isolate), indent_(0) {}
1139
1140
1141AstPrinter::~AstPrinter() {
1142  DCHECK(indent_ == 0);
1143}
1144
1145
1146void AstPrinter::PrintIndented(const char* txt) {
1147  for (int i = 0; i < indent_; i++) {
1148    Print(". ");
1149  }
1150  Print(txt);
1151}
1152
1153
1154void 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
1164void 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
1179void 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
1187void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
1188  IndentedScope indent(this, s, node->position());
1189  Visit(node);
1190}
1191
1192
1193const 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
1206void 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
1216void 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
1227void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
1228  for (int i = 0; i < statements->length(); i++) {
1229    Visit(statements->at(i));
1230  }
1231}
1232
1233
1234void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
1235  for (int i = 0; i < arguments->length(); i++) {
1236    Visit(arguments->at(i));
1237  }
1238}
1239
1240
1241void 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.
1250void 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.
1258void 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
1267void 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
1274void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
1275  IndentedScope indent(this, "EXPORT", node->position());
1276  PrintLiteral(node->proxy()->name(), true);
1277}
1278
1279
1280void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
1281  IndentedScope indent(this, "EXPRESSION STATEMENT", node->position());
1282  Visit(node->expression());
1283}
1284
1285
1286void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
1287  IndentedScope indent(this, "EMPTY", node->position());
1288}
1289
1290
1291void AstPrinter::VisitSloppyBlockFunctionStatement(
1292    SloppyBlockFunctionStatement* node) {
1293  Visit(node->statement());
1294}
1295
1296
1297void 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
1307void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
1308  IndentedScope indent(this, "CONTINUE", node->position());
1309  PrintLabelsIndented(node->target()->labels());
1310}
1311
1312
1313void AstPrinter::VisitBreakStatement(BreakStatement* node) {
1314  IndentedScope indent(this, "BREAK", node->position());
1315  PrintLabelsIndented(node->target()->labels());
1316}
1317
1318
1319void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
1320  IndentedScope indent(this, "RETURN", node->position());
1321  Visit(node->expression());
1322}
1323
1324
1325void AstPrinter::VisitWithStatement(WithStatement* node) {
1326  IndentedScope indent(this, "WITH", node->position());
1327  PrintIndentedVisit("OBJECT", node->expression());
1328  PrintIndentedVisit("BODY", node->statement());
1329}
1330
1331
1332void 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
1342void 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
1354void 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
1362void 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
1370void 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
1380void 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
1388void 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
1396void 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
1406void 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
1413void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
1414  IndentedScope indent(this, "DEBUGGER", node->position());
1415}
1416
1417
1418void 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
1430void 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
1442void 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
1477void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
1478  IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position());
1479  PrintLiteralIndented("NAME", node->name(), false);
1480}
1481
1482
1483void AstPrinter::VisitDoExpression(DoExpression* node) {
1484  IndentedScope indent(this, "DO EXPRESSION", node->position());
1485  PrintStatements(node->block()->statements());
1486}
1487
1488
1489void 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.
1498void AstPrinter::VisitLiteral(Literal* node) {
1499  PrintLiteralIndented("LITERAL", node->value(), true);
1500}
1501
1502
1503void 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
1522void 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
1531void 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
1546void 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
1575void 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
1582void AstPrinter::VisitYield(Yield* node) {
1583  IndentedScope indent(this, "YIELD", node->position());
1584  Visit(node->expression());
1585}
1586
1587
1588void AstPrinter::VisitThrow(Throw* node) {
1589  IndentedScope indent(this, "THROW", node->position());
1590  Visit(node->exception());
1591}
1592
1593
1594void 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
1609void 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
1619void AstPrinter::VisitCallNew(CallNew* node) {
1620  IndentedScope indent(this, "CALL NEW", node->position());
1621  Visit(node->expression());
1622  PrintArguments(node->arguments());
1623}
1624
1625
1626void 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
1634void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1635  IndentedScope indent(this, Token::Name(node->op()), node->position());
1636  Visit(node->expression());
1637}
1638
1639
1640void 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
1649void 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
1656void 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
1663void AstPrinter::VisitSpread(Spread* node) {
1664  IndentedScope indent(this, "...", node->position());
1665  Visit(node->expression());
1666}
1667
1668
1669void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
1670  IndentedScope indent(this, "()", node->position());
1671}
1672
1673
1674void AstPrinter::VisitThisFunction(ThisFunction* node) {
1675  IndentedScope indent(this, "THIS-FUNCTION", node->position());
1676}
1677
1678
1679void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
1680  IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position());
1681}
1682
1683
1684void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
1685  IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position());
1686}
1687
1688
1689void AstPrinter::VisitRewritableAssignmentExpression(
1690    RewritableAssignmentExpression* node) {
1691  Visit(node->expression());
1692}
1693
1694
1695#endif  // DEBUG
1696
1697}  // namespace internal
1698}  // namespace v8
1699