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