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/prettyprinter.h"
10 #include "src/scopes.h"
11 #include "src/platform.h"
12
13 namespace v8 {
14 namespace internal {
15
16 #ifdef DEBUG
17
PrettyPrinter(Zone * zone)18 PrettyPrinter::PrettyPrinter(Zone* zone) {
19 output_ = NULL;
20 size_ = 0;
21 pos_ = 0;
22 InitializeAstVisitor(zone);
23 }
24
25
~PrettyPrinter()26 PrettyPrinter::~PrettyPrinter() {
27 DeleteArray(output_);
28 }
29
30
VisitBlock(Block * node)31 void PrettyPrinter::VisitBlock(Block* node) {
32 if (!node->is_initializer_block()) Print("{ ");
33 PrintStatements(node->statements());
34 if (node->statements()->length() > 0) Print(" ");
35 if (!node->is_initializer_block()) Print("}");
36 }
37
38
VisitVariableDeclaration(VariableDeclaration * node)39 void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
40 Print("var ");
41 PrintLiteral(node->proxy()->name(), false);
42 Print(";");
43 }
44
45
VisitFunctionDeclaration(FunctionDeclaration * node)46 void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
47 Print("function ");
48 PrintLiteral(node->proxy()->name(), false);
49 Print(" = ");
50 PrintFunctionLiteral(node->fun());
51 Print(";");
52 }
53
54
VisitModuleDeclaration(ModuleDeclaration * node)55 void PrettyPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
56 Print("module ");
57 PrintLiteral(node->proxy()->name(), false);
58 Print(" = ");
59 Visit(node->module());
60 Print(";");
61 }
62
63
VisitImportDeclaration(ImportDeclaration * node)64 void PrettyPrinter::VisitImportDeclaration(ImportDeclaration* node) {
65 Print("import ");
66 PrintLiteral(node->proxy()->name(), false);
67 Print(" from ");
68 Visit(node->module());
69 Print(";");
70 }
71
72
VisitExportDeclaration(ExportDeclaration * node)73 void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) {
74 Print("export ");
75 PrintLiteral(node->proxy()->name(), false);
76 Print(";");
77 }
78
79
VisitModuleLiteral(ModuleLiteral * node)80 void PrettyPrinter::VisitModuleLiteral(ModuleLiteral* node) {
81 VisitBlock(node->body());
82 }
83
84
VisitModuleVariable(ModuleVariable * node)85 void PrettyPrinter::VisitModuleVariable(ModuleVariable* node) {
86 Visit(node->proxy());
87 }
88
89
VisitModulePath(ModulePath * node)90 void PrettyPrinter::VisitModulePath(ModulePath* node) {
91 Visit(node->module());
92 Print(".");
93 PrintLiteral(node->name(), false);
94 }
95
96
VisitModuleUrl(ModuleUrl * node)97 void PrettyPrinter::VisitModuleUrl(ModuleUrl* node) {
98 Print("at ");
99 PrintLiteral(node->url(), true);
100 }
101
102
VisitModuleStatement(ModuleStatement * node)103 void PrettyPrinter::VisitModuleStatement(ModuleStatement* node) {
104 Print("module ");
105 PrintLiteral(node->proxy()->name(), false);
106 Print(" ");
107 Visit(node->body());
108 }
109
110
VisitExpressionStatement(ExpressionStatement * node)111 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
112 Visit(node->expression());
113 Print(";");
114 }
115
116
VisitEmptyStatement(EmptyStatement * node)117 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
118 Print(";");
119 }
120
121
VisitIfStatement(IfStatement * node)122 void PrettyPrinter::VisitIfStatement(IfStatement* node) {
123 Print("if (");
124 Visit(node->condition());
125 Print(") ");
126 Visit(node->then_statement());
127 if (node->HasElseStatement()) {
128 Print(" else ");
129 Visit(node->else_statement());
130 }
131 }
132
133
VisitContinueStatement(ContinueStatement * node)134 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
135 Print("continue");
136 ZoneStringList* labels = node->target()->labels();
137 if (labels != NULL) {
138 Print(" ");
139 ASSERT(labels->length() > 0); // guaranteed to have at least one entry
140 PrintLiteral(labels->at(0), false); // any label from the list is fine
141 }
142 Print(";");
143 }
144
145
VisitBreakStatement(BreakStatement * node)146 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
147 Print("break");
148 ZoneStringList* labels = node->target()->labels();
149 if (labels != NULL) {
150 Print(" ");
151 ASSERT(labels->length() > 0); // guaranteed to have at least one entry
152 PrintLiteral(labels->at(0), false); // any label from the list is fine
153 }
154 Print(";");
155 }
156
157
VisitReturnStatement(ReturnStatement * node)158 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
159 Print("return ");
160 Visit(node->expression());
161 Print(";");
162 }
163
164
VisitWithStatement(WithStatement * node)165 void PrettyPrinter::VisitWithStatement(WithStatement* node) {
166 Print("with (");
167 Visit(node->expression());
168 Print(") ");
169 Visit(node->statement());
170 }
171
172
VisitSwitchStatement(SwitchStatement * node)173 void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) {
174 PrintLabels(node->labels());
175 Print("switch (");
176 Visit(node->tag());
177 Print(") { ");
178 ZoneList<CaseClause*>* cases = node->cases();
179 for (int i = 0; i < cases->length(); i++)
180 Visit(cases->at(i));
181 Print("}");
182 }
183
184
VisitCaseClause(CaseClause * clause)185 void PrettyPrinter::VisitCaseClause(CaseClause* clause) {
186 if (clause->is_default()) {
187 Print("default");
188 } else {
189 Print("case ");
190 Visit(clause->label());
191 }
192 Print(": ");
193 PrintStatements(clause->statements());
194 if (clause->statements()->length() > 0)
195 Print(" ");
196 }
197
198
VisitDoWhileStatement(DoWhileStatement * node)199 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
200 PrintLabels(node->labels());
201 Print("do ");
202 Visit(node->body());
203 Print(" while (");
204 Visit(node->cond());
205 Print(");");
206 }
207
208
VisitWhileStatement(WhileStatement * node)209 void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
210 PrintLabels(node->labels());
211 Print("while (");
212 Visit(node->cond());
213 Print(") ");
214 Visit(node->body());
215 }
216
217
VisitForStatement(ForStatement * node)218 void PrettyPrinter::VisitForStatement(ForStatement* node) {
219 PrintLabels(node->labels());
220 Print("for (");
221 if (node->init() != NULL) {
222 Visit(node->init());
223 Print(" ");
224 } else {
225 Print("; ");
226 }
227 if (node->cond() != NULL) Visit(node->cond());
228 Print("; ");
229 if (node->next() != NULL) {
230 Visit(node->next()); // prints extra ';', unfortunately
231 // to fix: should use Expression for next
232 }
233 Print(") ");
234 Visit(node->body());
235 }
236
237
VisitForInStatement(ForInStatement * node)238 void PrettyPrinter::VisitForInStatement(ForInStatement* node) {
239 PrintLabels(node->labels());
240 Print("for (");
241 Visit(node->each());
242 Print(" in ");
243 Visit(node->enumerable());
244 Print(") ");
245 Visit(node->body());
246 }
247
248
VisitForOfStatement(ForOfStatement * node)249 void PrettyPrinter::VisitForOfStatement(ForOfStatement* node) {
250 PrintLabels(node->labels());
251 Print("for (");
252 Visit(node->each());
253 Print(" of ");
254 Visit(node->iterable());
255 Print(") ");
256 Visit(node->body());
257 }
258
259
VisitTryCatchStatement(TryCatchStatement * node)260 void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
261 Print("try ");
262 Visit(node->try_block());
263 Print(" catch (");
264 const bool quote = false;
265 PrintLiteral(node->variable()->name(), quote);
266 Print(") ");
267 Visit(node->catch_block());
268 }
269
270
VisitTryFinallyStatement(TryFinallyStatement * node)271 void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
272 Print("try ");
273 Visit(node->try_block());
274 Print(" finally ");
275 Visit(node->finally_block());
276 }
277
278
VisitDebuggerStatement(DebuggerStatement * node)279 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
280 Print("debugger ");
281 }
282
283
VisitFunctionLiteral(FunctionLiteral * node)284 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
285 Print("(");
286 PrintFunctionLiteral(node);
287 Print(")");
288 }
289
290
VisitNativeFunctionLiteral(NativeFunctionLiteral * node)291 void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
292 Print("(");
293 PrintLiteral(node->name(), false);
294 Print(")");
295 }
296
297
VisitConditional(Conditional * node)298 void PrettyPrinter::VisitConditional(Conditional* node) {
299 Visit(node->condition());
300 Print(" ? ");
301 Visit(node->then_expression());
302 Print(" : ");
303 Visit(node->else_expression());
304 }
305
306
VisitLiteral(Literal * node)307 void PrettyPrinter::VisitLiteral(Literal* node) {
308 PrintLiteral(node->value(), true);
309 }
310
311
VisitRegExpLiteral(RegExpLiteral * node)312 void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
313 Print(" RegExp(");
314 PrintLiteral(node->pattern(), false);
315 Print(",");
316 PrintLiteral(node->flags(), false);
317 Print(") ");
318 }
319
320
VisitObjectLiteral(ObjectLiteral * node)321 void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
322 Print("{ ");
323 for (int i = 0; i < node->properties()->length(); i++) {
324 if (i != 0) Print(",");
325 ObjectLiteral::Property* property = node->properties()->at(i);
326 Print(" ");
327 Visit(property->key());
328 Print(": ");
329 Visit(property->value());
330 }
331 Print(" }");
332 }
333
334
VisitArrayLiteral(ArrayLiteral * node)335 void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
336 Print("[ ");
337 for (int i = 0; i < node->values()->length(); i++) {
338 if (i != 0) Print(",");
339 Visit(node->values()->at(i));
340 }
341 Print(" ]");
342 }
343
344
VisitVariableProxy(VariableProxy * node)345 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
346 PrintLiteral(node->name(), false);
347 }
348
349
VisitAssignment(Assignment * node)350 void PrettyPrinter::VisitAssignment(Assignment* node) {
351 Visit(node->target());
352 Print(" %s ", Token::String(node->op()));
353 Visit(node->value());
354 }
355
356
VisitYield(Yield * node)357 void PrettyPrinter::VisitYield(Yield* node) {
358 Print("yield ");
359 Visit(node->expression());
360 }
361
362
VisitThrow(Throw * node)363 void PrettyPrinter::VisitThrow(Throw* node) {
364 Print("throw ");
365 Visit(node->exception());
366 }
367
368
VisitProperty(Property * node)369 void PrettyPrinter::VisitProperty(Property* node) {
370 Expression* key = node->key();
371 Literal* literal = key->AsLiteral();
372 if (literal != NULL && literal->value()->IsInternalizedString()) {
373 Print("(");
374 Visit(node->obj());
375 Print(").");
376 PrintLiteral(literal->value(), false);
377 } else {
378 Visit(node->obj());
379 Print("[");
380 Visit(key);
381 Print("]");
382 }
383 }
384
385
VisitCall(Call * node)386 void PrettyPrinter::VisitCall(Call* node) {
387 Visit(node->expression());
388 PrintArguments(node->arguments());
389 }
390
391
VisitCallNew(CallNew * node)392 void PrettyPrinter::VisitCallNew(CallNew* node) {
393 Print("new (");
394 Visit(node->expression());
395 Print(")");
396 PrintArguments(node->arguments());
397 }
398
399
VisitCallRuntime(CallRuntime * node)400 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
401 Print("%%");
402 PrintLiteral(node->name(), false);
403 PrintArguments(node->arguments());
404 }
405
406
VisitUnaryOperation(UnaryOperation * node)407 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) {
408 Token::Value op = node->op();
409 bool needsSpace =
410 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
411 Print("(%s%s", Token::String(op), needsSpace ? " " : "");
412 Visit(node->expression());
413 Print(")");
414 }
415
416
VisitCountOperation(CountOperation * node)417 void PrettyPrinter::VisitCountOperation(CountOperation* node) {
418 Print("(");
419 if (node->is_prefix()) Print("%s", Token::String(node->op()));
420 Visit(node->expression());
421 if (node->is_postfix()) Print("%s", Token::String(node->op()));
422 Print(")");
423 }
424
425
VisitBinaryOperation(BinaryOperation * node)426 void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) {
427 Print("(");
428 Visit(node->left());
429 Print(" %s ", Token::String(node->op()));
430 Visit(node->right());
431 Print(")");
432 }
433
434
VisitCompareOperation(CompareOperation * node)435 void PrettyPrinter::VisitCompareOperation(CompareOperation* node) {
436 Print("(");
437 Visit(node->left());
438 Print(" %s ", Token::String(node->op()));
439 Visit(node->right());
440 Print(")");
441 }
442
443
VisitThisFunction(ThisFunction * node)444 void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
445 Print("<this-function>");
446 }
447
448
Print(AstNode * node)449 const char* PrettyPrinter::Print(AstNode* node) {
450 Init();
451 Visit(node);
452 return output_;
453 }
454
455
PrintExpression(FunctionLiteral * program)456 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
457 Init();
458 ExpressionStatement* statement =
459 program->body()->at(0)->AsExpressionStatement();
460 Visit(statement->expression());
461 return output_;
462 }
463
464
PrintProgram(FunctionLiteral * program)465 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
466 Init();
467 PrintStatements(program->body());
468 Print("\n");
469 return output_;
470 }
471
472
PrintOut(Zone * zone,AstNode * node)473 void PrettyPrinter::PrintOut(Zone* zone, AstNode* node) {
474 PrettyPrinter printer(zone);
475 PrintF("%s", printer.Print(node));
476 }
477
478
Init()479 void PrettyPrinter::Init() {
480 if (size_ == 0) {
481 ASSERT(output_ == NULL);
482 const int initial_size = 256;
483 output_ = NewArray<char>(initial_size);
484 size_ = initial_size;
485 }
486 output_[0] = '\0';
487 pos_ = 0;
488 }
489
490
Print(const char * format,...)491 void PrettyPrinter::Print(const char* format, ...) {
492 for (;;) {
493 va_list arguments;
494 va_start(arguments, format);
495 int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
496 format,
497 arguments);
498 va_end(arguments);
499
500 if (n >= 0) {
501 // there was enough space - we are done
502 pos_ += n;
503 return;
504 } else {
505 // there was not enough space - allocate more and try again
506 const int slack = 32;
507 int new_size = size_ + (size_ >> 1) + slack;
508 char* new_output = NewArray<char>(new_size);
509 MemCopy(new_output, output_, pos_);
510 DeleteArray(output_);
511 output_ = new_output;
512 size_ = new_size;
513 }
514 }
515 }
516
517
PrintStatements(ZoneList<Statement * > * statements)518 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
519 if (statements == NULL) return;
520 for (int i = 0; i < statements->length(); i++) {
521 if (i != 0) Print(" ");
522 Visit(statements->at(i));
523 }
524 }
525
526
PrintLabels(ZoneStringList * labels)527 void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
528 if (labels != NULL) {
529 for (int i = 0; i < labels->length(); i++) {
530 PrintLiteral(labels->at(i), false);
531 Print(": ");
532 }
533 }
534 }
535
536
PrintArguments(ZoneList<Expression * > * arguments)537 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
538 Print("(");
539 for (int i = 0; i < arguments->length(); i++) {
540 if (i != 0) Print(", ");
541 Visit(arguments->at(i));
542 }
543 Print(")");
544 }
545
546
PrintLiteral(Handle<Object> value,bool quote)547 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
548 Object* object = *value;
549 if (object->IsString()) {
550 String* string = String::cast(object);
551 if (quote) Print("\"");
552 for (int i = 0; i < string->length(); i++) {
553 Print("%c", string->Get(i));
554 }
555 if (quote) Print("\"");
556 } else if (object->IsNull()) {
557 Print("null");
558 } else if (object->IsTrue()) {
559 Print("true");
560 } else if (object->IsFalse()) {
561 Print("false");
562 } else if (object->IsUndefined()) {
563 Print("undefined");
564 } else if (object->IsNumber()) {
565 Print("%g", object->Number());
566 } else if (object->IsJSObject()) {
567 // regular expression
568 if (object->IsJSFunction()) {
569 Print("JS-Function");
570 } else if (object->IsJSArray()) {
571 Print("JS-array[%u]", JSArray::cast(object)->length());
572 } else if (object->IsJSObject()) {
573 Print("JS-Object");
574 } else {
575 Print("?UNKNOWN?");
576 }
577 } else if (object->IsFixedArray()) {
578 Print("FixedArray");
579 } else {
580 Print("<unknown literal %p>", object);
581 }
582 }
583
584
PrintParameters(Scope * scope)585 void PrettyPrinter::PrintParameters(Scope* scope) {
586 Print("(");
587 for (int i = 0; i < scope->num_parameters(); i++) {
588 if (i > 0) Print(", ");
589 PrintLiteral(scope->parameter(i)->name(), false);
590 }
591 Print(")");
592 }
593
594
PrintDeclarations(ZoneList<Declaration * > * declarations)595 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
596 for (int i = 0; i < declarations->length(); i++) {
597 if (i > 0) Print(" ");
598 Visit(declarations->at(i));
599 }
600 }
601
602
PrintFunctionLiteral(FunctionLiteral * function)603 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
604 Print("function ");
605 PrintLiteral(function->name(), false);
606 PrintParameters(function->scope());
607 Print(" { ");
608 PrintDeclarations(function->scope()->declarations());
609 PrintStatements(function->body());
610 Print(" }");
611 }
612
613
614 //-----------------------------------------------------------------------------
615
616 class IndentedScope BASE_EMBEDDED {
617 public:
IndentedScope(AstPrinter * printer,const char * txt)618 IndentedScope(AstPrinter* printer, const char* txt)
619 : ast_printer_(printer) {
620 ast_printer_->PrintIndented(txt);
621 ast_printer_->Print("\n");
622 ast_printer_->inc_indent();
623 }
624
~IndentedScope()625 virtual ~IndentedScope() {
626 ast_printer_->dec_indent();
627 }
628
629 private:
630 AstPrinter* ast_printer_;
631 };
632
633
634 //-----------------------------------------------------------------------------
635
636
AstPrinter(Zone * zone)637 AstPrinter::AstPrinter(Zone* zone) : PrettyPrinter(zone), indent_(0) {
638 }
639
640
~AstPrinter()641 AstPrinter::~AstPrinter() {
642 ASSERT(indent_ == 0);
643 }
644
645
PrintIndented(const char * txt)646 void AstPrinter::PrintIndented(const char* txt) {
647 for (int i = 0; i < indent_; i++) {
648 Print(". ");
649 }
650 Print(txt);
651 }
652
653
PrintLiteralIndented(const char * info,Handle<Object> value,bool quote)654 void AstPrinter::PrintLiteralIndented(const char* info,
655 Handle<Object> value,
656 bool quote) {
657 PrintIndented(info);
658 Print(" ");
659 PrintLiteral(value, quote);
660 Print("\n");
661 }
662
663
PrintLiteralWithModeIndented(const char * info,Variable * var,Handle<Object> value)664 void AstPrinter::PrintLiteralWithModeIndented(const char* info,
665 Variable* var,
666 Handle<Object> value) {
667 if (var == NULL) {
668 PrintLiteralIndented(info, value, true);
669 } else {
670 EmbeddedVector<char, 256> buf;
671 int pos = SNPrintF(buf, "%s (mode = %s", info,
672 Variable::Mode2String(var->mode()));
673 SNPrintF(buf + pos, ")");
674 PrintLiteralIndented(buf.start(), value, true);
675 }
676 }
677
678
PrintLabelsIndented(ZoneStringList * labels)679 void AstPrinter::PrintLabelsIndented(ZoneStringList* labels) {
680 if (labels == NULL || labels->length() == 0) return;
681 PrintIndented("LABELS ");
682 PrintLabels(labels);
683 Print("\n");
684 }
685
686
PrintIndentedVisit(const char * s,AstNode * node)687 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
688 IndentedScope indent(this, s);
689 Visit(node);
690 }
691
692
PrintProgram(FunctionLiteral * program)693 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
694 Init();
695 { IndentedScope indent(this, "FUNC");
696 PrintLiteralIndented("NAME", program->name(), true);
697 PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
698 PrintParameters(program->scope());
699 PrintDeclarations(program->scope()->declarations());
700 PrintStatements(program->body());
701 }
702 return Output();
703 }
704
705
PrintDeclarations(ZoneList<Declaration * > * declarations)706 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
707 if (declarations->length() > 0) {
708 IndentedScope indent(this, "DECLS");
709 for (int i = 0; i < declarations->length(); i++) {
710 Visit(declarations->at(i));
711 }
712 }
713 }
714
715
PrintParameters(Scope * scope)716 void AstPrinter::PrintParameters(Scope* scope) {
717 if (scope->num_parameters() > 0) {
718 IndentedScope indent(this, "PARAMS");
719 for (int i = 0; i < scope->num_parameters(); i++) {
720 PrintLiteralWithModeIndented("VAR", scope->parameter(i),
721 scope->parameter(i)->name());
722 }
723 }
724 }
725
726
PrintStatements(ZoneList<Statement * > * statements)727 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
728 for (int i = 0; i < statements->length(); i++) {
729 Visit(statements->at(i));
730 }
731 }
732
733
PrintArguments(ZoneList<Expression * > * arguments)734 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
735 for (int i = 0; i < arguments->length(); i++) {
736 Visit(arguments->at(i));
737 }
738 }
739
740
VisitBlock(Block * node)741 void AstPrinter::VisitBlock(Block* node) {
742 const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
743 IndentedScope indent(this, block_txt);
744 PrintStatements(node->statements());
745 }
746
747
748 // TODO(svenpanne) Start with IndentedScope.
VisitVariableDeclaration(VariableDeclaration * node)749 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
750 PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
751 node->proxy()->var(),
752 node->proxy()->name());
753 }
754
755
756 // TODO(svenpanne) Start with IndentedScope.
VisitFunctionDeclaration(FunctionDeclaration * node)757 void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
758 PrintIndented("FUNCTION ");
759 PrintLiteral(node->proxy()->name(), true);
760 Print(" = function ");
761 PrintLiteral(node->fun()->name(), false);
762 Print("\n");
763 }
764
765
VisitModuleDeclaration(ModuleDeclaration * node)766 void AstPrinter::VisitModuleDeclaration(ModuleDeclaration* node) {
767 IndentedScope indent(this, "MODULE");
768 PrintLiteralIndented("NAME", node->proxy()->name(), true);
769 Visit(node->module());
770 }
771
772
VisitImportDeclaration(ImportDeclaration * node)773 void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
774 IndentedScope indent(this, "IMPORT");
775 PrintLiteralIndented("NAME", node->proxy()->name(), true);
776 Visit(node->module());
777 }
778
779
VisitExportDeclaration(ExportDeclaration * node)780 void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
781 IndentedScope indent(this, "EXPORT ");
782 PrintLiteral(node->proxy()->name(), true);
783 }
784
785
VisitModuleLiteral(ModuleLiteral * node)786 void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) {
787 IndentedScope indent(this, "MODULE LITERAL");
788 VisitBlock(node->body());
789 }
790
791
VisitModuleVariable(ModuleVariable * node)792 void AstPrinter::VisitModuleVariable(ModuleVariable* node) {
793 IndentedScope indent(this, "MODULE VARIABLE");
794 Visit(node->proxy());
795 }
796
797
VisitModulePath(ModulePath * node)798 void AstPrinter::VisitModulePath(ModulePath* node) {
799 IndentedScope indent(this, "MODULE PATH");
800 PrintIndentedVisit("MODULE PATH PARENT", node->module());
801 PrintLiteralIndented("NAME", node->name(), true);
802 }
803
804
VisitModuleUrl(ModuleUrl * node)805 void AstPrinter::VisitModuleUrl(ModuleUrl* node) {
806 PrintLiteralIndented("URL", node->url(), true);
807 }
808
809
VisitModuleStatement(ModuleStatement * node)810 void AstPrinter::VisitModuleStatement(ModuleStatement* node) {
811 IndentedScope indent(this, "MODULE STATEMENT");
812 PrintLiteralIndented("NAME", node->proxy()->name(), true);
813 PrintStatements(node->body()->statements());
814 }
815
816
VisitExpressionStatement(ExpressionStatement * node)817 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
818 IndentedScope indent(this, "EXPRESSION STATEMENT");
819 Visit(node->expression());
820 }
821
822
VisitEmptyStatement(EmptyStatement * node)823 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
824 IndentedScope indent(this, "EMPTY");
825 }
826
827
VisitIfStatement(IfStatement * node)828 void AstPrinter::VisitIfStatement(IfStatement* node) {
829 IndentedScope indent(this, "IF");
830 PrintIndentedVisit("CONDITION", node->condition());
831 PrintIndentedVisit("THEN", node->then_statement());
832 if (node->HasElseStatement()) {
833 PrintIndentedVisit("ELSE", node->else_statement());
834 }
835 }
836
837
VisitContinueStatement(ContinueStatement * node)838 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
839 IndentedScope indent(this, "CONTINUE");
840 PrintLabelsIndented(node->target()->labels());
841 }
842
843
VisitBreakStatement(BreakStatement * node)844 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
845 IndentedScope indent(this, "BREAK");
846 PrintLabelsIndented(node->target()->labels());
847 }
848
849
VisitReturnStatement(ReturnStatement * node)850 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
851 IndentedScope indent(this, "RETURN");
852 Visit(node->expression());
853 }
854
855
VisitWithStatement(WithStatement * node)856 void AstPrinter::VisitWithStatement(WithStatement* node) {
857 IndentedScope indent(this, "WITH");
858 PrintIndentedVisit("OBJECT", node->expression());
859 PrintIndentedVisit("BODY", node->statement());
860 }
861
862
VisitSwitchStatement(SwitchStatement * node)863 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
864 IndentedScope indent(this, "SWITCH");
865 PrintLabelsIndented(node->labels());
866 PrintIndentedVisit("TAG", node->tag());
867 for (int i = 0; i < node->cases()->length(); i++) {
868 Visit(node->cases()->at(i));
869 }
870 }
871
872
VisitCaseClause(CaseClause * clause)873 void AstPrinter::VisitCaseClause(CaseClause* clause) {
874 if (clause->is_default()) {
875 IndentedScope indent(this, "DEFAULT");
876 PrintStatements(clause->statements());
877 } else {
878 IndentedScope indent(this, "CASE");
879 Visit(clause->label());
880 PrintStatements(clause->statements());
881 }
882 }
883
884
VisitDoWhileStatement(DoWhileStatement * node)885 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
886 IndentedScope indent(this, "DO");
887 PrintLabelsIndented(node->labels());
888 PrintIndentedVisit("BODY", node->body());
889 PrintIndentedVisit("COND", node->cond());
890 }
891
892
VisitWhileStatement(WhileStatement * node)893 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
894 IndentedScope indent(this, "WHILE");
895 PrintLabelsIndented(node->labels());
896 PrintIndentedVisit("COND", node->cond());
897 PrintIndentedVisit("BODY", node->body());
898 }
899
900
VisitForStatement(ForStatement * node)901 void AstPrinter::VisitForStatement(ForStatement* node) {
902 IndentedScope indent(this, "FOR");
903 PrintLabelsIndented(node->labels());
904 if (node->init()) PrintIndentedVisit("INIT", node->init());
905 if (node->cond()) PrintIndentedVisit("COND", node->cond());
906 PrintIndentedVisit("BODY", node->body());
907 if (node->next()) PrintIndentedVisit("NEXT", node->next());
908 }
909
910
VisitForInStatement(ForInStatement * node)911 void AstPrinter::VisitForInStatement(ForInStatement* node) {
912 IndentedScope indent(this, "FOR IN");
913 PrintIndentedVisit("FOR", node->each());
914 PrintIndentedVisit("IN", node->enumerable());
915 PrintIndentedVisit("BODY", node->body());
916 }
917
918
VisitForOfStatement(ForOfStatement * node)919 void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
920 IndentedScope indent(this, "FOR OF");
921 PrintIndentedVisit("FOR", node->each());
922 PrintIndentedVisit("OF", node->iterable());
923 PrintIndentedVisit("BODY", node->body());
924 }
925
926
VisitTryCatchStatement(TryCatchStatement * node)927 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
928 IndentedScope indent(this, "TRY CATCH");
929 PrintIndentedVisit("TRY", node->try_block());
930 PrintLiteralWithModeIndented("CATCHVAR",
931 node->variable(),
932 node->variable()->name());
933 PrintIndentedVisit("CATCH", node->catch_block());
934 }
935
936
VisitTryFinallyStatement(TryFinallyStatement * node)937 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
938 IndentedScope indent(this, "TRY FINALLY");
939 PrintIndentedVisit("TRY", node->try_block());
940 PrintIndentedVisit("FINALLY", node->finally_block());
941 }
942
943
VisitDebuggerStatement(DebuggerStatement * node)944 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
945 IndentedScope indent(this, "DEBUGGER");
946 }
947
948
VisitFunctionLiteral(FunctionLiteral * node)949 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
950 IndentedScope indent(this, "FUNC LITERAL");
951 PrintLiteralIndented("NAME", node->name(), false);
952 PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
953 PrintParameters(node->scope());
954 // We don't want to see the function literal in this case: it
955 // will be printed via PrintProgram when the code for it is
956 // generated.
957 // PrintStatements(node->body());
958 }
959
960
VisitNativeFunctionLiteral(NativeFunctionLiteral * node)961 void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
962 IndentedScope indent(this, "NATIVE FUNC LITERAL");
963 PrintLiteralIndented("NAME", node->name(), false);
964 }
965
966
VisitConditional(Conditional * node)967 void AstPrinter::VisitConditional(Conditional* node) {
968 IndentedScope indent(this, "CONDITIONAL");
969 PrintIndentedVisit("CONDITION", node->condition());
970 PrintIndentedVisit("THEN", node->then_expression());
971 PrintIndentedVisit("ELSE", node->else_expression());
972 }
973
974
975 // TODO(svenpanne) Start with IndentedScope.
VisitLiteral(Literal * node)976 void AstPrinter::VisitLiteral(Literal* node) {
977 PrintLiteralIndented("LITERAL", node->value(), true);
978 }
979
980
VisitRegExpLiteral(RegExpLiteral * node)981 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
982 IndentedScope indent(this, "REGEXP LITERAL");
983 PrintLiteralIndented("PATTERN", node->pattern(), false);
984 PrintLiteralIndented("FLAGS", node->flags(), false);
985 }
986
987
VisitObjectLiteral(ObjectLiteral * node)988 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
989 IndentedScope indent(this, "OBJ LITERAL");
990 for (int i = 0; i < node->properties()->length(); i++) {
991 const char* prop_kind = NULL;
992 switch (node->properties()->at(i)->kind()) {
993 case ObjectLiteral::Property::CONSTANT:
994 prop_kind = "PROPERTY - CONSTANT";
995 break;
996 case ObjectLiteral::Property::COMPUTED:
997 prop_kind = "PROPERTY - COMPUTED";
998 break;
999 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1000 prop_kind = "PROPERTY - MATERIALIZED_LITERAL";
1001 break;
1002 case ObjectLiteral::Property::PROTOTYPE:
1003 prop_kind = "PROPERTY - PROTOTYPE";
1004 break;
1005 case ObjectLiteral::Property::GETTER:
1006 prop_kind = "PROPERTY - GETTER";
1007 break;
1008 case ObjectLiteral::Property::SETTER:
1009 prop_kind = "PROPERTY - SETTER";
1010 break;
1011 default:
1012 UNREACHABLE();
1013 }
1014 IndentedScope prop(this, prop_kind);
1015 PrintIndentedVisit("KEY", node->properties()->at(i)->key());
1016 PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
1017 }
1018 }
1019
1020
VisitArrayLiteral(ArrayLiteral * node)1021 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
1022 IndentedScope indent(this, "ARRAY LITERAL");
1023 if (node->values()->length() > 0) {
1024 IndentedScope indent(this, "VALUES");
1025 for (int i = 0; i < node->values()->length(); i++) {
1026 Visit(node->values()->at(i));
1027 }
1028 }
1029 }
1030
1031
1032 // TODO(svenpanne) Start with IndentedScope.
VisitVariableProxy(VariableProxy * node)1033 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
1034 Variable* var = node->var();
1035 EmbeddedVector<char, 128> buf;
1036 int pos = SNPrintF(buf, "VAR PROXY");
1037 switch (var->location()) {
1038 case Variable::UNALLOCATED:
1039 break;
1040 case Variable::PARAMETER:
1041 SNPrintF(buf + pos, " parameter[%d]", var->index());
1042 break;
1043 case Variable::LOCAL:
1044 SNPrintF(buf + pos, " local[%d]", var->index());
1045 break;
1046 case Variable::CONTEXT:
1047 SNPrintF(buf + pos, " context[%d]", var->index());
1048 break;
1049 case Variable::LOOKUP:
1050 SNPrintF(buf + pos, " lookup");
1051 break;
1052 }
1053 PrintLiteralWithModeIndented(buf.start(), var, node->name());
1054 }
1055
1056
VisitAssignment(Assignment * node)1057 void AstPrinter::VisitAssignment(Assignment* node) {
1058 IndentedScope indent(this, Token::Name(node->op()));
1059 Visit(node->target());
1060 Visit(node->value());
1061 }
1062
1063
VisitYield(Yield * node)1064 void AstPrinter::VisitYield(Yield* node) {
1065 IndentedScope indent(this, "YIELD");
1066 Visit(node->expression());
1067 }
1068
1069
VisitThrow(Throw * node)1070 void AstPrinter::VisitThrow(Throw* node) {
1071 IndentedScope indent(this, "THROW");
1072 Visit(node->exception());
1073 }
1074
1075
VisitProperty(Property * node)1076 void AstPrinter::VisitProperty(Property* node) {
1077 IndentedScope indent(this, "PROPERTY");
1078 Visit(node->obj());
1079 Literal* literal = node->key()->AsLiteral();
1080 if (literal != NULL && literal->value()->IsInternalizedString()) {
1081 PrintLiteralIndented("NAME", literal->value(), false);
1082 } else {
1083 PrintIndentedVisit("KEY", node->key());
1084 }
1085 }
1086
1087
VisitCall(Call * node)1088 void AstPrinter::VisitCall(Call* node) {
1089 IndentedScope indent(this, "CALL");
1090 Visit(node->expression());
1091 PrintArguments(node->arguments());
1092 }
1093
1094
VisitCallNew(CallNew * node)1095 void AstPrinter::VisitCallNew(CallNew* node) {
1096 IndentedScope indent(this, "CALL NEW");
1097 Visit(node->expression());
1098 PrintArguments(node->arguments());
1099 }
1100
1101
VisitCallRuntime(CallRuntime * node)1102 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1103 IndentedScope indent(this, "CALL RUNTIME");
1104 PrintLiteralIndented("NAME", node->name(), false);
1105 PrintArguments(node->arguments());
1106 }
1107
1108
VisitUnaryOperation(UnaryOperation * node)1109 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1110 IndentedScope indent(this, Token::Name(node->op()));
1111 Visit(node->expression());
1112 }
1113
1114
VisitCountOperation(CountOperation * node)1115 void AstPrinter::VisitCountOperation(CountOperation* node) {
1116 EmbeddedVector<char, 128> buf;
1117 SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1118 Token::Name(node->op()));
1119 IndentedScope indent(this, buf.start());
1120 Visit(node->expression());
1121 }
1122
1123
VisitBinaryOperation(BinaryOperation * node)1124 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1125 IndentedScope indent(this, Token::Name(node->op()));
1126 Visit(node->left());
1127 Visit(node->right());
1128 }
1129
1130
VisitCompareOperation(CompareOperation * node)1131 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1132 IndentedScope indent(this, Token::Name(node->op()));
1133 Visit(node->left());
1134 Visit(node->right());
1135 }
1136
1137
VisitThisFunction(ThisFunction * node)1138 void AstPrinter::VisitThisFunction(ThisFunction* node) {
1139 IndentedScope indent(this, "THIS-FUNCTION");
1140 }
1141
1142 #endif // DEBUG
1143
1144 } } // namespace v8::internal
1145