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