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