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