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 36namespace v8 { 37namespace internal { 38 39#ifdef DEBUG 40 41PrettyPrinter::PrettyPrinter() { 42 output_ = NULL; 43 size_ = 0; 44 pos_ = 0; 45} 46 47 48PrettyPrinter::~PrettyPrinter() { 49 DeleteArray(output_); 50} 51 52 53void 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 61void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 62 Print("var "); 63 PrintLiteral(node->proxy()->name(), false); 64 Print(";"); 65} 66 67 68void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { 69 Print("function "); 70 PrintLiteral(node->proxy()->name(), false); 71 Print(" = "); 72 PrintFunctionLiteral(node->fun()); 73 Print(";"); 74} 75 76 77void PrettyPrinter::VisitModuleDeclaration(ModuleDeclaration* node) { 78 Print("module "); 79 PrintLiteral(node->proxy()->name(), false); 80 Print(" = "); 81 Visit(node->module()); 82 Print(";"); 83} 84 85 86void 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 95void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) { 96 Print("export "); 97 PrintLiteral(node->proxy()->name(), false); 98 Print(";"); 99} 100 101 102void PrettyPrinter::VisitModuleLiteral(ModuleLiteral* node) { 103 VisitBlock(node->body()); 104} 105 106 107void PrettyPrinter::VisitModuleVariable(ModuleVariable* node) { 108 Visit(node->proxy()); 109} 110 111 112void PrettyPrinter::VisitModulePath(ModulePath* node) { 113 Visit(node->module()); 114 Print("."); 115 PrintLiteral(node->name(), false); 116} 117 118 119void PrettyPrinter::VisitModuleUrl(ModuleUrl* node) { 120 Print("at "); 121 PrintLiteral(node->url(), true); 122} 123 124 125void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) { 126 Visit(node->expression()); 127 Print(";"); 128} 129 130 131void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) { 132 Print(";"); 133} 134 135 136void 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 148void 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 160void 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 172void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { 173 Print("return "); 174 Visit(node->expression()); 175 Print(";"); 176} 177 178 179void PrettyPrinter::VisitWithStatement(WithStatement* node) { 180 Print("with ("); 181 Visit(node->expression()); 182 Print(") "); 183 Visit(node->statement()); 184} 185 186 187void 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 199void 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 209void PrettyPrinter::VisitWhileStatement(WhileStatement* node) { 210 PrintLabels(node->labels()); 211 Print("while ("); 212 Visit(node->cond()); 213 Print(") "); 214 Visit(node->body()); 215} 216 217 218void 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 238void 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 249void 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 260void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 261 Print("try "); 262 Visit(node->try_block()); 263 Print(" finally "); 264 Visit(node->finally_block()); 265} 266 267 268void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 269 Print("debugger "); 270} 271 272 273void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 274 Print("("); 275 PrintFunctionLiteral(node); 276 Print(")"); 277} 278 279 280void PrettyPrinter::VisitSharedFunctionInfoLiteral( 281 SharedFunctionInfoLiteral* node) { 282 Print("("); 283 PrintLiteral(node->shared_function_info(), true); 284 Print(")"); 285} 286 287 288void 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 297void PrettyPrinter::VisitLiteral(Literal* node) { 298 PrintLiteral(node->handle(), true); 299} 300 301 302void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 303 Print(" RegExp("); 304 PrintLiteral(node->pattern(), false); 305 Print(","); 306 PrintLiteral(node->flags(), false); 307 Print(") "); 308} 309 310 311void 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 325void 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 335void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { 336 PrintLiteral(node->name(), false); 337} 338 339 340void PrettyPrinter::VisitAssignment(Assignment* node) { 341 Visit(node->target()); 342 Print(" %s ", Token::String(node->op())); 343 Visit(node->value()); 344} 345 346 347void PrettyPrinter::VisitThrow(Throw* node) { 348 Print("throw "); 349 Visit(node->exception()); 350} 351 352 353void 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 370void PrettyPrinter::VisitCall(Call* node) { 371 Visit(node->expression()); 372 PrintArguments(node->arguments()); 373} 374 375 376void PrettyPrinter::VisitCallNew(CallNew* node) { 377 Print("new ("); 378 Visit(node->expression()); 379 Print(")"); 380 PrintArguments(node->arguments()); 381} 382 383 384void PrettyPrinter::VisitCallRuntime(CallRuntime* node) { 385 Print("%%"); 386 PrintLiteral(node->name(), false); 387 PrintArguments(node->arguments()); 388} 389 390 391void 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 401void 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 410void 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 419void 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 428void PrettyPrinter::VisitThisFunction(ThisFunction* node) { 429 Print("<this-function>"); 430} 431 432 433const char* PrettyPrinter::Print(AstNode* node) { 434 Init(); 435 Visit(node); 436 return output_; 437} 438 439 440const 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 449const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) { 450 Init(); 451 PrintStatements(program->body()); 452 Print("\n"); 453 return output_; 454} 455 456 457void PrettyPrinter::PrintOut(AstNode* node) { 458 PrettyPrinter printer; 459 PrintF("%s", printer.Print(node)); 460} 461 462 463void 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 475void 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 502void 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 511void 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 521void 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 531void 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 569void 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 579void 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 587void 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 598void 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 614class 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 639AstPrinter::AstPrinter() : indent_(0) { 640} 641 642 643AstPrinter::~AstPrinter() { 644 ASSERT(indent_ == 0); 645} 646 647 648void AstPrinter::PrintIndented(const char* txt) { 649 for (int i = 0; i < indent_; i++) { 650 Print(". "); 651 } 652 Print(txt); 653} 654 655 656void 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 666void 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 681void 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 694void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { 695 IndentedScope indent(this, s, node); 696 Visit(node); 697} 698 699 700const 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 713void 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 723void 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 734void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) { 735 for (int i = 0; i < statements->length(); i++) { 736 Visit(statements->at(i)); 737 } 738} 739 740 741void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 742 for (int i = 0; i < arguments->length(); i++) { 743 Visit(arguments->at(i)); 744 } 745} 746 747 748void 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 760void 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 767void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 768 PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()), 769 node->proxy()->var(), 770 node->proxy()->name()); 771} 772 773 774void 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 783void AstPrinter::VisitModuleDeclaration(ModuleDeclaration* node) { 784 IndentedScope indent(this, "MODULE"); 785 PrintLiteralIndented("NAME", node->proxy()->name(), true); 786 Visit(node->module()); 787} 788 789 790void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) { 791 IndentedScope indent(this, "IMPORT"); 792 PrintLiteralIndented("NAME", node->proxy()->name(), true); 793 Visit(node->module()); 794} 795 796 797void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) { 798 IndentedScope indent(this, "EXPORT "); 799 PrintLiteral(node->proxy()->name(), true); 800} 801 802 803void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) { 804 VisitBlock(node->body()); 805} 806 807 808void AstPrinter::VisitModuleVariable(ModuleVariable* node) { 809 Visit(node->proxy()); 810} 811 812 813void AstPrinter::VisitModulePath(ModulePath* node) { 814 IndentedScope indent(this, "PATH"); 815 PrintIndentedVisit("MODULE", node->module()); 816 PrintLiteralIndented("NAME", node->name(), false); 817} 818 819 820void AstPrinter::VisitModuleUrl(ModuleUrl* node) { 821 PrintLiteralIndented("URL", node->url(), true); 822} 823 824 825void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { 826 Visit(node->expression()); 827} 828 829 830void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { 831 PrintIndented("EMPTY\n"); 832} 833 834 835void 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 844void AstPrinter::VisitContinueStatement(ContinueStatement* node) { 845 PrintLabelsIndented("CONTINUE", node->target()->labels()); 846} 847 848 849void AstPrinter::VisitBreakStatement(BreakStatement* node) { 850 PrintLabelsIndented("BREAK", node->target()->labels()); 851} 852 853 854void AstPrinter::VisitReturnStatement(ReturnStatement* node) { 855 PrintIndentedVisit("RETURN", node->expression()); 856} 857 858 859void AstPrinter::VisitWithStatement(WithStatement* node) { 860 IndentedScope indent(this, "WITH"); 861 PrintIndentedVisit("OBJECT", node->expression()); 862 PrintIndentedVisit("BODY", node->statement()); 863} 864 865 866void 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 876void 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 884void 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 892void 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 902void 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 910void 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 920void 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 927void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 928 IndentedScope indent(this, "DEBUGGER"); 929} 930 931 932void 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 944void AstPrinter::VisitSharedFunctionInfoLiteral( 945 SharedFunctionInfoLiteral* node) { 946 IndentedScope indent(this, "FUNC LITERAL"); 947 PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true); 948} 949 950 951void 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 959void AstPrinter::VisitLiteral(Literal* node) { 960 PrintLiteralIndented("LITERAL", node->handle(), true); 961} 962 963 964void 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 971void 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 1004void 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 1015void 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 1039void AstPrinter::VisitAssignment(Assignment* node) { 1040 IndentedScope indent(this, Token::Name(node->op()), node); 1041 Visit(node->target()); 1042 Visit(node->value()); 1043} 1044 1045 1046void AstPrinter::VisitThrow(Throw* node) { 1047 PrintIndentedVisit("THROW", node->exception()); 1048} 1049 1050 1051void 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 1063void AstPrinter::VisitCall(Call* node) { 1064 IndentedScope indent(this, "CALL"); 1065 Visit(node->expression()); 1066 PrintArguments(node->arguments()); 1067} 1068 1069 1070void AstPrinter::VisitCallNew(CallNew* node) { 1071 IndentedScope indent(this, "CALL NEW"); 1072 Visit(node->expression()); 1073 PrintArguments(node->arguments()); 1074} 1075 1076 1077void AstPrinter::VisitCallRuntime(CallRuntime* node) { 1078 PrintLiteralIndented("CALL RUNTIME ", node->name(), false); 1079 IndentedScope indent(this); 1080 PrintArguments(node->arguments()); 1081} 1082 1083 1084void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { 1085 PrintIndentedVisit(Token::Name(node->op()), node->expression()); 1086} 1087 1088 1089void 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 1097void AstPrinter::VisitBinaryOperation(BinaryOperation* node) { 1098 IndentedScope indent(this, Token::Name(node->op()), node); 1099 Visit(node->left()); 1100 Visit(node->right()); 1101} 1102 1103 1104void AstPrinter::VisitCompareOperation(CompareOperation* node) { 1105 IndentedScope indent(this, Token::Name(node->op()), node); 1106 Visit(node->left()); 1107 Visit(node->right()); 1108} 1109 1110 1111void AstPrinter::VisitThisFunction(ThisFunction* node) { 1112 IndentedScope indent(this, "THIS-FUNCTION"); 1113} 1114 1115#endif // DEBUG 1116 1117} } // namespace v8::internal 1118