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