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