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