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