1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include <stdarg.h> 29 30 #include "v8.h" 31 32 #include "prettyprinter.h" 33 #include "scopes.h" 34 #include "platform.h" 35 36 namespace v8 { 37 namespace internal { 38 39 #ifdef DEBUG 40 41 PrettyPrinter::PrettyPrinter() { 42 output_ = NULL; 43 size_ = 0; 44 pos_ = 0; 45 } 46 47 48 PrettyPrinter::~PrettyPrinter() { 49 DeleteArray(output_); 50 } 51 52 53 void PrettyPrinter::VisitBlock(Block* node) { 54 if (!node->is_initializer_block()) Print("{ "); 55 PrintStatements(node->statements()); 56 if (node->statements()->length() > 0) Print(" "); 57 if (!node->is_initializer_block()) Print("}"); 58 } 59 60 61 void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 62 Print("var "); 63 PrintLiteral(node->proxy()->name(), false); 64 Print(";"); 65 } 66 67 68 void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { 69 Print("function "); 70 PrintLiteral(node->proxy()->name(), false); 71 Print(" = "); 72 PrintFunctionLiteral(node->fun()); 73 Print(";"); 74 } 75 76 77 void PrettyPrinter::VisitModuleDeclaration(ModuleDeclaration* node) { 78 Print("module "); 79 PrintLiteral(node->proxy()->name(), false); 80 Print(" = "); 81 Visit(node->module()); 82 Print(";"); 83 } 84 85 86 void PrettyPrinter::VisitImportDeclaration(ImportDeclaration* node) { 87 Print("import "); 88 PrintLiteral(node->proxy()->name(), false); 89 Print(" from "); 90 Visit(node->module()); 91 Print(";"); 92 } 93 94 95 void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) { 96 Print("export "); 97 PrintLiteral(node->proxy()->name(), false); 98 Print(";"); 99 } 100 101 102 void PrettyPrinter::VisitModuleLiteral(ModuleLiteral* node) { 103 VisitBlock(node->body()); 104 } 105 106 107 void PrettyPrinter::VisitModuleVariable(ModuleVariable* node) { 108 Visit(node->proxy()); 109 } 110 111 112 void PrettyPrinter::VisitModulePath(ModulePath* node) { 113 Visit(node->module()); 114 Print("."); 115 PrintLiteral(node->name(), false); 116 } 117 118 119 void PrettyPrinter::VisitModuleUrl(ModuleUrl* node) { 120 Print("at "); 121 PrintLiteral(node->url(), true); 122 } 123 124 125 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) { 126 Visit(node->expression()); 127 Print(";"); 128 } 129 130 131 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) { 132 Print(";"); 133 } 134 135 136 void PrettyPrinter::VisitIfStatement(IfStatement* node) { 137 Print("if ("); 138 Visit(node->condition()); 139 Print(") "); 140 Visit(node->then_statement()); 141 if (node->HasElseStatement()) { 142 Print(" else "); 143 Visit(node->else_statement()); 144 } 145 } 146 147 148 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) { 149 Print("continue"); 150 ZoneStringList* labels = node->target()->labels(); 151 if (labels != NULL) { 152 Print(" "); 153 ASSERT(labels->length() > 0); // guaranteed to have at least one entry 154 PrintLiteral(labels->at(0), false); // any label from the list is fine 155 } 156 Print(";"); 157 } 158 159 160 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) { 161 Print("break"); 162 ZoneStringList* labels = node->target()->labels(); 163 if (labels != NULL) { 164 Print(" "); 165 ASSERT(labels->length() > 0); // guaranteed to have at least one entry 166 PrintLiteral(labels->at(0), false); // any label from the list is fine 167 } 168 Print(";"); 169 } 170 171 172 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { 173 Print("return "); 174 Visit(node->expression()); 175 Print(";"); 176 } 177 178 179 void PrettyPrinter::VisitWithStatement(WithStatement* node) { 180 Print("with ("); 181 Visit(node->expression()); 182 Print(") "); 183 Visit(node->statement()); 184 } 185 186 187 void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) { 188 PrintLabels(node->labels()); 189 Print("switch ("); 190 Visit(node->tag()); 191 Print(") { "); 192 ZoneList<CaseClause*>* cases = node->cases(); 193 for (int i = 0; i < cases->length(); i++) 194 PrintCaseClause(cases->at(i)); 195 Print("}"); 196 } 197 198 199 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 200 PrintLabels(node->labels()); 201 Print("do "); 202 Visit(node->body()); 203 Print(" while ("); 204 Visit(node->cond()); 205 Print(");"); 206 } 207 208 209 void PrettyPrinter::VisitWhileStatement(WhileStatement* node) { 210 PrintLabels(node->labels()); 211 Print("while ("); 212 Visit(node->cond()); 213 Print(") "); 214 Visit(node->body()); 215 } 216 217 218 void PrettyPrinter::VisitForStatement(ForStatement* node) { 219 PrintLabels(node->labels()); 220 Print("for ("); 221 if (node->init() != NULL) { 222 Visit(node->init()); 223 Print(" "); 224 } else { 225 Print("; "); 226 } 227 if (node->cond() != NULL) Visit(node->cond()); 228 Print("; "); 229 if (node->next() != NULL) { 230 Visit(node->next()); // prints extra ';', unfortunately 231 // to fix: should use Expression for next 232 } 233 Print(") "); 234 Visit(node->body()); 235 } 236 237 238 void PrettyPrinter::VisitForInStatement(ForInStatement* node) { 239 PrintLabels(node->labels()); 240 Print("for ("); 241 Visit(node->each()); 242 Print(" in "); 243 Visit(node->enumerable()); 244 Print(") "); 245 Visit(node->body()); 246 } 247 248 249 void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 250 Print("try "); 251 Visit(node->try_block()); 252 Print(" catch ("); 253 const bool quote = false; 254 PrintLiteral(node->variable()->name(), quote); 255 Print(") "); 256 Visit(node->catch_block()); 257 } 258 259 260 void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 261 Print("try "); 262 Visit(node->try_block()); 263 Print(" finally "); 264 Visit(node->finally_block()); 265 } 266 267 268 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 269 Print("debugger "); 270 } 271 272 273 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 274 Print("("); 275 PrintFunctionLiteral(node); 276 Print(")"); 277 } 278 279 280 void PrettyPrinter::VisitSharedFunctionInfoLiteral( 281 SharedFunctionInfoLiteral* node) { 282 Print("("); 283 PrintLiteral(node->shared_function_info(), true); 284 Print(")"); 285 } 286 287 288 void PrettyPrinter::VisitConditional(Conditional* node) { 289 Visit(node->condition()); 290 Print(" ? "); 291 Visit(node->then_expression()); 292 Print(" : "); 293 Visit(node->else_expression()); 294 } 295 296 297 void PrettyPrinter::VisitLiteral(Literal* node) { 298 PrintLiteral(node->handle(), true); 299 } 300 301 302 void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 303 Print(" RegExp("); 304 PrintLiteral(node->pattern(), false); 305 Print(","); 306 PrintLiteral(node->flags(), false); 307 Print(") "); 308 } 309 310 311 void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) { 312 Print("{ "); 313 for (int i = 0; i < node->properties()->length(); i++) { 314 if (i != 0) Print(","); 315 ObjectLiteral::Property* property = node->properties()->at(i); 316 Print(" "); 317 Visit(property->key()); 318 Print(": "); 319 Visit(property->value()); 320 } 321 Print(" }"); 322 } 323 324 325 void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) { 326 Print("[ "); 327 for (int i = 0; i < node->values()->length(); i++) { 328 if (i != 0) Print(","); 329 Visit(node->values()->at(i)); 330 } 331 Print(" ]"); 332 } 333 334 335 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { 336 PrintLiteral(node->name(), false); 337 } 338 339 340 void PrettyPrinter::VisitAssignment(Assignment* node) { 341 Visit(node->target()); 342 Print(" %s ", Token::String(node->op())); 343 Visit(node->value()); 344 } 345 346 347 void PrettyPrinter::VisitThrow(Throw* node) { 348 Print("throw "); 349 Visit(node->exception()); 350 } 351 352 353 void PrettyPrinter::VisitProperty(Property* node) { 354 Expression* key = node->key(); 355 Literal* literal = key->AsLiteral(); 356 if (literal != NULL && literal->handle()->IsSymbol()) { 357 Print("("); 358 Visit(node->obj()); 359 Print(")."); 360 PrintLiteral(literal->handle(), false); 361 } else { 362 Visit(node->obj()); 363 Print("["); 364 Visit(key); 365 Print("]"); 366 } 367 } 368 369 370 void PrettyPrinter::VisitCall(Call* node) { 371 Visit(node->expression()); 372 PrintArguments(node->arguments()); 373 } 374 375 376 void PrettyPrinter::VisitCallNew(CallNew* node) { 377 Print("new ("); 378 Visit(node->expression()); 379 Print(")"); 380 PrintArguments(node->arguments()); 381 } 382 383 384 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) { 385 Print("%%"); 386 PrintLiteral(node->name(), false); 387 PrintArguments(node->arguments()); 388 } 389 390 391 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) { 392 Token::Value op = node->op(); 393 bool needsSpace = 394 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; 395 Print("(%s%s", Token::String(op), needsSpace ? " " : ""); 396 Visit(node->expression()); 397 Print(")"); 398 } 399 400 401 void PrettyPrinter::VisitCountOperation(CountOperation* node) { 402 Print("("); 403 if (node->is_prefix()) Print("%s", Token::String(node->op())); 404 Visit(node->expression()); 405 if (node->is_postfix()) Print("%s", Token::String(node->op())); 406 Print(")"); 407 } 408 409 410 void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) { 411 Print("("); 412 Visit(node->left()); 413 Print(" %s ", Token::String(node->op())); 414 Visit(node->right()); 415 Print(")"); 416 } 417 418 419 void PrettyPrinter::VisitCompareOperation(CompareOperation* node) { 420 Print("("); 421 Visit(node->left()); 422 Print(" %s ", Token::String(node->op())); 423 Visit(node->right()); 424 Print(")"); 425 } 426 427 428 void PrettyPrinter::VisitThisFunction(ThisFunction* node) { 429 Print("<this-function>"); 430 } 431 432 433 const char* PrettyPrinter::Print(AstNode* node) { 434 Init(); 435 Visit(node); 436 return output_; 437 } 438 439 440 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) { 441 Init(); 442 ExpressionStatement* statement = 443 program->body()->at(0)->AsExpressionStatement(); 444 Visit(statement->expression()); 445 return output_; 446 } 447 448 449 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) { 450 Init(); 451 PrintStatements(program->body()); 452 Print("\n"); 453 return output_; 454 } 455 456 457 void PrettyPrinter::PrintOut(AstNode* node) { 458 PrettyPrinter printer; 459 PrintF("%s", printer.Print(node)); 460 } 461 462 463 void PrettyPrinter::Init() { 464 if (size_ == 0) { 465 ASSERT(output_ == NULL); 466 const int initial_size = 256; 467 output_ = NewArray<char>(initial_size); 468 size_ = initial_size; 469 } 470 output_[0] = '\0'; 471 pos_ = 0; 472 } 473 474 475 void PrettyPrinter::Print(const char* format, ...) { 476 for (;;) { 477 va_list arguments; 478 va_start(arguments, format); 479 int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_, 480 format, 481 arguments); 482 va_end(arguments); 483 484 if (n >= 0) { 485 // there was enough space - we are done 486 pos_ += n; 487 return; 488 } else { 489 // there was not enough space - allocate more and try again 490 const int slack = 32; 491 int new_size = size_ + (size_ >> 1) + slack; 492 char* new_output = NewArray<char>(new_size); 493 memcpy(new_output, output_, pos_); 494 DeleteArray(output_); 495 output_ = new_output; 496 size_ = new_size; 497 } 498 } 499 } 500 501 502 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) { 503 if (statements == NULL) return; 504 for (int i = 0; i < statements->length(); i++) { 505 if (i != 0) Print(" "); 506 Visit(statements->at(i)); 507 } 508 } 509 510 511 void PrettyPrinter::PrintLabels(ZoneStringList* labels) { 512 if (labels != NULL) { 513 for (int i = 0; i < labels->length(); i++) { 514 PrintLiteral(labels->at(i), false); 515 Print(": "); 516 } 517 } 518 } 519 520 521 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 522 Print("("); 523 for (int i = 0; i < arguments->length(); i++) { 524 if (i != 0) Print(", "); 525 Visit(arguments->at(i)); 526 } 527 Print(")"); 528 } 529 530 531 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) { 532 Object* object = *value; 533 if (object->IsString()) { 534 String* string = String::cast(object); 535 if (quote) Print("\""); 536 for (int i = 0; i < string->length(); i++) { 537 Print("%c", string->Get(i)); 538 } 539 if (quote) Print("\""); 540 } else if (object->IsNull()) { 541 Print("null"); 542 } else if (object->IsTrue()) { 543 Print("true"); 544 } else if (object->IsFalse()) { 545 Print("false"); 546 } else if (object->IsUndefined()) { 547 Print("undefined"); 548 } else if (object->IsNumber()) { 549 Print("%g", object->Number()); 550 } else if (object->IsJSObject()) { 551 // regular expression 552 if (object->IsJSFunction()) { 553 Print("JS-Function"); 554 } else if (object->IsJSArray()) { 555 Print("JS-array[%u]", JSArray::cast(object)->length()); 556 } else if (object->IsJSObject()) { 557 Print("JS-Object"); 558 } else { 559 Print("?UNKNOWN?"); 560 } 561 } else if (object->IsFixedArray()) { 562 Print("FixedArray"); 563 } else { 564 Print("<unknown literal %p>", object); 565 } 566 } 567 568 569 void PrettyPrinter::PrintParameters(Scope* scope) { 570 Print("("); 571 for (int i = 0; i < scope->num_parameters(); i++) { 572 if (i > 0) Print(", "); 573 PrintLiteral(scope->parameter(i)->name(), false); 574 } 575 Print(")"); 576 } 577 578 579 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { 580 for (int i = 0; i < declarations->length(); i++) { 581 if (i > 0) Print(" "); 582 Visit(declarations->at(i)); 583 } 584 } 585 586 587 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) { 588 Print("function "); 589 PrintLiteral(function->name(), false); 590 PrintParameters(function->scope()); 591 Print(" { "); 592 PrintDeclarations(function->scope()->declarations()); 593 PrintStatements(function->body()); 594 Print(" }"); 595 } 596 597 598 void PrettyPrinter::PrintCaseClause(CaseClause* clause) { 599 if (clause->is_default()) { 600 Print("default"); 601 } else { 602 Print("case "); 603 Visit(clause->label()); 604 } 605 Print(": "); 606 PrintStatements(clause->statements()); 607 if (clause->statements()->length() > 0) 608 Print(" "); 609 } 610 611 612 //----------------------------------------------------------------------------- 613 614 class IndentedScope BASE_EMBEDDED { 615 public: 616 explicit IndentedScope(AstPrinter* printer) : ast_printer_(printer) { 617 ast_printer_->inc_indent(); 618 } 619 620 IndentedScope(AstPrinter* printer, const char* txt, AstNode* node = NULL) 621 : ast_printer_(printer) { 622 ast_printer_->PrintIndented(txt); 623 ast_printer_->Print("\n"); 624 ast_printer_->inc_indent(); 625 } 626 627 virtual ~IndentedScope() { 628 ast_printer_->dec_indent(); 629 } 630 631 private: 632 AstPrinter* ast_printer_; 633 }; 634 635 636 //----------------------------------------------------------------------------- 637 638 639 AstPrinter::AstPrinter() : indent_(0) { 640 } 641 642 643 AstPrinter::~AstPrinter() { 644 ASSERT(indent_ == 0); 645 } 646 647 648 void AstPrinter::PrintIndented(const char* txt) { 649 for (int i = 0; i < indent_; i++) { 650 Print(". "); 651 } 652 Print(txt); 653 } 654 655 656 void AstPrinter::PrintLiteralIndented(const char* info, 657 Handle<Object> value, 658 bool quote) { 659 PrintIndented(info); 660 Print(" "); 661 PrintLiteral(value, quote); 662 Print("\n"); 663 } 664 665 666 void AstPrinter::PrintLiteralWithModeIndented(const char* info, 667 Variable* var, 668 Handle<Object> value) { 669 if (var == NULL) { 670 PrintLiteralIndented(info, value, true); 671 } else { 672 EmbeddedVector<char, 256> buf; 673 int pos = OS::SNPrintF(buf, "%s (mode = %s", info, 674 Variable::Mode2String(var->mode())); 675 OS::SNPrintF(buf + pos, ")"); 676 PrintLiteralIndented(buf.start(), value, true); 677 } 678 } 679 680 681 void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) { 682 if (labels != NULL && labels->length() > 0) { 683 PrintIndented(info == NULL ? "LABELS" : info); 684 Print(" "); 685 PrintLabels(labels); 686 Print("\n"); 687 } else if (info != NULL) { 688 PrintIndented(info); 689 Print("\n"); 690 } 691 } 692 693 694 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { 695 IndentedScope indent(this, s, node); 696 Visit(node); 697 } 698 699 700 const char* AstPrinter::PrintProgram(FunctionLiteral* program) { 701 Init(); 702 { IndentedScope indent(this, "FUNC"); 703 PrintLiteralIndented("NAME", program->name(), true); 704 PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true); 705 PrintParameters(program->scope()); 706 PrintDeclarations(program->scope()->declarations()); 707 PrintStatements(program->body()); 708 } 709 return Output(); 710 } 711 712 713 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { 714 if (declarations->length() > 0) { 715 IndentedScope indent(this, "DECLS"); 716 for (int i = 0; i < declarations->length(); i++) { 717 Visit(declarations->at(i)); 718 } 719 } 720 } 721 722 723 void AstPrinter::PrintParameters(Scope* scope) { 724 if (scope->num_parameters() > 0) { 725 IndentedScope indent(this, "PARAMS"); 726 for (int i = 0; i < scope->num_parameters(); i++) { 727 PrintLiteralWithModeIndented("VAR", scope->parameter(i), 728 scope->parameter(i)->name()); 729 } 730 } 731 } 732 733 734 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) { 735 for (int i = 0; i < statements->length(); i++) { 736 Visit(statements->at(i)); 737 } 738 } 739 740 741 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 742 for (int i = 0; i < arguments->length(); i++) { 743 Visit(arguments->at(i)); 744 } 745 } 746 747 748 void AstPrinter::PrintCaseClause(CaseClause* clause) { 749 if (clause->is_default()) { 750 IndentedScope indent(this, "DEFAULT"); 751 PrintStatements(clause->statements()); 752 } else { 753 IndentedScope indent(this, "CASE"); 754 Visit(clause->label()); 755 PrintStatements(clause->statements()); 756 } 757 } 758 759 760 void AstPrinter::VisitBlock(Block* node) { 761 const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK"; 762 IndentedScope indent(this, block_txt); 763 PrintStatements(node->statements()); 764 } 765 766 767 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 768 PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()), 769 node->proxy()->var(), 770 node->proxy()->name()); 771 } 772 773 774 void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { 775 PrintIndented("FUNCTION "); 776 PrintLiteral(node->proxy()->name(), true); 777 Print(" = function "); 778 PrintLiteral(node->fun()->name(), false); 779 Print("\n"); 780 } 781 782 783 void AstPrinter::VisitModuleDeclaration(ModuleDeclaration* node) { 784 IndentedScope indent(this, "MODULE"); 785 PrintLiteralIndented("NAME", node->proxy()->name(), true); 786 Visit(node->module()); 787 } 788 789 790 void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) { 791 IndentedScope indent(this, "IMPORT"); 792 PrintLiteralIndented("NAME", node->proxy()->name(), true); 793 Visit(node->module()); 794 } 795 796 797 void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) { 798 IndentedScope indent(this, "EXPORT "); 799 PrintLiteral(node->proxy()->name(), true); 800 } 801 802 803 void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) { 804 VisitBlock(node->body()); 805 } 806 807 808 void AstPrinter::VisitModuleVariable(ModuleVariable* node) { 809 Visit(node->proxy()); 810 } 811 812 813 void AstPrinter::VisitModulePath(ModulePath* node) { 814 IndentedScope indent(this, "PATH"); 815 PrintIndentedVisit("MODULE", node->module()); 816 PrintLiteralIndented("NAME", node->name(), false); 817 } 818 819 820 void AstPrinter::VisitModuleUrl(ModuleUrl* node) { 821 PrintLiteralIndented("URL", node->url(), true); 822 } 823 824 825 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { 826 Visit(node->expression()); 827 } 828 829 830 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { 831 PrintIndented("EMPTY\n"); 832 } 833 834 835 void AstPrinter::VisitIfStatement(IfStatement* node) { 836 PrintIndentedVisit("IF", node->condition()); 837 PrintIndentedVisit("THEN", node->then_statement()); 838 if (node->HasElseStatement()) { 839 PrintIndentedVisit("ELSE", node->else_statement()); 840 } 841 } 842 843 844 void AstPrinter::VisitContinueStatement(ContinueStatement* node) { 845 PrintLabelsIndented("CONTINUE", node->target()->labels()); 846 } 847 848 849 void AstPrinter::VisitBreakStatement(BreakStatement* node) { 850 PrintLabelsIndented("BREAK", node->target()->labels()); 851 } 852 853 854 void AstPrinter::VisitReturnStatement(ReturnStatement* node) { 855 PrintIndentedVisit("RETURN", node->expression()); 856 } 857 858 859 void AstPrinter::VisitWithStatement(WithStatement* node) { 860 IndentedScope indent(this, "WITH"); 861 PrintIndentedVisit("OBJECT", node->expression()); 862 PrintIndentedVisit("BODY", node->statement()); 863 } 864 865 866 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) { 867 IndentedScope indent(this, "SWITCH"); 868 PrintLabelsIndented(NULL, node->labels()); 869 PrintIndentedVisit("TAG", node->tag()); 870 for (int i = 0; i < node->cases()->length(); i++) { 871 PrintCaseClause(node->cases()->at(i)); 872 } 873 } 874 875 876 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 877 IndentedScope indent(this, "DO"); 878 PrintLabelsIndented(NULL, node->labels()); 879 PrintIndentedVisit("BODY", node->body()); 880 PrintIndentedVisit("COND", node->cond()); 881 } 882 883 884 void AstPrinter::VisitWhileStatement(WhileStatement* node) { 885 IndentedScope indent(this, "WHILE"); 886 PrintLabelsIndented(NULL, node->labels()); 887 PrintIndentedVisit("COND", node->cond()); 888 PrintIndentedVisit("BODY", node->body()); 889 } 890 891 892 void AstPrinter::VisitForStatement(ForStatement* node) { 893 IndentedScope indent(this, "FOR"); 894 PrintLabelsIndented(NULL, node->labels()); 895 if (node->init()) PrintIndentedVisit("INIT", node->init()); 896 if (node->cond()) PrintIndentedVisit("COND", node->cond()); 897 PrintIndentedVisit("BODY", node->body()); 898 if (node->next()) PrintIndentedVisit("NEXT", node->next()); 899 } 900 901 902 void AstPrinter::VisitForInStatement(ForInStatement* node) { 903 IndentedScope indent(this, "FOR IN"); 904 PrintIndentedVisit("FOR", node->each()); 905 PrintIndentedVisit("IN", node->enumerable()); 906 PrintIndentedVisit("BODY", node->body()); 907 } 908 909 910 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 911 IndentedScope indent(this, "TRY CATCH"); 912 PrintIndentedVisit("TRY", node->try_block()); 913 PrintLiteralWithModeIndented("CATCHVAR", 914 node->variable(), 915 node->variable()->name()); 916 PrintIndentedVisit("CATCH", node->catch_block()); 917 } 918 919 920 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 921 IndentedScope indent(this, "TRY FINALLY"); 922 PrintIndentedVisit("TRY", node->try_block()); 923 PrintIndentedVisit("FINALLY", node->finally_block()); 924 } 925 926 927 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 928 IndentedScope indent(this, "DEBUGGER"); 929 } 930 931 932 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 933 IndentedScope indent(this, "FUNC LITERAL"); 934 PrintLiteralIndented("NAME", node->name(), false); 935 PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false); 936 PrintParameters(node->scope()); 937 // We don't want to see the function literal in this case: it 938 // will be printed via PrintProgram when the code for it is 939 // generated. 940 // PrintStatements(node->body()); 941 } 942 943 944 void AstPrinter::VisitSharedFunctionInfoLiteral( 945 SharedFunctionInfoLiteral* node) { 946 IndentedScope indent(this, "FUNC LITERAL"); 947 PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true); 948 } 949 950 951 void AstPrinter::VisitConditional(Conditional* node) { 952 IndentedScope indent(this, "CONDITIONAL"); 953 PrintIndentedVisit("?", node->condition()); 954 PrintIndentedVisit("THEN", node->then_expression()); 955 PrintIndentedVisit("ELSE", node->else_expression()); 956 } 957 958 959 void AstPrinter::VisitLiteral(Literal* node) { 960 PrintLiteralIndented("LITERAL", node->handle(), true); 961 } 962 963 964 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 965 IndentedScope indent(this, "REGEXP LITERAL"); 966 PrintLiteralIndented("PATTERN", node->pattern(), false); 967 PrintLiteralIndented("FLAGS", node->flags(), false); 968 } 969 970 971 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) { 972 IndentedScope indent(this, "OBJ LITERAL"); 973 for (int i = 0; i < node->properties()->length(); i++) { 974 const char* prop_kind = NULL; 975 switch (node->properties()->at(i)->kind()) { 976 case ObjectLiteral::Property::CONSTANT: 977 prop_kind = "PROPERTY - CONSTANT"; 978 break; 979 case ObjectLiteral::Property::COMPUTED: 980 prop_kind = "PROPERTY - COMPUTED"; 981 break; 982 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 983 prop_kind = "PROPERTY - MATERIALIZED_LITERAL"; 984 break; 985 case ObjectLiteral::Property::PROTOTYPE: 986 prop_kind = "PROPERTY - PROTOTYPE"; 987 break; 988 case ObjectLiteral::Property::GETTER: 989 prop_kind = "PROPERTY - GETTER"; 990 break; 991 case ObjectLiteral::Property::SETTER: 992 prop_kind = "PROPERTY - SETTER"; 993 break; 994 default: 995 UNREACHABLE(); 996 } 997 IndentedScope prop(this, prop_kind); 998 PrintIndentedVisit("KEY", node->properties()->at(i)->key()); 999 PrintIndentedVisit("VALUE", node->properties()->at(i)->value()); 1000 } 1001 } 1002 1003 1004 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) { 1005 IndentedScope indent(this, "ARRAY LITERAL"); 1006 if (node->values()->length() > 0) { 1007 IndentedScope indent(this, "VALUES"); 1008 for (int i = 0; i < node->values()->length(); i++) { 1009 Visit(node->values()->at(i)); 1010 } 1011 } 1012 } 1013 1014 1015 void AstPrinter::VisitVariableProxy(VariableProxy* node) { 1016 Variable* var = node->var(); 1017 EmbeddedVector<char, 128> buf; 1018 int pos = OS::SNPrintF(buf, "VAR PROXY"); 1019 switch (var->location()) { 1020 case Variable::UNALLOCATED: 1021 break; 1022 case Variable::PARAMETER: 1023 OS::SNPrintF(buf + pos, " parameter[%d]", var->index()); 1024 break; 1025 case Variable::LOCAL: 1026 OS::SNPrintF(buf + pos, " local[%d]", var->index()); 1027 break; 1028 case Variable::CONTEXT: 1029 OS::SNPrintF(buf + pos, " context[%d]", var->index()); 1030 break; 1031 case Variable::LOOKUP: 1032 OS::SNPrintF(buf + pos, " lookup"); 1033 break; 1034 } 1035 PrintLiteralWithModeIndented(buf.start(), var, node->name()); 1036 } 1037 1038 1039 void AstPrinter::VisitAssignment(Assignment* node) { 1040 IndentedScope indent(this, Token::Name(node->op()), node); 1041 Visit(node->target()); 1042 Visit(node->value()); 1043 } 1044 1045 1046 void AstPrinter::VisitThrow(Throw* node) { 1047 PrintIndentedVisit("THROW", node->exception()); 1048 } 1049 1050 1051 void AstPrinter::VisitProperty(Property* node) { 1052 IndentedScope indent(this, "PROPERTY", node); 1053 Visit(node->obj()); 1054 Literal* literal = node->key()->AsLiteral(); 1055 if (literal != NULL && literal->handle()->IsSymbol()) { 1056 PrintLiteralIndented("NAME", literal->handle(), false); 1057 } else { 1058 PrintIndentedVisit("KEY", node->key()); 1059 } 1060 } 1061 1062 1063 void AstPrinter::VisitCall(Call* node) { 1064 IndentedScope indent(this, "CALL"); 1065 Visit(node->expression()); 1066 PrintArguments(node->arguments()); 1067 } 1068 1069 1070 void AstPrinter::VisitCallNew(CallNew* node) { 1071 IndentedScope indent(this, "CALL NEW"); 1072 Visit(node->expression()); 1073 PrintArguments(node->arguments()); 1074 } 1075 1076 1077 void AstPrinter::VisitCallRuntime(CallRuntime* node) { 1078 PrintLiteralIndented("CALL RUNTIME ", node->name(), false); 1079 IndentedScope indent(this); 1080 PrintArguments(node->arguments()); 1081 } 1082 1083 1084 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { 1085 PrintIndentedVisit(Token::Name(node->op()), node->expression()); 1086 } 1087 1088 1089 void AstPrinter::VisitCountOperation(CountOperation* node) { 1090 EmbeddedVector<char, 128> buf; 1091 OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"), 1092 Token::Name(node->op())); 1093 PrintIndentedVisit(buf.start(), node->expression()); 1094 } 1095 1096 1097 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) { 1098 IndentedScope indent(this, Token::Name(node->op()), node); 1099 Visit(node->left()); 1100 Visit(node->right()); 1101 } 1102 1103 1104 void AstPrinter::VisitCompareOperation(CompareOperation* node) { 1105 IndentedScope indent(this, Token::Name(node->op()), node); 1106 Visit(node->left()); 1107 Visit(node->right()); 1108 } 1109 1110 1111 void AstPrinter::VisitThisFunction(ThisFunction* node) { 1112 IndentedScope indent(this, "THIS-FUNCTION"); 1113 } 1114 1115 #endif // DEBUG 1116 1117 } } // namespace v8::internal 1118