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