Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/ast/prettyprinter.h"
6 :
7 : #include <stdarg.h>
8 :
9 : #include "src/ast/ast-value-factory.h"
10 : #include "src/ast/scopes.h"
11 : #include "src/base/platform/platform.h"
12 : #include "src/globals.h"
13 : #include "src/objects-inl.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 :
18 7060 : CallPrinter::CallPrinter(Isolate* isolate, bool is_user_js)
19 7060 : : builder_(isolate) {
20 7060 : isolate_ = isolate;
21 7060 : position_ = 0;
22 7060 : num_prints_ = 0;
23 7060 : found_ = false;
24 7060 : done_ = false;
25 7060 : is_call_error_ = false;
26 7060 : is_iterator_error_ = false;
27 7060 : is_async_iterator_error_ = false;
28 7060 : is_user_js_ = is_user_js;
29 : InitializeAstVisitor(isolate);
30 7060 : }
31 :
32 7060 : CallPrinter::ErrorHint CallPrinter::GetErrorHint() const {
33 7060 : if (is_call_error_) {
34 5827 : if (is_iterator_error_) return ErrorHint::kCallAndNormalIterator;
35 5728 : if (is_async_iterator_error_) return ErrorHint::kCallAndAsyncIterator;
36 : } else {
37 1233 : if (is_iterator_error_) return ErrorHint::kNormalIterator;
38 1060 : if (is_async_iterator_error_) return ErrorHint::kAsyncIterator;
39 : }
40 6779 : return ErrorHint::kNone;
41 : }
42 :
43 7060 : Handle<String> CallPrinter::Print(FunctionLiteral* program, int position) {
44 7060 : num_prints_ = 0;
45 7060 : position_ = position;
46 7060 : Find(program);
47 14120 : return builder_.Finish().ToHandleChecked();
48 : }
49 :
50 :
51 437542 : void CallPrinter::Find(AstNode* node, bool print) {
52 437542 : if (found_) {
53 14047 : if (print) {
54 12218 : int prev_num_prints = num_prints_;
55 12218 : Visit(node);
56 449760 : if (prev_num_prints != num_prints_) return;
57 : }
58 2093 : Print("(intermediate value)");
59 : } else {
60 423495 : Visit(node);
61 : }
62 : }
63 :
64 233364 : void CallPrinter::Print(const char* str) {
65 466728 : if (!found_ || done_) return;
66 9358 : num_prints_++;
67 9358 : builder_.AppendCString(str);
68 : }
69 :
70 175325 : void CallPrinter::Print(Handle<String> str) {
71 350650 : if (!found_ || done_) return;
72 9501 : num_prints_++;
73 9501 : builder_.AppendString(str);
74 : }
75 :
76 0 : void CallPrinter::VisitBlock(Block* node) {
77 38563 : FindStatements(node->statements());
78 0 : }
79 :
80 :
81 0 : void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {}
82 :
83 :
84 0 : void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {}
85 :
86 :
87 50575 : void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) {
88 50575 : Find(node->expression());
89 50575 : }
90 :
91 :
92 0 : void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {}
93 :
94 :
95 36 : void CallPrinter::VisitSloppyBlockFunctionStatement(
96 36 : SloppyBlockFunctionStatement* node) {
97 36 : Find(node->statement());
98 36 : }
99 :
100 :
101 33772 : void CallPrinter::VisitIfStatement(IfStatement* node) {
102 12915 : Find(node->condition());
103 12915 : Find(node->then_statement());
104 12915 : if (node->HasElseStatement()) {
105 7942 : Find(node->else_statement());
106 : }
107 12915 : }
108 :
109 :
110 0 : void CallPrinter::VisitContinueStatement(ContinueStatement* node) {}
111 :
112 :
113 0 : void CallPrinter::VisitBreakStatement(BreakStatement* node) {}
114 :
115 :
116 3307 : void CallPrinter::VisitReturnStatement(ReturnStatement* node) {
117 3307 : Find(node->expression());
118 3307 : }
119 :
120 :
121 18 : void CallPrinter::VisitWithStatement(WithStatement* node) {
122 9 : Find(node->expression());
123 9 : Find(node->statement());
124 9 : }
125 :
126 :
127 19 : void CallPrinter::VisitSwitchStatement(SwitchStatement* node) {
128 19 : Find(node->tag());
129 94 : for (CaseClause* clause : *node->cases()) {
130 28 : if (!clause->is_default()) Find(clause->label());
131 28 : FindStatements(clause->statements());
132 : }
133 19 : }
134 :
135 :
136 18 : void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
137 9 : Find(node->body());
138 9 : Find(node->cond());
139 9 : }
140 :
141 :
142 135 : void CallPrinter::VisitWhileStatement(WhileStatement* node) {
143 135 : Find(node->cond());
144 135 : Find(node->body());
145 135 : }
146 :
147 :
148 840 : void CallPrinter::VisitForStatement(ForStatement* node) {
149 280 : if (node->init() != nullptr) {
150 280 : Find(node->init());
151 : }
152 280 : if (node->cond() != nullptr) Find(node->cond());
153 280 : if (node->next() != nullptr) Find(node->next());
154 280 : Find(node->body());
155 280 : }
156 :
157 :
158 30 : void CallPrinter::VisitForInStatement(ForInStatement* node) {
159 30 : Find(node->each());
160 30 : Find(node->enumerable());
161 30 : Find(node->body());
162 30 : }
163 :
164 :
165 4428 : void CallPrinter::VisitForOfStatement(ForOfStatement* node) {
166 1107 : Find(node->assign_iterator());
167 1107 : Find(node->next_result());
168 1107 : Find(node->result_done());
169 1107 : Find(node->assign_each());
170 1107 : Find(node->body());
171 1107 : }
172 :
173 :
174 11800 : void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
175 5900 : Find(node->try_block());
176 5900 : Find(node->catch_block());
177 5900 : }
178 :
179 :
180 3780 : void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
181 1890 : Find(node->try_block());
182 1890 : Find(node->finally_block());
183 1890 : }
184 :
185 :
186 0 : void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {}
187 :
188 :
189 7409 : void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
190 7409 : FindStatements(node->body());
191 0 : }
192 :
193 :
194 4347 : void CallPrinter::VisitClassLiteral(ClassLiteral* node) {
195 1449 : if (node->extends()) Find(node->extends());
196 4347 : for (int i = 0; i < node->properties()->length(); i++) {
197 1449 : Find(node->properties()->at(i)->value());
198 : }
199 1449 : }
200 :
201 :
202 0 : void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
203 :
204 :
205 157 : void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); }
206 :
207 :
208 756 : void CallPrinter::VisitConditional(Conditional* node) {
209 252 : Find(node->condition());
210 252 : Find(node->then_expression());
211 252 : Find(node->else_expression());
212 252 : }
213 :
214 :
215 39920 : void CallPrinter::VisitLiteral(Literal* node) {
216 39920 : PrintLiteral(node->value(), true);
217 39920 : }
218 :
219 :
220 1925 : void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
221 275 : Print("/");
222 275 : PrintLiteral(node->pattern(), false);
223 275 : Print("/");
224 275 : if (node->flags() & RegExp::kGlobal) Print("g");
225 275 : if (node->flags() & RegExp::kIgnoreCase) Print("i");
226 275 : if (node->flags() & RegExp::kMultiline) Print("m");
227 275 : if (node->flags() & RegExp::kUnicode) Print("u");
228 275 : if (node->flags() & RegExp::kSticky) Print("y");
229 275 : }
230 :
231 :
232 9694 : void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) {
233 2781 : Print("{");
234 13826 : for (int i = 0; i < node->properties()->length(); i++) {
235 4132 : Find(node->properties()->at(i)->value());
236 : }
237 2781 : Print("}");
238 2781 : }
239 :
240 :
241 21246 : void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) {
242 1153 : Print("[");
243 21246 : for (int i = 0; i < node->values()->length(); i++) {
244 9470 : if (i != 0) Print(",");
245 9470 : Find(node->values()->at(i), true);
246 : }
247 1153 : Print("]");
248 1153 : }
249 :
250 :
251 121088 : void CallPrinter::VisitVariableProxy(VariableProxy* node) {
252 121088 : if (is_user_js_) {
253 106561 : PrintLiteral(node->name(), false);
254 : } else {
255 : // Variable names of non-user code are meaningless due to minification.
256 14527 : Print("(var)");
257 : }
258 121088 : }
259 :
260 :
261 58844 : void CallPrinter::VisitAssignment(Assignment* node) {
262 29422 : Find(node->target());
263 29422 : Find(node->value());
264 29422 : }
265 :
266 0 : void CallPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
267 0 : VisitAssignment(node);
268 0 : }
269 :
270 190 : void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
271 :
272 54 : void CallPrinter::VisitYieldStar(YieldStar* node) { Find(node->expression()); }
273 :
274 99 : void CallPrinter::VisitAwait(Await* node) { Find(node->expression()); }
275 :
276 2640 : void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); }
277 :
278 :
279 81124 : void CallPrinter::VisitProperty(Property* node) {
280 : Expression* key = node->key();
281 120212 : Literal* literal = key->AsLiteral();
282 80657 : if (literal != nullptr && literal->value()->IsInternalizedString()) {
283 39555 : Find(node->obj(), true);
284 39555 : Print(".");
285 39555 : PrintLiteral(literal->value(), false);
286 : } else {
287 1007 : Find(node->obj(), true);
288 1007 : Print("[");
289 1007 : Find(key, true);
290 1007 : Print("]");
291 : }
292 40562 : }
293 :
294 :
295 65787 : void CallPrinter::VisitCall(Call* node) {
296 : bool was_found = false;
297 21929 : if (node->position() == position_) {
298 3948 : is_call_error_ = true;
299 3948 : was_found = !found_;
300 : }
301 21929 : if (was_found) {
302 : // Bail out if the error is caused by a direct call to a variable in
303 : // non-user JS code. The variable name is meaningless due to minification.
304 3849 : if (!is_user_js_ && node->expression()->IsVariableProxy()) {
305 0 : done_ = true;
306 21929 : return;
307 : }
308 3849 : found_ = true;
309 : }
310 21929 : Find(node->expression(), true);
311 21929 : if (!was_found) Print("(...)");
312 21929 : FindArguments(node->arguments());
313 21929 : if (was_found) {
314 3849 : done_ = true;
315 3849 : found_ = false;
316 : }
317 : }
318 :
319 :
320 11793 : void CallPrinter::VisitCallNew(CallNew* node) {
321 : bool was_found = false;
322 3931 : if (node->position() == position_) {
323 1978 : is_call_error_ = true;
324 1978 : was_found = !found_;
325 : }
326 3931 : if (was_found) {
327 : // Bail out if the error is caused by a direct call to a variable in
328 : // non-user JS code. The variable name is meaningless due to minification.
329 1978 : if (!is_user_js_ && node->expression()->IsVariableProxy()) {
330 0 : done_ = true;
331 3931 : return;
332 : }
333 1978 : found_ = true;
334 : }
335 7862 : Find(node->expression(), was_found);
336 3931 : FindArguments(node->arguments());
337 3931 : if (was_found) {
338 1978 : done_ = true;
339 1978 : found_ = false;
340 : }
341 : }
342 :
343 :
344 15961 : void CallPrinter::VisitCallRuntime(CallRuntime* node) {
345 15961 : FindArguments(node->arguments());
346 15961 : }
347 :
348 :
349 15306 : void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
350 : Token::Value op = node->op();
351 : bool needsSpace =
352 7653 : op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
353 7653 : Print("(");
354 7653 : Print(Token::String(op));
355 7653 : if (needsSpace) Print(" ");
356 7653 : Find(node->expression(), true);
357 7653 : Print(")");
358 7653 : }
359 :
360 :
361 897 : void CallPrinter::VisitCountOperation(CountOperation* node) {
362 299 : Print("(");
363 308 : if (node->is_prefix()) Print(Token::String(node->op()));
364 299 : Find(node->expression(), true);
365 589 : if (node->is_postfix()) Print(Token::String(node->op()));
366 299 : Print(")");
367 299 : }
368 :
369 :
370 19660 : void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
371 4915 : Print("(");
372 4915 : Find(node->left(), true);
373 4915 : Print(" ");
374 4915 : Print(Token::String(node->op()));
375 4915 : Print(" ");
376 4915 : Find(node->right(), true);
377 4915 : Print(")");
378 4915 : }
379 :
380 :
381 45980 : void CallPrinter::VisitCompareOperation(CompareOperation* node) {
382 11495 : Print("(");
383 11495 : Find(node->left(), true);
384 11495 : Print(" ");
385 11495 : Print(Token::String(node->op()));
386 11495 : Print(" ");
387 11495 : Find(node->right(), true);
388 11495 : Print(")");
389 11495 : }
390 :
391 :
392 0 : void CallPrinter::VisitSpread(Spread* node) {
393 0 : Print("(...");
394 0 : Find(node->expression(), true);
395 0 : Print(")");
396 0 : }
397 :
398 :
399 0 : void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
400 0 : UNREACHABLE();
401 : }
402 :
403 3807 : void CallPrinter::VisitGetIterator(GetIterator* node) {
404 : bool was_found = false;
405 1763 : if (node->position() == position_) {
406 281 : is_async_iterator_error_ = node->hint() == IteratorType::kAsync;
407 281 : is_iterator_error_ = !is_async_iterator_error_;
408 281 : was_found = !found_;
409 281 : if (was_found) {
410 281 : found_ = true;
411 : }
412 : }
413 1763 : Find(node->iterable_for_call_printer(), true);
414 1763 : if (was_found) {
415 281 : done_ = true;
416 281 : found_ = false;
417 : }
418 1763 : }
419 :
420 0 : void CallPrinter::VisitGetTemplateObject(GetTemplateObject* node) {}
421 :
422 0 : void CallPrinter::VisitImportCallExpression(ImportCallExpression* node) {
423 0 : Print("ImportCall(");
424 0 : Find(node->argument(), true);
425 0 : Print(")");
426 0 : }
427 :
428 0 : void CallPrinter::VisitThisFunction(ThisFunction* node) {}
429 :
430 :
431 0 : void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
432 :
433 :
434 0 : void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
435 10 : Print("super");
436 0 : }
437 :
438 :
439 157 : void CallPrinter::VisitRewritableExpression(RewritableExpression* node) {
440 157 : Find(node->expression());
441 157 : }
442 :
443 :
444 173103 : void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {
445 92000 : if (statements == nullptr) return;
446 208444 : for (int i = 0; i < statements->length(); i++) {
447 81341 : Find(statements->at(i));
448 : }
449 : }
450 :
451 :
452 128420 : void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) {
453 83642 : if (found_) return;
454 137460 : for (int i = 0; i < arguments->length(); i++) {
455 50861 : Find(arguments->at(i));
456 : }
457 : }
458 :
459 186311 : void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) {
460 186311 : if (value->IsString()) {
461 156297 : if (quote) Print("\"");
462 156297 : Print(Handle<String>::cast(value));
463 156297 : if (quote) Print("\"");
464 60028 : } else if (value->IsNull(isolate_)) {
465 2781 : Print("null");
466 54466 : } else if (value->IsTrue(isolate_)) {
467 3083 : Print("true");
468 48300 : } else if (value->IsFalse(isolate_)) {
469 4352 : Print("false");
470 39596 : } else if (value->IsUndefined(isolate_)) {
471 752 : Print("undefined");
472 19046 : } else if (value->IsNumber()) {
473 19028 : Print(isolate_->factory()->NumberToString(value));
474 18 : } else if (value->IsSymbol()) {
475 : // Symbols can only occur as literals if they were inserted by the parser.
476 0 : PrintLiteral(handle(Handle<Symbol>::cast(value)->name(), isolate_), false);
477 : }
478 186311 : }
479 :
480 :
481 0 : void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
482 0 : PrintLiteral(value->string(), quote);
483 0 : }
484 :
485 :
486 : //-----------------------------------------------------------------------------
487 :
488 :
489 : #ifdef DEBUG
490 :
491 : const char* AstPrinter::Print(AstNode* node) {
492 : Init();
493 : Visit(node);
494 : return output_;
495 : }
496 :
497 : void AstPrinter::Init() {
498 : if (size_ == 0) {
499 : DCHECK_NULL(output_);
500 : const int initial_size = 256;
501 : output_ = NewArray<char>(initial_size);
502 : size_ = initial_size;
503 : }
504 : output_[0] = '\0';
505 : pos_ = 0;
506 : }
507 :
508 : void AstPrinter::Print(const char* format, ...) {
509 : for (;;) {
510 : va_list arguments;
511 : va_start(arguments, format);
512 : int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
513 : format,
514 : arguments);
515 : va_end(arguments);
516 :
517 : if (n >= 0) {
518 : // there was enough space - we are done
519 : pos_ += n;
520 : return;
521 : } else {
522 : // there was not enough space - allocate more and try again
523 : const int slack = 32;
524 : int new_size = size_ + (size_ >> 1) + slack;
525 : char* new_output = NewArray<char>(new_size);
526 : MemCopy(new_output, output_, pos_);
527 : DeleteArray(output_);
528 : output_ = new_output;
529 : size_ = new_size;
530 : }
531 : }
532 : }
533 :
534 : void AstPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) {
535 : if (labels != nullptr) {
536 : for (int i = 0; i < labels->length(); i++) {
537 : PrintLiteral(labels->at(i), false);
538 : Print(": ");
539 : }
540 : }
541 : }
542 :
543 : void AstPrinter::PrintLiteral(MaybeHandle<Object> maybe_value, bool quote) {
544 : Handle<Object> value;
545 : if (!maybe_value.ToHandle(&value)) {
546 : Print("<nil>");
547 : return;
548 : }
549 : Object* object = *value;
550 : if (object->IsString()) {
551 : String* string = String::cast(object);
552 : if (quote) Print("\"");
553 : for (int i = 0; i < string->length(); i++) {
554 : Print("%c", string->Get(i));
555 : }
556 : if (quote) Print("\"");
557 : } else if (object->IsNull(isolate_)) {
558 : Print("null");
559 : } else if (object->IsTrue(isolate_)) {
560 : Print("true");
561 : } else if (object->IsFalse(isolate_)) {
562 : Print("false");
563 : } else if (object->IsUndefined(isolate_)) {
564 : Print("undefined");
565 : } else if (object->IsNumber()) {
566 : Print("%g", object->Number());
567 : } else if (object->IsJSObject()) {
568 : // regular expression
569 : if (object->IsJSFunction()) {
570 : Print("JS-Function");
571 : } else if (object->IsJSArray()) {
572 : Print("JS-array[%u]", Smi::ToInt(JSArray::cast(object)->length()));
573 : } else if (object->IsJSObject()) {
574 : Print("JS-Object");
575 : } else {
576 : Print("?UNKNOWN?");
577 : }
578 : } else if (object->IsFixedArray()) {
579 : Print("FixedArray");
580 : } else if (object->IsSymbol()) {
581 : // Symbols can only occur as literals if they were inserted by the parser.
582 : Symbol* symbol = Symbol::cast(object);
583 : if (symbol->name()->IsString()) {
584 : int length = 0;
585 : String* string = String::cast(symbol->name());
586 : std::unique_ptr<char[]> desc = string->ToCString(
587 : ALLOW_NULLS, FAST_STRING_TRAVERSAL, 0, string->length(), &length);
588 : Print("Symbol(%*s)", length, desc.get());
589 : } else {
590 : Print("Symbol()");
591 : }
592 : } else {
593 : Print("<unknown literal %p>", static_cast<void*>(object));
594 : }
595 : }
596 :
597 : void AstPrinter::PrintLiteral(const AstRawString* value, bool quote) {
598 : PrintLiteral(value->string(), quote);
599 : }
600 :
601 :
602 : //-----------------------------------------------------------------------------
603 :
604 : class IndentedScope BASE_EMBEDDED {
605 : public:
606 : IndentedScope(AstPrinter* printer, const char* txt)
607 : : ast_printer_(printer) {
608 : ast_printer_->PrintIndented(txt);
609 : ast_printer_->Print("\n");
610 : ast_printer_->inc_indent();
611 : }
612 :
613 : IndentedScope(AstPrinter* printer, const char* txt, int pos)
614 : : ast_printer_(printer) {
615 : ast_printer_->PrintIndented(txt);
616 : ast_printer_->Print(" at %d\n", pos);
617 : ast_printer_->inc_indent();
618 : }
619 :
620 : virtual ~IndentedScope() {
621 : ast_printer_->dec_indent();
622 : }
623 :
624 : private:
625 : AstPrinter* ast_printer_;
626 : };
627 :
628 :
629 : //-----------------------------------------------------------------------------
630 :
631 : AstPrinter::AstPrinter(Isolate* isolate)
632 : : isolate_(isolate), output_(nullptr), size_(0), pos_(0), indent_(0) {
633 : InitializeAstVisitor(isolate);
634 : }
635 :
636 : AstPrinter::~AstPrinter() {
637 : DCHECK_EQ(indent_, 0);
638 : DeleteArray(output_);
639 : }
640 :
641 :
642 : void AstPrinter::PrintIndented(const char* txt) {
643 : for (int i = 0; i < indent_; i++) {
644 : Print(". ");
645 : }
646 : Print("%s", txt);
647 : }
648 :
649 : void AstPrinter::PrintLiteralIndented(const char* info,
650 : MaybeHandle<Object> maybe_value,
651 : bool quote) {
652 : PrintIndented(info);
653 : Print(" ");
654 : PrintLiteral(maybe_value, quote);
655 : Print("\n");
656 : }
657 :
658 :
659 : void AstPrinter::PrintLiteralWithModeIndented(const char* info,
660 : Variable* var,
661 : Handle<Object> value) {
662 : if (var == nullptr) {
663 : PrintLiteralIndented(info, value, true);
664 : } else {
665 : EmbeddedVector<char, 256> buf;
666 : int pos =
667 : SNPrintF(buf, "%s (%p) (mode = %s", info, reinterpret_cast<void*>(var),
668 : VariableMode2String(var->mode()));
669 : SNPrintF(buf + pos, ")");
670 : PrintLiteralIndented(buf.start(), value, true);
671 : }
672 : }
673 :
674 :
675 : void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) {
676 : if (labels == nullptr || labels->length() == 0) return;
677 : PrintIndented("LABELS ");
678 : PrintLabels(labels);
679 : Print("\n");
680 : }
681 :
682 :
683 : void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
684 : IndentedScope indent(this, s, node->position());
685 : Visit(node);
686 : }
687 :
688 :
689 : const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
690 : Init();
691 : { IndentedScope indent(this, "FUNC", program->position());
692 : PrintIndented("KIND");
693 : Print(" %d\n", program->kind());
694 : PrintIndented("SUSPEND COUNT");
695 : Print(" %d\n", program->suspend_count());
696 : PrintLiteralIndented("NAME", program->name(), true);
697 : PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
698 : PrintParameters(program->scope());
699 : PrintDeclarations(program->scope()->declarations());
700 : PrintStatements(program->body());
701 : }
702 : return output_;
703 : }
704 :
705 :
706 : void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) {
707 : AstPrinter printer(isolate);
708 : printer.Init();
709 : printer.Visit(node);
710 : PrintF("%s", printer.output_);
711 : }
712 :
713 : void AstPrinter::PrintDeclarations(Declaration::List* declarations) {
714 : if (!declarations->is_empty()) {
715 : IndentedScope indent(this, "DECLS");
716 : for (Declaration* decl : *declarations) Visit(decl);
717 : }
718 : }
719 :
720 : void AstPrinter::PrintParameters(DeclarationScope* scope) {
721 : if (scope->num_parameters() > 0) {
722 : IndentedScope indent(this, "PARAMS");
723 : for (int i = 0; i < scope->num_parameters(); i++) {
724 : PrintLiteralWithModeIndented("VAR", scope->parameter(i),
725 : scope->parameter(i)->name());
726 : }
727 : }
728 : }
729 :
730 :
731 : void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
732 : for (int i = 0; i < statements->length(); i++) {
733 : Visit(statements->at(i));
734 : }
735 : }
736 :
737 :
738 : void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
739 : for (int i = 0; i < arguments->length(); i++) {
740 : Visit(arguments->at(i));
741 : }
742 : }
743 :
744 :
745 : void AstPrinter::VisitBlock(Block* node) {
746 : const char* block_txt =
747 : node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK";
748 : IndentedScope indent(this, block_txt, node->position());
749 : PrintStatements(node->statements());
750 : }
751 :
752 :
753 : // TODO(svenpanne) Start with IndentedScope.
754 : void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
755 : PrintLiteralWithModeIndented("VARIABLE", node->proxy()->var(),
756 : node->proxy()->name());
757 : }
758 :
759 :
760 : // TODO(svenpanne) Start with IndentedScope.
761 : void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
762 : PrintIndented("FUNCTION ");
763 : PrintLiteral(node->proxy()->name(), true);
764 : Print(" = function ");
765 : PrintLiteral(node->fun()->name(), false);
766 : Print("\n");
767 : }
768 :
769 :
770 : void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
771 : IndentedScope indent(this, "EXPRESSION STATEMENT", node->position());
772 : Visit(node->expression());
773 : }
774 :
775 :
776 : void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
777 : IndentedScope indent(this, "EMPTY", node->position());
778 : }
779 :
780 :
781 : void AstPrinter::VisitSloppyBlockFunctionStatement(
782 : SloppyBlockFunctionStatement* node) {
783 : Visit(node->statement());
784 : }
785 :
786 :
787 : void AstPrinter::VisitIfStatement(IfStatement* node) {
788 : IndentedScope indent(this, "IF", node->position());
789 : PrintIndentedVisit("CONDITION", node->condition());
790 : PrintIndentedVisit("THEN", node->then_statement());
791 : if (node->HasElseStatement()) {
792 : PrintIndentedVisit("ELSE", node->else_statement());
793 : }
794 : }
795 :
796 :
797 : void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
798 : IndentedScope indent(this, "CONTINUE", node->position());
799 : PrintLabelsIndented(node->target()->labels());
800 : }
801 :
802 :
803 : void AstPrinter::VisitBreakStatement(BreakStatement* node) {
804 : IndentedScope indent(this, "BREAK", node->position());
805 : PrintLabelsIndented(node->target()->labels());
806 : }
807 :
808 :
809 : void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
810 : IndentedScope indent(this, "RETURN", node->position());
811 : Visit(node->expression());
812 : }
813 :
814 :
815 : void AstPrinter::VisitWithStatement(WithStatement* node) {
816 : IndentedScope indent(this, "WITH", node->position());
817 : PrintIndentedVisit("OBJECT", node->expression());
818 : PrintIndentedVisit("BODY", node->statement());
819 : }
820 :
821 :
822 : void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
823 : IndentedScope indent(this, "SWITCH", node->position());
824 : PrintLabelsIndented(node->labels());
825 : PrintIndentedVisit("TAG", node->tag());
826 : for (CaseClause* clause : *node->cases()) {
827 : if (clause->is_default()) {
828 : IndentedScope indent(this, "DEFAULT");
829 : PrintStatements(clause->statements());
830 : } else {
831 : IndentedScope indent(this, "CASE");
832 : Visit(clause->label());
833 : PrintStatements(clause->statements());
834 : }
835 : }
836 : }
837 :
838 :
839 : void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
840 : IndentedScope indent(this, "DO", node->position());
841 : PrintIndented("SUSPEND COUNT");
842 : Print(" %d\n", node->suspend_count());
843 : PrintLabelsIndented(node->labels());
844 : PrintIndentedVisit("BODY", node->body());
845 : PrintIndentedVisit("COND", node->cond());
846 : }
847 :
848 :
849 : void AstPrinter::VisitWhileStatement(WhileStatement* node) {
850 : IndentedScope indent(this, "WHILE", node->position());
851 : PrintIndented("SUSPEND COUNT");
852 : Print(" %d\n", node->suspend_count());
853 : PrintLabelsIndented(node->labels());
854 : PrintIndentedVisit("COND", node->cond());
855 : PrintIndentedVisit("BODY", node->body());
856 : }
857 :
858 :
859 : void AstPrinter::VisitForStatement(ForStatement* node) {
860 : IndentedScope indent(this, "FOR", node->position());
861 : PrintIndented("SUSPEND COUNT");
862 : Print(" %d\n", node->suspend_count());
863 : PrintLabelsIndented(node->labels());
864 : if (node->init()) PrintIndentedVisit("INIT", node->init());
865 : if (node->cond()) PrintIndentedVisit("COND", node->cond());
866 : PrintIndentedVisit("BODY", node->body());
867 : if (node->next()) PrintIndentedVisit("NEXT", node->next());
868 : }
869 :
870 :
871 : void AstPrinter::VisitForInStatement(ForInStatement* node) {
872 : IndentedScope indent(this, "FOR IN", node->position());
873 : PrintIndented("SUSPEND COUNT");
874 : Print(" %d\n", node->suspend_count());
875 : PrintIndentedVisit("FOR", node->each());
876 : PrintIndentedVisit("IN", node->enumerable());
877 : PrintIndentedVisit("BODY", node->body());
878 : }
879 :
880 :
881 : void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
882 : IndentedScope indent(this, "FOR OF", node->position());
883 : PrintIndented("SUSPEND COUNT");
884 : Print(" %d\n", node->suspend_count());
885 : PrintIndentedVisit("INIT", node->assign_iterator());
886 : PrintIndentedVisit("NEXT", node->next_result());
887 : PrintIndentedVisit("DONE", node->result_done());
888 : PrintIndentedVisit("EACH", node->assign_each());
889 : PrintIndentedVisit("BODY", node->body());
890 : }
891 :
892 :
893 : void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
894 : IndentedScope indent(this, "TRY CATCH", node->position());
895 : PrintIndentedVisit("TRY", node->try_block());
896 : PrintIndented("CATCH PREDICTION");
897 : const char* prediction = "";
898 : switch (node->GetCatchPrediction(HandlerTable::UNCAUGHT)) {
899 : case HandlerTable::UNCAUGHT:
900 : prediction = "UNCAUGHT";
901 : break;
902 : case HandlerTable::CAUGHT:
903 : prediction = "CAUGHT";
904 : break;
905 : case HandlerTable::DESUGARING:
906 : prediction = "DESUGARING";
907 : break;
908 : case HandlerTable::ASYNC_AWAIT:
909 : prediction = "ASYNC_AWAIT";
910 : break;
911 : case HandlerTable::PROMISE:
912 : // Catch prediction resulting in promise rejections aren't
913 : // parsed by the parser.
914 : UNREACHABLE();
915 : }
916 : Print(" %s\n", prediction);
917 : PrintLiteralWithModeIndented("CATCHVAR", node->scope()->catch_variable(),
918 : node->scope()->catch_variable()->name());
919 : PrintIndentedVisit("CATCH", node->catch_block());
920 : }
921 :
922 : void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
923 : IndentedScope indent(this, "TRY FINALLY", node->position());
924 : PrintIndentedVisit("TRY", node->try_block());
925 : PrintIndentedVisit("FINALLY", node->finally_block());
926 : }
927 :
928 : void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
929 : IndentedScope indent(this, "DEBUGGER", node->position());
930 : }
931 :
932 :
933 : void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
934 : IndentedScope indent(this, "FUNC LITERAL", node->position());
935 : PrintLiteralIndented("NAME", node->name(), false);
936 : PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
937 : PrintParameters(node->scope());
938 : // We don't want to see the function literal in this case: it
939 : // will be printed via PrintProgram when the code for it is
940 : // generated.
941 : // PrintStatements(node->body());
942 : }
943 :
944 :
945 : void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
946 : IndentedScope indent(this, "CLASS LITERAL", node->position());
947 : PrintLiteralIndented("NAME", node->constructor()->name(), false);
948 : if (node->extends() != nullptr) {
949 : PrintIndentedVisit("EXTENDS", node->extends());
950 : }
951 : PrintClassProperties(node->properties());
952 : }
953 :
954 : void AstPrinter::PrintClassProperties(
955 : ZoneList<ClassLiteral::Property*>* properties) {
956 : for (int i = 0; i < properties->length(); i++) {
957 : ClassLiteral::Property* property = properties->at(i);
958 : const char* prop_kind = nullptr;
959 : switch (property->kind()) {
960 : case ClassLiteral::Property::METHOD:
961 : prop_kind = "METHOD";
962 : break;
963 : case ClassLiteral::Property::GETTER:
964 : prop_kind = "GETTER";
965 : break;
966 : case ClassLiteral::Property::SETTER:
967 : prop_kind = "SETTER";
968 : break;
969 : case ClassLiteral::Property::FIELD:
970 : prop_kind = "FIELD";
971 : break;
972 : }
973 : EmbeddedVector<char, 128> buf;
974 : SNPrintF(buf, "PROPERTY%s - %s", property->is_static() ? " - STATIC" : "",
975 : prop_kind);
976 : IndentedScope prop(this, buf.start());
977 : PrintIndentedVisit("KEY", properties->at(i)->key());
978 : PrintIndentedVisit("VALUE", properties->at(i)->value());
979 : }
980 : }
981 :
982 :
983 : void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
984 : IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position());
985 : PrintLiteralIndented("NAME", node->name(), false);
986 : }
987 :
988 :
989 : void AstPrinter::VisitDoExpression(DoExpression* node) {
990 : IndentedScope indent(this, "DO EXPRESSION", node->position());
991 : PrintStatements(node->block()->statements());
992 : }
993 :
994 :
995 : void AstPrinter::VisitConditional(Conditional* node) {
996 : IndentedScope indent(this, "CONDITIONAL", node->position());
997 : PrintIndentedVisit("CONDITION", node->condition());
998 : PrintIndentedVisit("THEN", node->then_expression());
999 : PrintIndentedVisit("ELSE", node->else_expression());
1000 : }
1001 :
1002 :
1003 : // TODO(svenpanne) Start with IndentedScope.
1004 : void AstPrinter::VisitLiteral(Literal* node) {
1005 : PrintLiteralIndented("LITERAL", node->value(), true);
1006 : }
1007 :
1008 :
1009 : void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
1010 : IndentedScope indent(this, "REGEXP LITERAL", node->position());
1011 : PrintLiteralIndented("PATTERN", node->pattern(), false);
1012 : int i = 0;
1013 : EmbeddedVector<char, 128> buf;
1014 : if (node->flags() & RegExp::kGlobal) buf[i++] = 'g';
1015 : if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i';
1016 : if (node->flags() & RegExp::kMultiline) buf[i++] = 'm';
1017 : if (node->flags() & RegExp::kUnicode) buf[i++] = 'u';
1018 : if (node->flags() & RegExp::kSticky) buf[i++] = 'y';
1019 : buf[i] = '\0';
1020 : PrintIndented("FLAGS ");
1021 : Print("%s", buf.start());
1022 : Print("\n");
1023 : }
1024 :
1025 :
1026 : void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
1027 : IndentedScope indent(this, "OBJ LITERAL", node->position());
1028 : PrintObjectProperties(node->properties());
1029 : }
1030 :
1031 : void AstPrinter::PrintObjectProperties(
1032 : ZoneList<ObjectLiteral::Property*>* properties) {
1033 : for (int i = 0; i < properties->length(); i++) {
1034 : ObjectLiteral::Property* property = properties->at(i);
1035 : const char* prop_kind = nullptr;
1036 : switch (property->kind()) {
1037 : case ObjectLiteral::Property::CONSTANT:
1038 : prop_kind = "CONSTANT";
1039 : break;
1040 : case ObjectLiteral::Property::COMPUTED:
1041 : prop_kind = "COMPUTED";
1042 : break;
1043 : case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1044 : prop_kind = "MATERIALIZED_LITERAL";
1045 : break;
1046 : case ObjectLiteral::Property::PROTOTYPE:
1047 : prop_kind = "PROTOTYPE";
1048 : break;
1049 : case ObjectLiteral::Property::GETTER:
1050 : prop_kind = "GETTER";
1051 : break;
1052 : case ObjectLiteral::Property::SETTER:
1053 : prop_kind = "SETTER";
1054 : break;
1055 : case ObjectLiteral::Property::SPREAD:
1056 : prop_kind = "SPREAD";
1057 : break;
1058 : }
1059 : EmbeddedVector<char, 128> buf;
1060 : SNPrintF(buf, "PROPERTY - %s", prop_kind);
1061 : IndentedScope prop(this, buf.start());
1062 : PrintIndentedVisit("KEY", properties->at(i)->key());
1063 : PrintIndentedVisit("VALUE", properties->at(i)->value());
1064 : }
1065 : }
1066 :
1067 :
1068 : void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
1069 : IndentedScope indent(this, "ARRAY LITERAL", node->position());
1070 : if (node->values()->length() > 0) {
1071 : IndentedScope indent(this, "VALUES", node->position());
1072 : for (int i = 0; i < node->values()->length(); i++) {
1073 : Visit(node->values()->at(i));
1074 : }
1075 : }
1076 : }
1077 :
1078 :
1079 : void AstPrinter::VisitVariableProxy(VariableProxy* node) {
1080 : EmbeddedVector<char, 128> buf;
1081 : int pos = SNPrintF(buf, "VAR PROXY");
1082 :
1083 : if (!node->is_resolved()) {
1084 : SNPrintF(buf + pos, " unresolved");
1085 : PrintLiteralWithModeIndented(buf.start(), nullptr, node->name());
1086 : } else {
1087 : Variable* var = node->var();
1088 : switch (var->location()) {
1089 : case VariableLocation::UNALLOCATED:
1090 : SNPrintF(buf + pos, " unallocated");
1091 : break;
1092 : case VariableLocation::PARAMETER:
1093 : SNPrintF(buf + pos, " parameter[%d]", var->index());
1094 : break;
1095 : case VariableLocation::LOCAL:
1096 : SNPrintF(buf + pos, " local[%d]", var->index());
1097 : break;
1098 : case VariableLocation::CONTEXT:
1099 : SNPrintF(buf + pos, " context[%d]", var->index());
1100 : break;
1101 : case VariableLocation::LOOKUP:
1102 : SNPrintF(buf + pos, " lookup");
1103 : break;
1104 : case VariableLocation::MODULE:
1105 : SNPrintF(buf + pos, " module");
1106 : break;
1107 : }
1108 : PrintLiteralWithModeIndented(buf.start(), var, node->name());
1109 : }
1110 : }
1111 :
1112 :
1113 : void AstPrinter::VisitAssignment(Assignment* node) {
1114 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1115 : Visit(node->target());
1116 : Visit(node->value());
1117 : }
1118 :
1119 : void AstPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
1120 : VisitAssignment(node);
1121 : }
1122 :
1123 : void AstPrinter::VisitYield(Yield* node) {
1124 : EmbeddedVector<char, 128> buf;
1125 : SNPrintF(buf, "YIELD id %d", node->suspend_id());
1126 : IndentedScope indent(this, buf.start(), node->position());
1127 : Visit(node->expression());
1128 : }
1129 :
1130 : void AstPrinter::VisitYieldStar(YieldStar* node) {
1131 : EmbeddedVector<char, 128> buf;
1132 : SNPrintF(buf, "YIELD_STAR id %d", node->suspend_id());
1133 : IndentedScope indent(this, buf.start(), node->position());
1134 : Visit(node->expression());
1135 : }
1136 :
1137 : void AstPrinter::VisitAwait(Await* node) {
1138 : EmbeddedVector<char, 128> buf;
1139 : SNPrintF(buf, "AWAIT id %d", node->suspend_id());
1140 : IndentedScope indent(this, buf.start(), node->position());
1141 : Visit(node->expression());
1142 : }
1143 :
1144 : void AstPrinter::VisitThrow(Throw* node) {
1145 : IndentedScope indent(this, "THROW", node->position());
1146 : Visit(node->exception());
1147 : }
1148 :
1149 :
1150 : void AstPrinter::VisitProperty(Property* node) {
1151 : EmbeddedVector<char, 128> buf;
1152 : SNPrintF(buf, "PROPERTY");
1153 : IndentedScope indent(this, buf.start(), node->position());
1154 :
1155 : Visit(node->obj());
1156 : Literal* literal = node->key()->AsLiteral();
1157 : if (literal != nullptr && literal->value()->IsInternalizedString()) {
1158 : PrintLiteralIndented("NAME", literal->value(), false);
1159 : } else {
1160 : PrintIndentedVisit("KEY", node->key());
1161 : }
1162 : }
1163 :
1164 :
1165 : void AstPrinter::VisitCall(Call* node) {
1166 : EmbeddedVector<char, 128> buf;
1167 : SNPrintF(buf, "CALL");
1168 : IndentedScope indent(this, buf.start());
1169 :
1170 : Visit(node->expression());
1171 : PrintArguments(node->arguments());
1172 : }
1173 :
1174 :
1175 : void AstPrinter::VisitCallNew(CallNew* node) {
1176 : IndentedScope indent(this, "CALL NEW", node->position());
1177 : Visit(node->expression());
1178 : PrintArguments(node->arguments());
1179 : }
1180 :
1181 :
1182 : void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1183 : EmbeddedVector<char, 128> buf;
1184 : SNPrintF(buf, "CALL RUNTIME %s%s", node->debug_name(),
1185 : node->is_jsruntime() ? " (JS function)" : "");
1186 : IndentedScope indent(this, buf.start(), node->position());
1187 : PrintArguments(node->arguments());
1188 : }
1189 :
1190 :
1191 : void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1192 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1193 : Visit(node->expression());
1194 : }
1195 :
1196 :
1197 : void AstPrinter::VisitCountOperation(CountOperation* node) {
1198 : EmbeddedVector<char, 128> buf;
1199 : SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1200 : Token::Name(node->op()));
1201 : IndentedScope indent(this, buf.start(), node->position());
1202 : Visit(node->expression());
1203 : }
1204 :
1205 :
1206 : void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1207 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1208 : Visit(node->left());
1209 : Visit(node->right());
1210 : }
1211 :
1212 :
1213 : void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1214 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1215 : Visit(node->left());
1216 : Visit(node->right());
1217 : }
1218 :
1219 :
1220 : void AstPrinter::VisitSpread(Spread* node) {
1221 : IndentedScope indent(this, "...", node->position());
1222 : Visit(node->expression());
1223 : }
1224 :
1225 :
1226 : void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
1227 : IndentedScope indent(this, "()", node->position());
1228 : }
1229 :
1230 : void AstPrinter::VisitGetIterator(GetIterator* node) {
1231 : IndentedScope indent(this, "GET-ITERATOR", node->position());
1232 : Visit(node->iterable());
1233 : }
1234 :
1235 : void AstPrinter::VisitGetTemplateObject(GetTemplateObject* node) {
1236 : IndentedScope indent(this, "GET-TEMPLATE-OBJECT", node->position());
1237 : }
1238 :
1239 : void AstPrinter::VisitImportCallExpression(ImportCallExpression* node) {
1240 : IndentedScope indent(this, "IMPORT-CALL", node->position());
1241 : Visit(node->argument());
1242 : }
1243 :
1244 : void AstPrinter::VisitThisFunction(ThisFunction* node) {
1245 : IndentedScope indent(this, "THIS-FUNCTION", node->position());
1246 : }
1247 :
1248 :
1249 : void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
1250 : IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position());
1251 : }
1252 :
1253 :
1254 : void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
1255 : IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position());
1256 : }
1257 :
1258 :
1259 : void AstPrinter::VisitRewritableExpression(RewritableExpression* node) {
1260 : Visit(node->expression());
1261 : }
1262 :
1263 :
1264 : #endif // DEBUG
1265 :
1266 : } // namespace internal
1267 : } // namespace v8
|