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 : #include "src/string-builder-inl.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 6330 : CallPrinter::CallPrinter(Isolate* isolate, bool is_user_js)
20 6330 : : builder_(new IncrementalStringBuilder(isolate)) {
21 6330 : isolate_ = isolate;
22 6330 : position_ = 0;
23 6330 : num_prints_ = 0;
24 6330 : found_ = false;
25 6330 : done_ = false;
26 6330 : is_call_error_ = false;
27 6330 : is_iterator_error_ = false;
28 6330 : is_async_iterator_error_ = false;
29 6330 : is_user_js_ = is_user_js;
30 6330 : function_kind_ = kNormalFunction;
31 : InitializeAstVisitor(isolate);
32 6330 : }
33 :
34 : CallPrinter::~CallPrinter() = default;
35 :
36 6330 : CallPrinter::ErrorHint CallPrinter::GetErrorHint() const {
37 6330 : if (is_call_error_) {
38 5718 : if (is_iterator_error_) return ErrorHint::kCallAndNormalIterator;
39 5664 : if (is_async_iterator_error_) return ErrorHint::kCallAndAsyncIterator;
40 : } else {
41 612 : if (is_iterator_error_) return ErrorHint::kNormalIterator;
42 567 : if (is_async_iterator_error_) return ErrorHint::kAsyncIterator;
43 : }
44 6222 : return ErrorHint::kNone;
45 : }
46 :
47 6330 : Handle<String> CallPrinter::Print(FunctionLiteral* program, int position) {
48 6330 : num_prints_ = 0;
49 6330 : position_ = position;
50 6330 : Find(program);
51 12660 : return builder_->Finish().ToHandleChecked();
52 : }
53 :
54 :
55 197986 : void CallPrinter::Find(AstNode* node, bool print) {
56 197986 : if (found_) {
57 13600 : if (print) {
58 11767 : int prev_num_prints = num_prints_;
59 11767 : Visit(node);
60 209753 : if (prev_num_prints != num_prints_) return;
61 : }
62 1887 : Print("(intermediate value)");
63 : } else {
64 184386 : Visit(node);
65 : }
66 : }
67 :
68 94358 : void CallPrinter::Print(const char* str) {
69 188716 : if (!found_ || done_) return;
70 9170 : num_prints_++;
71 : builder_->AppendCString(str);
72 : }
73 :
74 96809 : void CallPrinter::Print(Handle<String> str) {
75 193618 : if (!found_ || done_) return;
76 9230 : num_prints_++;
77 9230 : builder_->AppendString(str);
78 : }
79 :
80 0 : void CallPrinter::VisitBlock(Block* node) {
81 13844 : FindStatements(node->statements());
82 0 : }
83 :
84 :
85 0 : void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {}
86 :
87 :
88 0 : void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {}
89 :
90 :
91 25762 : void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) {
92 25762 : Find(node->expression());
93 25762 : }
94 :
95 :
96 0 : void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {}
97 :
98 :
99 36 : void CallPrinter::VisitSloppyBlockFunctionStatement(
100 36 : SloppyBlockFunctionStatement* node) {
101 36 : Find(node->statement());
102 36 : }
103 :
104 :
105 309 : void CallPrinter::VisitIfStatement(IfStatement* node) {
106 103 : Find(node->condition());
107 103 : Find(node->then_statement());
108 103 : if (node->HasElseStatement()) {
109 18 : Find(node->else_statement());
110 : }
111 103 : }
112 :
113 :
114 0 : void CallPrinter::VisitContinueStatement(ContinueStatement* node) {}
115 :
116 :
117 0 : void CallPrinter::VisitBreakStatement(BreakStatement* node) {}
118 :
119 :
120 2507 : void CallPrinter::VisitReturnStatement(ReturnStatement* node) {
121 2507 : Find(node->expression());
122 2507 : }
123 :
124 :
125 28 : void CallPrinter::VisitWithStatement(WithStatement* node) {
126 14 : Find(node->expression());
127 14 : Find(node->statement());
128 14 : }
129 :
130 :
131 18 : void CallPrinter::VisitSwitchStatement(SwitchStatement* node) {
132 18 : Find(node->tag());
133 63 : for (CaseClause* clause : *node->cases()) {
134 27 : if (!clause->is_default()) Find(clause->label());
135 27 : FindStatements(clause->statements());
136 : }
137 18 : }
138 :
139 :
140 18 : void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
141 9 : Find(node->body());
142 9 : Find(node->cond());
143 9 : }
144 :
145 :
146 9 : void CallPrinter::VisitWhileStatement(WhileStatement* node) {
147 9 : Find(node->cond());
148 9 : Find(node->body());
149 9 : }
150 :
151 :
152 957 : void CallPrinter::VisitForStatement(ForStatement* node) {
153 319 : if (node->init() != nullptr) {
154 310 : Find(node->init());
155 : }
156 319 : if (node->cond() != nullptr) Find(node->cond());
157 319 : if (node->next() != nullptr) Find(node->next());
158 319 : Find(node->body());
159 319 : }
160 :
161 :
162 27 : void CallPrinter::VisitForInStatement(ForInStatement* node) {
163 27 : Find(node->each());
164 27 : Find(node->subject());
165 27 : Find(node->body());
166 27 : }
167 :
168 :
169 828 : void CallPrinter::VisitForOfStatement(ForOfStatement* node) {
170 1548 : Find(node->each());
171 :
172 : // Check the subject's position in case there was a GetIterator error.
173 : bool was_found = false;
174 774 : if (node->subject()->position() == position_) {
175 54 : is_async_iterator_error_ = node->type() == IteratorType::kAsync;
176 54 : is_iterator_error_ = !is_async_iterator_error_;
177 54 : was_found = !found_;
178 54 : if (was_found) {
179 54 : found_ = true;
180 : }
181 : }
182 774 : Find(node->subject(), true);
183 774 : if (was_found) {
184 54 : done_ = true;
185 54 : found_ = false;
186 : }
187 :
188 774 : Find(node->body());
189 774 : }
190 :
191 :
192 4740 : void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
193 2370 : Find(node->try_block());
194 2370 : Find(node->catch_block());
195 2370 : }
196 :
197 :
198 288 : void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
199 144 : Find(node->try_block());
200 144 : Find(node->finally_block());
201 144 : }
202 :
203 :
204 0 : void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {}
205 :
206 :
207 6735 : void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
208 6735 : FunctionKind last_function_kind = function_kind_;
209 6735 : function_kind_ = node->kind();
210 6735 : FindStatements(node->body());
211 6735 : function_kind_ = last_function_kind;
212 6735 : }
213 :
214 :
215 4347 : void CallPrinter::VisitClassLiteral(ClassLiteral* node) {
216 1449 : if (node->extends()) Find(node->extends());
217 4347 : for (int i = 0; i < node->properties()->length(); i++) {
218 1449 : Find(node->properties()->at(i)->value());
219 : }
220 1449 : }
221 :
222 0 : void CallPrinter::VisitInitializeClassMembersStatement(
223 0 : InitializeClassMembersStatement* node) {
224 0 : for (int i = 0; i < node->fields()->length(); i++) {
225 0 : Find(node->fields()->at(i)->value());
226 : }
227 0 : }
228 :
229 0 : void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {}
230 :
231 :
232 0 : void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); }
233 :
234 :
235 405 : void CallPrinter::VisitConditional(Conditional* node) {
236 135 : Find(node->condition());
237 135 : Find(node->then_expression());
238 135 : Find(node->else_expression());
239 135 : }
240 :
241 :
242 15816 : void CallPrinter::VisitLiteral(Literal* node) {
243 : // TODO(adamk): Teach Literal how to print its values without
244 : // allocating on the heap.
245 15816 : PrintLiteral(node->BuildValue(isolate_), true);
246 15816 : }
247 :
248 :
249 1764 : void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
250 252 : Print("/");
251 252 : PrintLiteral(node->pattern(), false);
252 252 : Print("/");
253 252 : if (node->flags() & RegExp::kGlobal) Print("g");
254 252 : if (node->flags() & RegExp::kIgnoreCase) Print("i");
255 252 : if (node->flags() & RegExp::kMultiline) Print("m");
256 252 : if (node->flags() & RegExp::kUnicode) Print("u");
257 252 : if (node->flags() & RegExp::kSticky) Print("y");
258 252 : }
259 :
260 :
261 2831 : void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) {
262 2831 : Print("{");
263 6931 : for (int i = 0; i < node->properties()->length(); i++) {
264 4100 : Find(node->properties()->at(i)->value());
265 : }
266 2831 : Print("}");
267 2831 : }
268 :
269 :
270 1703 : void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) {
271 1703 : Print("[");
272 10883 : for (int i = 0; i < node->values()->length(); i++) {
273 9180 : if (i != 0) Print(",");
274 9180 : Expression* subexpr = node->values()->at(i);
275 9540 : Spread* spread = subexpr->AsSpread();
276 9540 : if (spread != nullptr && !found_ &&
277 720 : position_ == spread->expression()->position()) {
278 0 : found_ = true;
279 0 : is_iterator_error_ = true;
280 0 : Find(spread->expression(), true);
281 0 : done_ = true;
282 1703 : return;
283 : }
284 9180 : Find(subexpr, true);
285 : }
286 1703 : Print("]");
287 : }
288 :
289 :
290 56512 : void CallPrinter::VisitVariableProxy(VariableProxy* node) {
291 56512 : if (is_user_js_) {
292 56512 : PrintLiteral(node->name(), false);
293 : } else {
294 : // Variable names of non-user code are meaningless due to minification.
295 0 : Print("(var)");
296 : }
297 56512 : }
298 :
299 :
300 25731 : void CallPrinter::VisitAssignment(Assignment* node) {
301 8475 : Find(node->target());
302 8475 : if (node->target()->IsArrayLiteral()) {
303 : // Special case the visit for destructuring array assignment.
304 : bool was_found = false;
305 306 : if (node->value()->position() == position_) {
306 54 : is_iterator_error_ = true;
307 54 : was_found = !found_;
308 54 : if (was_found) {
309 54 : found_ = true;
310 : }
311 : }
312 306 : Find(node->value(), true);
313 306 : if (was_found) {
314 54 : done_ = true;
315 54 : found_ = false;
316 : }
317 : } else {
318 8169 : Find(node->value());
319 : }
320 8475 : }
321 :
322 0 : void CallPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
323 0 : VisitAssignment(node);
324 0 : }
325 :
326 189 : void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
327 :
328 54 : void CallPrinter::VisitYieldStar(YieldStar* node) {
329 108 : if (!found_ && position_ == node->expression()->position()) {
330 0 : found_ = true;
331 0 : if (IsAsyncFunction(function_kind_))
332 0 : is_async_iterator_error_ = true;
333 : else
334 0 : is_iterator_error_ = true;
335 0 : Print("yield* ");
336 : }
337 54 : Find(node->expression());
338 54 : }
339 :
340 72 : void CallPrinter::VisitAwait(Await* node) { Find(node->expression()); }
341 :
342 81 : void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); }
343 :
344 :
345 62798 : void CallPrinter::VisitProperty(Property* node) {
346 : Expression* key = node->key();
347 31399 : Literal* literal = key->AsLiteral();
348 94197 : if (literal != nullptr &&
349 124354 : literal->BuildValue(isolate_)->IsInternalizedString()) {
350 30520 : Find(node->obj(), true);
351 30520 : Print(".");
352 : // TODO(adamk): Teach Literal how to print its values without
353 : // allocating on the heap.
354 30520 : PrintLiteral(literal->BuildValue(isolate_), false);
355 : } else {
356 879 : Find(node->obj(), true);
357 879 : Print("[");
358 879 : Find(key, true);
359 879 : Print("]");
360 : }
361 31399 : }
362 :
363 0 : void CallPrinter::VisitResolvedProperty(ResolvedProperty* node) {}
364 :
365 37372 : void CallPrinter::VisitCall(Call* node) {
366 : bool was_found = false;
367 18686 : if (node->position() == position_) {
368 3865 : is_call_error_ = true;
369 3865 : was_found = !found_;
370 : }
371 18686 : if (was_found) {
372 : // Bail out if the error is caused by a direct call to a variable in
373 : // non-user JS code. The variable name is meaningless due to minification.
374 3811 : if (!is_user_js_ && node->expression()->IsVariableProxy()) {
375 0 : done_ = true;
376 18686 : return;
377 : }
378 3811 : found_ = true;
379 : }
380 18686 : Find(node->expression(), true);
381 18686 : if (!was_found && !is_iterator_error_) Print("(...)");
382 18686 : FindArguments(node->arguments());
383 18686 : if (was_found) {
384 3811 : done_ = true;
385 3811 : found_ = false;
386 : }
387 : }
388 :
389 :
390 5080 : void CallPrinter::VisitCallNew(CallNew* node) {
391 : bool was_found = false;
392 2540 : if (node->position() == position_) {
393 1853 : is_call_error_ = true;
394 1853 : was_found = !found_;
395 : }
396 2540 : if (was_found) {
397 : // Bail out if the error is caused by a direct call to a variable in
398 : // non-user JS code. The variable name is meaningless due to minification.
399 1853 : if (!is_user_js_ && node->expression()->IsVariableProxy()) {
400 0 : done_ = true;
401 2540 : return;
402 : }
403 1853 : found_ = true;
404 : }
405 5080 : Find(node->expression(), was_found || is_iterator_error_);
406 2540 : FindArguments(node->arguments());
407 2540 : if (was_found) {
408 1853 : done_ = true;
409 1853 : found_ = false;
410 : }
411 : }
412 :
413 :
414 378 : void CallPrinter::VisitCallRuntime(CallRuntime* node) {
415 378 : FindArguments(node->arguments());
416 378 : }
417 :
418 :
419 846 : void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
420 : Token::Value op = node->op();
421 : bool needsSpace =
422 423 : op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
423 423 : Print("(");
424 423 : Print(Token::String(op));
425 423 : if (needsSpace) Print(" ");
426 423 : Find(node->expression(), true);
427 423 : Print(")");
428 423 : }
429 :
430 :
431 1011 : void CallPrinter::VisitCountOperation(CountOperation* node) {
432 337 : Print("(");
433 346 : if (node->is_prefix()) Print(Token::String(node->op()));
434 337 : Find(node->expression(), true);
435 665 : if (node->is_postfix()) Print(Token::String(node->op()));
436 337 : Print(")");
437 337 : }
438 :
439 :
440 1116 : void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
441 279 : Print("(");
442 279 : Find(node->left(), true);
443 279 : Print(" ");
444 279 : Print(Token::String(node->op()));
445 279 : Print(" ");
446 279 : Find(node->right(), true);
447 279 : Print(")");
448 279 : }
449 :
450 180 : void CallPrinter::VisitNaryOperation(NaryOperation* node) {
451 45 : Print("(");
452 45 : Find(node->first(), true);
453 270 : for (size_t i = 0; i < node->subsequent_length(); ++i) {
454 90 : Print(" ");
455 90 : Print(Token::String(node->op()));
456 90 : Print(" ");
457 90 : Find(node->subsequent(i), true);
458 : }
459 45 : Print(")");
460 45 : }
461 :
462 5432 : void CallPrinter::VisitCompareOperation(CompareOperation* node) {
463 1358 : Print("(");
464 1358 : Find(node->left(), true);
465 1358 : Print(" ");
466 1358 : Print(Token::String(node->op()));
467 1358 : Print(" ");
468 1358 : Find(node->right(), true);
469 1358 : Print(")");
470 1358 : }
471 :
472 :
473 738 : void CallPrinter::VisitSpread(Spread* node) {
474 369 : Print("(...");
475 369 : Find(node->expression(), true);
476 369 : Print(")");
477 369 : }
478 :
479 0 : void CallPrinter::VisitStoreInArrayLiteral(StoreInArrayLiteral* node) {
480 0 : Find(node->array());
481 0 : Find(node->index());
482 0 : Find(node->value());
483 0 : }
484 :
485 0 : void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
486 0 : UNREACHABLE();
487 : }
488 :
489 0 : void CallPrinter::VisitGetTemplateObject(GetTemplateObject* node) {}
490 :
491 0 : void CallPrinter::VisitTemplateLiteral(TemplateLiteral* node) {
492 0 : for (Expression* substitution : *node->substitutions()) {
493 0 : Find(substitution, true);
494 : }
495 0 : }
496 :
497 0 : void CallPrinter::VisitImportCallExpression(ImportCallExpression* node) {
498 0 : Print("ImportCall(");
499 0 : Find(node->argument(), true);
500 0 : Print(")");
501 0 : }
502 :
503 0 : void CallPrinter::VisitThisFunction(ThisFunction* node) {}
504 :
505 :
506 0 : void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
507 :
508 :
509 0 : void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
510 9 : Print("super");
511 0 : }
512 :
513 :
514 80263 : void CallPrinter::FindStatements(const ZonePtrList<Statement>* statements) {
515 41212 : if (statements == nullptr) return;
516 98708 : for (int i = 0; i < statements->length(); i++) {
517 39051 : Find(statements->at(i));
518 : }
519 : }
520 :
521 62033 : void CallPrinter::FindArguments(const ZonePtrList<Expression>* arguments) {
522 43208 : if (found_) return;
523 65176 : for (int i = 0; i < arguments->length(); i++) {
524 24747 : Find(arguments->at(i));
525 : }
526 : }
527 :
528 103100 : void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) {
529 206200 : if (value->IsString()) {
530 92216 : if (quote) Print("\"");
531 92216 : Print(Handle<String>::cast(value));
532 92216 : if (quote) Print("\"");
533 32652 : } else if (value->IsNull(isolate_)) {
534 720 : Print("null");
535 30492 : } else if (value->IsTrue(isolate_)) {
536 2349 : Print("true");
537 23445 : } else if (value->IsFalse(isolate_)) {
538 2952 : Print("false");
539 14589 : } else if (value->IsUndefined(isolate_)) {
540 261 : Print("undefined");
541 9204 : } else if (value->IsNumber()) {
542 4593 : Print(isolate_->factory()->NumberToString(value));
543 18 : } else if (value->IsSymbol()) {
544 : // Symbols can only occur as literals if they were inserted by the parser.
545 0 : PrintLiteral(handle(Handle<Symbol>::cast(value)->name(), isolate_), false);
546 : }
547 103100 : }
548 :
549 :
550 0 : void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
551 0 : PrintLiteral(value->string(), quote);
552 0 : }
553 :
554 :
555 : //-----------------------------------------------------------------------------
556 :
557 :
558 : #ifdef DEBUG
559 :
560 : const char* AstPrinter::Print(AstNode* node) {
561 : Init();
562 : Visit(node);
563 : return output_;
564 : }
565 :
566 : void AstPrinter::Init() {
567 : if (size_ == 0) {
568 : DCHECK_NULL(output_);
569 : const int initial_size = 256;
570 : output_ = NewArray<char>(initial_size);
571 : size_ = initial_size;
572 : }
573 : output_[0] = '\0';
574 : pos_ = 0;
575 : }
576 :
577 : void AstPrinter::Print(const char* format, ...) {
578 : for (;;) {
579 : va_list arguments;
580 : va_start(arguments, format);
581 : int n = VSNPrintF(Vector<char>(output_, size_) + pos_,
582 : format,
583 : arguments);
584 : va_end(arguments);
585 :
586 : if (n >= 0) {
587 : // there was enough space - we are done
588 : pos_ += n;
589 : return;
590 : } else {
591 : // there was not enough space - allocate more and try again
592 : const int slack = 32;
593 : int new_size = size_ + (size_ >> 1) + slack;
594 : char* new_output = NewArray<char>(new_size);
595 : MemCopy(new_output, output_, pos_);
596 : DeleteArray(output_);
597 : output_ = new_output;
598 : size_ = new_size;
599 : }
600 : }
601 : }
602 :
603 : void AstPrinter::PrintLabels(ZonePtrList<const AstRawString>* labels) {
604 : if (labels != nullptr) {
605 : for (int i = 0; i < labels->length(); i++) {
606 : PrintLiteral(labels->at(i), false);
607 : Print(": ");
608 : }
609 : }
610 : }
611 :
612 : void AstPrinter::PrintLiteral(Literal* literal, bool quote) {
613 : switch (literal->type()) {
614 : case Literal::kString:
615 : PrintLiteral(literal->AsRawString(), quote);
616 : break;
617 : case Literal::kSymbol:
618 : const char* symbol;
619 : switch (literal->AsSymbol()) {
620 : case AstSymbol::kHomeObjectSymbol:
621 : symbol = "HomeObjectSymbol";
622 : }
623 : Print("%s", symbol);
624 : break;
625 : case Literal::kSmi:
626 : Print("%d", Smi::ToInt(literal->AsSmiLiteral()));
627 : break;
628 : case Literal::kHeapNumber:
629 : Print("%g", literal->AsNumber());
630 : break;
631 : case Literal::kBigInt:
632 : Print("%sn", literal->AsBigInt().c_str());
633 : break;
634 : case Literal::kNull:
635 : Print("null");
636 : break;
637 : case Literal::kUndefined:
638 : Print("undefined");
639 : break;
640 : case Literal::kTheHole:
641 : Print("the hole");
642 : break;
643 : case Literal::kBoolean:
644 : if (literal->ToBooleanIsTrue()) {
645 : Print("true");
646 : } else {
647 : Print("false");
648 : }
649 : break;
650 : }
651 : }
652 :
653 : void AstPrinter::PrintLiteral(const AstRawString* value, bool quote) {
654 : if (quote) Print("\"");
655 : if (value != nullptr) {
656 : const char* format = value->is_one_byte() ? "%c" : "%lc";
657 : const int increment = value->is_one_byte() ? 1 : 2;
658 : const unsigned char* raw_bytes = value->raw_data();
659 : for (int i = 0; i < value->length(); i += increment) {
660 : Print(format, raw_bytes[i]);
661 : }
662 : }
663 : if (quote) Print("\"");
664 : }
665 :
666 : void AstPrinter::PrintLiteral(const AstConsString* value, bool quote) {
667 : if (quote) Print("\"");
668 : if (value != nullptr) {
669 : std::forward_list<const AstRawString*> strings = value->ToRawStrings();
670 : for (const AstRawString* string : strings) {
671 : PrintLiteral(string, false);
672 : }
673 : }
674 : if (quote) Print("\"");
675 : }
676 :
677 : //-----------------------------------------------------------------------------
678 :
679 : class IndentedScope {
680 : public:
681 : IndentedScope(AstPrinter* printer, const char* txt)
682 : : ast_printer_(printer) {
683 : ast_printer_->PrintIndented(txt);
684 : ast_printer_->Print("\n");
685 : ast_printer_->inc_indent();
686 : }
687 :
688 : IndentedScope(AstPrinter* printer, const char* txt, int pos)
689 : : ast_printer_(printer) {
690 : ast_printer_->PrintIndented(txt);
691 : ast_printer_->Print(" at %d\n", pos);
692 : ast_printer_->inc_indent();
693 : }
694 :
695 : virtual ~IndentedScope() {
696 : ast_printer_->dec_indent();
697 : }
698 :
699 : private:
700 : AstPrinter* ast_printer_;
701 : };
702 :
703 :
704 : //-----------------------------------------------------------------------------
705 :
706 : AstPrinter::AstPrinter(uintptr_t stack_limit)
707 : : output_(nullptr), size_(0), pos_(0), indent_(0) {
708 : InitializeAstVisitor(stack_limit);
709 : }
710 :
711 : AstPrinter::~AstPrinter() {
712 : DCHECK_EQ(indent_, 0);
713 : DeleteArray(output_);
714 : }
715 :
716 :
717 : void AstPrinter::PrintIndented(const char* txt) {
718 : for (int i = 0; i < indent_; i++) {
719 : Print(". ");
720 : }
721 : Print("%s", txt);
722 : }
723 :
724 : void AstPrinter::PrintLiteralIndented(const char* info, Literal* literal,
725 : bool quote) {
726 : PrintIndented(info);
727 : Print(" ");
728 : PrintLiteral(literal, quote);
729 : Print("\n");
730 : }
731 :
732 : void AstPrinter::PrintLiteralIndented(const char* info,
733 : const AstRawString* value, bool quote) {
734 : PrintIndented(info);
735 : Print(" ");
736 : PrintLiteral(value, quote);
737 : Print("\n");
738 : }
739 :
740 : void AstPrinter::PrintLiteralIndented(const char* info,
741 : const AstConsString* value, bool quote) {
742 : PrintIndented(info);
743 : Print(" ");
744 : PrintLiteral(value, quote);
745 : Print("\n");
746 : }
747 :
748 : void AstPrinter::PrintLiteralWithModeIndented(const char* info, Variable* var,
749 : const AstRawString* value) {
750 : if (var == nullptr) {
751 : PrintLiteralIndented(info, value, true);
752 : } else {
753 : EmbeddedVector<char, 256> buf;
754 : int pos =
755 : SNPrintF(buf, "%s (%p) (mode = %s, assigned = %s", info,
756 : reinterpret_cast<void*>(var), VariableMode2String(var->mode()),
757 : var->maybe_assigned() == kMaybeAssigned ? "true" : "false");
758 : SNPrintF(buf + pos, ")");
759 : PrintLiteralIndented(buf.start(), value, true);
760 : }
761 : }
762 :
763 : void AstPrinter::PrintLabelsIndented(ZonePtrList<const AstRawString>* labels,
764 : const char* prefix) {
765 : if (labels == nullptr || labels->length() == 0) return;
766 : PrintIndented(prefix);
767 : Print("LABELS ");
768 : PrintLabels(labels);
769 : Print("\n");
770 : }
771 :
772 :
773 : void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
774 : if (node != nullptr) {
775 : IndentedScope indent(this, s, node->position());
776 : Visit(node);
777 : }
778 : }
779 :
780 :
781 : const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
782 : Init();
783 : { IndentedScope indent(this, "FUNC", program->position());
784 : PrintIndented("KIND");
785 : Print(" %d\n", program->kind());
786 : PrintIndented("SUSPEND COUNT");
787 : Print(" %d\n", program->suspend_count());
788 : PrintLiteralIndented("NAME", program->raw_name(), true);
789 : if (program->raw_inferred_name()) {
790 : PrintLiteralIndented("INFERRED NAME", program->raw_inferred_name(), true);
791 : }
792 : if (program->requires_instance_members_initializer()) {
793 : Print(" REQUIRES INSTANCE FIELDS INITIALIZER\n");
794 : }
795 : PrintParameters(program->scope());
796 : PrintDeclarations(program->scope()->declarations());
797 : PrintStatements(program->body());
798 : }
799 : return output_;
800 : }
801 :
802 :
803 : void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) {
804 : AstPrinter printer(isolate->stack_guard()->real_climit());
805 : printer.Init();
806 : printer.Visit(node);
807 : PrintF("%s", printer.output_);
808 : }
809 :
810 : void AstPrinter::PrintDeclarations(Declaration::List* declarations) {
811 : if (!declarations->is_empty()) {
812 : IndentedScope indent(this, "DECLS");
813 : for (Declaration* decl : *declarations) Visit(decl);
814 : }
815 : }
816 :
817 : void AstPrinter::PrintParameters(DeclarationScope* scope) {
818 : if (scope->num_parameters() > 0) {
819 : IndentedScope indent(this, "PARAMS");
820 : for (int i = 0; i < scope->num_parameters(); i++) {
821 : PrintLiteralWithModeIndented("VAR", scope->parameter(i),
822 : scope->parameter(i)->raw_name());
823 : }
824 : }
825 : }
826 :
827 : void AstPrinter::PrintStatements(const ZonePtrList<Statement>* statements) {
828 : for (int i = 0; i < statements->length(); i++) {
829 : Visit(statements->at(i));
830 : }
831 : }
832 :
833 : void AstPrinter::PrintArguments(const ZonePtrList<Expression>* arguments) {
834 : for (int i = 0; i < arguments->length(); i++) {
835 : Visit(arguments->at(i));
836 : }
837 : }
838 :
839 :
840 : void AstPrinter::VisitBlock(Block* node) {
841 : const char* block_txt =
842 : node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK";
843 : IndentedScope indent(this, block_txt, node->position());
844 : PrintLabelsIndented(node->labels());
845 : PrintStatements(node->statements());
846 : }
847 :
848 :
849 : // TODO(svenpanne) Start with IndentedScope.
850 : void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
851 : PrintLiteralWithModeIndented("VARIABLE", node->var(),
852 : node->var()->raw_name());
853 : }
854 :
855 :
856 : // TODO(svenpanne) Start with IndentedScope.
857 : void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
858 : PrintIndented("FUNCTION ");
859 : PrintLiteral(node->var()->raw_name(), true);
860 : Print(" = function ");
861 : PrintLiteral(node->fun()->raw_name(), false);
862 : Print("\n");
863 : }
864 :
865 :
866 : void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
867 : IndentedScope indent(this, "EXPRESSION STATEMENT", node->position());
868 : Visit(node->expression());
869 : }
870 :
871 :
872 : void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
873 : IndentedScope indent(this, "EMPTY", node->position());
874 : }
875 :
876 :
877 : void AstPrinter::VisitSloppyBlockFunctionStatement(
878 : SloppyBlockFunctionStatement* node) {
879 : Visit(node->statement());
880 : }
881 :
882 :
883 : void AstPrinter::VisitIfStatement(IfStatement* node) {
884 : IndentedScope indent(this, "IF", node->position());
885 : PrintIndentedVisit("CONDITION", node->condition());
886 : PrintIndentedVisit("THEN", node->then_statement());
887 : if (node->HasElseStatement()) {
888 : PrintIndentedVisit("ELSE", node->else_statement());
889 : }
890 : }
891 :
892 :
893 : void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
894 : IndentedScope indent(this, "CONTINUE", node->position());
895 : PrintLabelsIndented(node->target()->labels());
896 : }
897 :
898 :
899 : void AstPrinter::VisitBreakStatement(BreakStatement* node) {
900 : IndentedScope indent(this, "BREAK", node->position());
901 : PrintLabelsIndented(node->target()->labels());
902 : }
903 :
904 :
905 : void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
906 : IndentedScope indent(this, "RETURN", node->position());
907 : Visit(node->expression());
908 : }
909 :
910 :
911 : void AstPrinter::VisitWithStatement(WithStatement* node) {
912 : IndentedScope indent(this, "WITH", node->position());
913 : PrintIndentedVisit("OBJECT", node->expression());
914 : PrintIndentedVisit("BODY", node->statement());
915 : }
916 :
917 :
918 : void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
919 : IndentedScope indent(this, "SWITCH", node->position());
920 : PrintLabelsIndented(node->labels());
921 : PrintIndentedVisit("TAG", node->tag());
922 : for (CaseClause* clause : *node->cases()) {
923 : if (clause->is_default()) {
924 : IndentedScope indent(this, "DEFAULT");
925 : PrintStatements(clause->statements());
926 : } else {
927 : IndentedScope indent(this, "CASE");
928 : Visit(clause->label());
929 : PrintStatements(clause->statements());
930 : }
931 : }
932 : }
933 :
934 :
935 : void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
936 : IndentedScope indent(this, "DO", node->position());
937 : PrintLabelsIndented(node->labels());
938 : PrintLabelsIndented(node->own_labels(), "OWN ");
939 : PrintIndentedVisit("BODY", node->body());
940 : PrintIndentedVisit("COND", node->cond());
941 : }
942 :
943 :
944 : void AstPrinter::VisitWhileStatement(WhileStatement* node) {
945 : IndentedScope indent(this, "WHILE", node->position());
946 : PrintLabelsIndented(node->labels());
947 : PrintLabelsIndented(node->own_labels(), "OWN ");
948 : PrintIndentedVisit("COND", node->cond());
949 : PrintIndentedVisit("BODY", node->body());
950 : }
951 :
952 :
953 : void AstPrinter::VisitForStatement(ForStatement* node) {
954 : IndentedScope indent(this, "FOR", node->position());
955 : PrintLabelsIndented(node->labels());
956 : PrintLabelsIndented(node->own_labels(), "OWN ");
957 : if (node->init()) PrintIndentedVisit("INIT", node->init());
958 : if (node->cond()) PrintIndentedVisit("COND", node->cond());
959 : PrintIndentedVisit("BODY", node->body());
960 : if (node->next()) PrintIndentedVisit("NEXT", node->next());
961 : }
962 :
963 :
964 : void AstPrinter::VisitForInStatement(ForInStatement* node) {
965 : IndentedScope indent(this, "FOR IN", node->position());
966 : PrintLabelsIndented(node->labels());
967 : PrintLabelsIndented(node->own_labels(), "OWN ");
968 : PrintIndentedVisit("FOR", node->each());
969 : PrintIndentedVisit("IN", node->subject());
970 : PrintIndentedVisit("BODY", node->body());
971 : }
972 :
973 :
974 : void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
975 : IndentedScope indent(this, "FOR OF", node->position());
976 : PrintLabelsIndented(node->labels());
977 : PrintLabelsIndented(node->own_labels(), "OWN ");
978 : const char* for_type;
979 : switch (node->type()) {
980 : case IteratorType::kNormal:
981 : for_type = "FOR";
982 : break;
983 : case IteratorType::kAsync:
984 : for_type = "FOR AWAIT";
985 : break;
986 : }
987 : PrintIndentedVisit(for_type, node->each());
988 : PrintIndentedVisit("OF", node->subject());
989 : PrintIndentedVisit("BODY", node->body());
990 : }
991 :
992 :
993 : void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
994 : IndentedScope indent(this, "TRY CATCH", node->position());
995 : PrintIndentedVisit("TRY", node->try_block());
996 : PrintIndented("CATCH PREDICTION");
997 : const char* prediction = "";
998 : switch (node->GetCatchPrediction(HandlerTable::UNCAUGHT)) {
999 : case HandlerTable::UNCAUGHT:
1000 : prediction = "UNCAUGHT";
1001 : break;
1002 : case HandlerTable::CAUGHT:
1003 : prediction = "CAUGHT";
1004 : break;
1005 : case HandlerTable::DESUGARING:
1006 : prediction = "DESUGARING";
1007 : break;
1008 : case HandlerTable::ASYNC_AWAIT:
1009 : prediction = "ASYNC_AWAIT";
1010 : break;
1011 : case HandlerTable::PROMISE:
1012 : // Catch prediction resulting in promise rejections aren't
1013 : // parsed by the parser.
1014 : UNREACHABLE();
1015 : }
1016 : Print(" %s\n", prediction);
1017 : if (node->scope()) {
1018 : PrintLiteralWithModeIndented("CATCHVAR", node->scope()->catch_variable(),
1019 : node->scope()->catch_variable()->raw_name());
1020 : }
1021 : PrintIndentedVisit("CATCH", node->catch_block());
1022 : }
1023 :
1024 : void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
1025 : IndentedScope indent(this, "TRY FINALLY", node->position());
1026 : PrintIndentedVisit("TRY", node->try_block());
1027 : PrintIndentedVisit("FINALLY", node->finally_block());
1028 : }
1029 :
1030 : void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
1031 : IndentedScope indent(this, "DEBUGGER", node->position());
1032 : }
1033 :
1034 :
1035 : void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
1036 : IndentedScope indent(this, "FUNC LITERAL", node->position());
1037 : PrintLiteralIndented("NAME", node->raw_name(), false);
1038 : PrintLiteralIndented("INFERRED NAME", node->raw_inferred_name(), false);
1039 : // We don't want to see the function literal in this case: it
1040 : // will be printed via PrintProgram when the code for it is
1041 : // generated.
1042 : // PrintParameters(node->scope());
1043 : // PrintStatements(node->body());
1044 : }
1045 :
1046 :
1047 : void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
1048 : IndentedScope indent(this, "CLASS LITERAL", node->position());
1049 : PrintLiteralIndented("NAME", node->constructor()->raw_name(), false);
1050 : if (node->extends() != nullptr) {
1051 : PrintIndentedVisit("EXTENDS", node->extends());
1052 : }
1053 : if (node->static_fields_initializer() != nullptr) {
1054 : PrintIndentedVisit("STATIC FIELDS INITIALIZER",
1055 : node->static_fields_initializer());
1056 : }
1057 : if (node->instance_members_initializer_function() != nullptr) {
1058 : PrintIndentedVisit("INSTANCE ELEMENTS INITIALIZER",
1059 : node->instance_members_initializer_function());
1060 : }
1061 : PrintClassProperties(node->properties());
1062 : }
1063 :
1064 : void AstPrinter::VisitInitializeClassMembersStatement(
1065 : InitializeClassMembersStatement* node) {
1066 : IndentedScope indent(this, "INITIALIZE CLASS ELEMENTS", node->position());
1067 : PrintClassProperties(node->fields());
1068 : }
1069 :
1070 : void AstPrinter::PrintClassProperties(
1071 : const ZonePtrList<ClassLiteral::Property>* properties) {
1072 : for (int i = 0; i < properties->length(); i++) {
1073 : ClassLiteral::Property* property = properties->at(i);
1074 : const char* prop_kind = nullptr;
1075 : switch (property->kind()) {
1076 : case ClassLiteral::Property::METHOD:
1077 : prop_kind = "METHOD";
1078 : break;
1079 : case ClassLiteral::Property::GETTER:
1080 : prop_kind = "GETTER";
1081 : break;
1082 : case ClassLiteral::Property::SETTER:
1083 : prop_kind = "SETTER";
1084 : break;
1085 : case ClassLiteral::Property::FIELD:
1086 : prop_kind = "FIELD";
1087 : break;
1088 : }
1089 : EmbeddedVector<char, 128> buf;
1090 : SNPrintF(buf, "PROPERTY%s%s - %s", property->is_static() ? " - STATIC" : "",
1091 : property->is_private() ? " - PRIVATE" : " - PUBLIC", prop_kind);
1092 : IndentedScope prop(this, buf.start());
1093 : PrintIndentedVisit("KEY", properties->at(i)->key());
1094 : PrintIndentedVisit("VALUE", properties->at(i)->value());
1095 : }
1096 : }
1097 :
1098 :
1099 : void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
1100 : IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position());
1101 : PrintLiteralIndented("NAME", node->raw_name(), false);
1102 : }
1103 :
1104 :
1105 : void AstPrinter::VisitDoExpression(DoExpression* node) {
1106 : IndentedScope indent(this, "DO EXPRESSION", node->position());
1107 : PrintStatements(node->block()->statements());
1108 : }
1109 :
1110 :
1111 : void AstPrinter::VisitConditional(Conditional* node) {
1112 : IndentedScope indent(this, "CONDITIONAL", node->position());
1113 : PrintIndentedVisit("CONDITION", node->condition());
1114 : PrintIndentedVisit("THEN", node->then_expression());
1115 : PrintIndentedVisit("ELSE", node->else_expression());
1116 : }
1117 :
1118 :
1119 : void AstPrinter::VisitLiteral(Literal* node) {
1120 : PrintLiteralIndented("LITERAL", node, true);
1121 : }
1122 :
1123 :
1124 : void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
1125 : IndentedScope indent(this, "REGEXP LITERAL", node->position());
1126 : PrintLiteralIndented("PATTERN", node->raw_pattern(), false);
1127 : int i = 0;
1128 : EmbeddedVector<char, 128> buf;
1129 : if (node->flags() & RegExp::kGlobal) buf[i++] = 'g';
1130 : if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i';
1131 : if (node->flags() & RegExp::kMultiline) buf[i++] = 'm';
1132 : if (node->flags() & RegExp::kUnicode) buf[i++] = 'u';
1133 : if (node->flags() & RegExp::kSticky) buf[i++] = 'y';
1134 : buf[i] = '\0';
1135 : PrintIndented("FLAGS ");
1136 : Print("%s", buf.start());
1137 : Print("\n");
1138 : }
1139 :
1140 :
1141 : void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
1142 : IndentedScope indent(this, "OBJ LITERAL", node->position());
1143 : PrintObjectProperties(node->properties());
1144 : }
1145 :
1146 : void AstPrinter::PrintObjectProperties(
1147 : const ZonePtrList<ObjectLiteral::Property>* properties) {
1148 : for (int i = 0; i < properties->length(); i++) {
1149 : ObjectLiteral::Property* property = properties->at(i);
1150 : const char* prop_kind = nullptr;
1151 : switch (property->kind()) {
1152 : case ObjectLiteral::Property::CONSTANT:
1153 : prop_kind = "CONSTANT";
1154 : break;
1155 : case ObjectLiteral::Property::COMPUTED:
1156 : prop_kind = "COMPUTED";
1157 : break;
1158 : case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1159 : prop_kind = "MATERIALIZED_LITERAL";
1160 : break;
1161 : case ObjectLiteral::Property::PROTOTYPE:
1162 : prop_kind = "PROTOTYPE";
1163 : break;
1164 : case ObjectLiteral::Property::GETTER:
1165 : prop_kind = "GETTER";
1166 : break;
1167 : case ObjectLiteral::Property::SETTER:
1168 : prop_kind = "SETTER";
1169 : break;
1170 : case ObjectLiteral::Property::SPREAD:
1171 : prop_kind = "SPREAD";
1172 : break;
1173 : }
1174 : EmbeddedVector<char, 128> buf;
1175 : SNPrintF(buf, "PROPERTY - %s", prop_kind);
1176 : IndentedScope prop(this, buf.start());
1177 : PrintIndentedVisit("KEY", properties->at(i)->key());
1178 : PrintIndentedVisit("VALUE", properties->at(i)->value());
1179 : }
1180 : }
1181 :
1182 :
1183 : void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
1184 : IndentedScope indent(this, "ARRAY LITERAL", node->position());
1185 : if (node->values()->length() > 0) {
1186 : IndentedScope indent(this, "VALUES", node->position());
1187 : for (int i = 0; i < node->values()->length(); i++) {
1188 : Visit(node->values()->at(i));
1189 : }
1190 : }
1191 : }
1192 :
1193 :
1194 : void AstPrinter::VisitVariableProxy(VariableProxy* node) {
1195 : EmbeddedVector<char, 128> buf;
1196 : int pos = SNPrintF(buf, "VAR PROXY");
1197 :
1198 : if (!node->is_resolved()) {
1199 : SNPrintF(buf + pos, " unresolved");
1200 : PrintLiteralWithModeIndented(buf.start(), nullptr, node->raw_name());
1201 : } else {
1202 : Variable* var = node->var();
1203 : switch (var->location()) {
1204 : case VariableLocation::UNALLOCATED:
1205 : SNPrintF(buf + pos, " unallocated");
1206 : break;
1207 : case VariableLocation::PARAMETER:
1208 : SNPrintF(buf + pos, " parameter[%d]", var->index());
1209 : break;
1210 : case VariableLocation::LOCAL:
1211 : SNPrintF(buf + pos, " local[%d]", var->index());
1212 : break;
1213 : case VariableLocation::CONTEXT:
1214 : SNPrintF(buf + pos, " context[%d]", var->index());
1215 : break;
1216 : case VariableLocation::LOOKUP:
1217 : SNPrintF(buf + pos, " lookup");
1218 : break;
1219 : case VariableLocation::MODULE:
1220 : SNPrintF(buf + pos, " module");
1221 : break;
1222 : }
1223 : PrintLiteralWithModeIndented(buf.start(), var, node->raw_name());
1224 : }
1225 : }
1226 :
1227 :
1228 : void AstPrinter::VisitAssignment(Assignment* node) {
1229 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1230 : Visit(node->target());
1231 : Visit(node->value());
1232 : }
1233 :
1234 : void AstPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
1235 : VisitAssignment(node);
1236 : }
1237 :
1238 : void AstPrinter::VisitYield(Yield* node) {
1239 : EmbeddedVector<char, 128> buf;
1240 : SNPrintF(buf, "YIELD");
1241 : IndentedScope indent(this, buf.start(), node->position());
1242 : Visit(node->expression());
1243 : }
1244 :
1245 : void AstPrinter::VisitYieldStar(YieldStar* node) {
1246 : EmbeddedVector<char, 128> buf;
1247 : SNPrintF(buf, "YIELD_STAR");
1248 : IndentedScope indent(this, buf.start(), node->position());
1249 : Visit(node->expression());
1250 : }
1251 :
1252 : void AstPrinter::VisitAwait(Await* node) {
1253 : EmbeddedVector<char, 128> buf;
1254 : SNPrintF(buf, "AWAIT");
1255 : IndentedScope indent(this, buf.start(), node->position());
1256 : Visit(node->expression());
1257 : }
1258 :
1259 : void AstPrinter::VisitThrow(Throw* node) {
1260 : IndentedScope indent(this, "THROW", node->position());
1261 : Visit(node->exception());
1262 : }
1263 :
1264 : void AstPrinter::VisitProperty(Property* node) {
1265 : EmbeddedVector<char, 128> buf;
1266 : SNPrintF(buf, "PROPERTY");
1267 : IndentedScope indent(this, buf.start(), node->position());
1268 :
1269 : Visit(node->obj());
1270 : AssignType property_kind = Property::GetAssignType(node);
1271 : if (property_kind == NAMED_PROPERTY ||
1272 : property_kind == NAMED_SUPER_PROPERTY) {
1273 : PrintLiteralIndented("NAME", node->key()->AsLiteral(), false);
1274 : } else {
1275 : DCHECK(property_kind == KEYED_PROPERTY ||
1276 : property_kind == KEYED_SUPER_PROPERTY);
1277 : PrintIndentedVisit("KEY", node->key());
1278 : }
1279 : }
1280 :
1281 : void AstPrinter::VisitResolvedProperty(ResolvedProperty* node) {
1282 : EmbeddedVector<char, 128> buf;
1283 : SNPrintF(buf, "RESOLVED-PROPERTY");
1284 : IndentedScope indent(this, buf.start(), node->position());
1285 :
1286 : PrintIndentedVisit("RECEIVER", node->object());
1287 : PrintIndentedVisit("PROPERTY", node->property());
1288 : }
1289 :
1290 : void AstPrinter::VisitCall(Call* node) {
1291 : EmbeddedVector<char, 128> buf;
1292 : SNPrintF(buf, "CALL");
1293 : IndentedScope indent(this, buf.start());
1294 :
1295 : Visit(node->expression());
1296 : PrintArguments(node->arguments());
1297 : }
1298 :
1299 :
1300 : void AstPrinter::VisitCallNew(CallNew* node) {
1301 : IndentedScope indent(this, "CALL NEW", node->position());
1302 : Visit(node->expression());
1303 : PrintArguments(node->arguments());
1304 : }
1305 :
1306 :
1307 : void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1308 : EmbeddedVector<char, 128> buf;
1309 : SNPrintF(buf, "CALL RUNTIME %s%s", node->debug_name(),
1310 : node->is_jsruntime() ? " (JS function)" : "");
1311 : IndentedScope indent(this, buf.start(), node->position());
1312 : PrintArguments(node->arguments());
1313 : }
1314 :
1315 :
1316 : void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1317 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1318 : Visit(node->expression());
1319 : }
1320 :
1321 :
1322 : void AstPrinter::VisitCountOperation(CountOperation* node) {
1323 : EmbeddedVector<char, 128> buf;
1324 : SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1325 : Token::Name(node->op()));
1326 : IndentedScope indent(this, buf.start(), node->position());
1327 : Visit(node->expression());
1328 : }
1329 :
1330 :
1331 : void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1332 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1333 : Visit(node->left());
1334 : Visit(node->right());
1335 : }
1336 :
1337 : void AstPrinter::VisitNaryOperation(NaryOperation* node) {
1338 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1339 : Visit(node->first());
1340 : for (size_t i = 0; i < node->subsequent_length(); ++i) {
1341 : Visit(node->subsequent(i));
1342 : }
1343 : }
1344 :
1345 : void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1346 : IndentedScope indent(this, Token::Name(node->op()), node->position());
1347 : Visit(node->left());
1348 : Visit(node->right());
1349 : }
1350 :
1351 :
1352 : void AstPrinter::VisitSpread(Spread* node) {
1353 : IndentedScope indent(this, "SPREAD", node->position());
1354 : Visit(node->expression());
1355 : }
1356 :
1357 : void AstPrinter::VisitStoreInArrayLiteral(StoreInArrayLiteral* node) {
1358 : IndentedScope indent(this, "STORE IN ARRAY LITERAL", node->position());
1359 : PrintIndentedVisit("ARRAY", node->array());
1360 : PrintIndentedVisit("INDEX", node->index());
1361 : PrintIndentedVisit("VALUE", node->value());
1362 : }
1363 :
1364 : void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) {
1365 : IndentedScope indent(this, "()", node->position());
1366 : }
1367 :
1368 : void AstPrinter::VisitGetTemplateObject(GetTemplateObject* node) {
1369 : IndentedScope indent(this, "GET-TEMPLATE-OBJECT", node->position());
1370 : }
1371 :
1372 : void AstPrinter::VisitTemplateLiteral(TemplateLiteral* node) {
1373 : IndentedScope indent(this, "TEMPLATE-LITERAL", node->position());
1374 : const AstRawString* string = node->string_parts()->first();
1375 : if (!string->IsEmpty()) PrintLiteralIndented("SPAN", string, true);
1376 : for (int i = 0; i < node->substitutions()->length();) {
1377 : PrintIndentedVisit("EXPR", node->substitutions()->at(i++));
1378 : if (i < node->string_parts()->length()) {
1379 : string = node->string_parts()->at(i);
1380 : if (!string->IsEmpty()) PrintLiteralIndented("SPAN", string, true);
1381 : }
1382 : }
1383 : }
1384 :
1385 : void AstPrinter::VisitImportCallExpression(ImportCallExpression* node) {
1386 : IndentedScope indent(this, "IMPORT-CALL", node->position());
1387 : Visit(node->argument());
1388 : }
1389 :
1390 : void AstPrinter::VisitThisFunction(ThisFunction* node) {
1391 : IndentedScope indent(this, "THIS-FUNCTION", node->position());
1392 : }
1393 :
1394 :
1395 : void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
1396 : IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position());
1397 : }
1398 :
1399 :
1400 : void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
1401 : IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position());
1402 : }
1403 :
1404 :
1405 : #endif // DEBUG
1406 :
1407 : } // namespace internal
1408 183867 : } // namespace v8
|