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