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