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