1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include <stdarg.h> 29 30 #include "v8.h" 31 32 #include "prettyprinter.h" 33 #include "scopes.h" 34 #include "platform.h" 35 36 namespace v8 { 37 namespace internal { 38 39 #ifdef DEBUG 40 41 PrettyPrinter::PrettyPrinter() { 42 output_ = NULL; 43 size_ = 0; 44 pos_ = 0; 45 } 46 47 48 PrettyPrinter::~PrettyPrinter() { 49 DeleteArray(output_); 50 } 51 52 53 void PrettyPrinter::VisitBlock(Block* node) { 54 if (!node->is_initializer_block()) Print("{ "); 55 PrintStatements(node->statements()); 56 if (node->statements()->length() > 0) Print(" "); 57 if (!node->is_initializer_block()) Print("}"); 58 } 59 60 61 void PrettyPrinter::VisitDeclaration(Declaration* node) { 62 Print("var "); 63 PrintLiteral(node->proxy()->name(), false); 64 if (node->fun() != NULL) { 65 Print(" = "); 66 PrintFunctionLiteral(node->fun()); 67 } 68 Print(";"); 69 } 70 71 72 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) { 73 Visit(node->expression()); 74 Print(";"); 75 } 76 77 78 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) { 79 Print(";"); 80 } 81 82 83 void PrettyPrinter::VisitIfStatement(IfStatement* node) { 84 Print("if ("); 85 Visit(node->condition()); 86 Print(") "); 87 Visit(node->then_statement()); 88 if (node->HasElseStatement()) { 89 Print(" else "); 90 Visit(node->else_statement()); 91 } 92 } 93 94 95 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) { 96 Print("continue"); 97 ZoneStringList* labels = node->target()->labels(); 98 if (labels != NULL) { 99 Print(" "); 100 ASSERT(labels->length() > 0); // guaranteed to have at least one entry 101 PrintLiteral(labels->at(0), false); // any label from the list is fine 102 } 103 Print(";"); 104 } 105 106 107 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) { 108 Print("break"); 109 ZoneStringList* labels = node->target()->labels(); 110 if (labels != NULL) { 111 Print(" "); 112 ASSERT(labels->length() > 0); // guaranteed to have at least one entry 113 PrintLiteral(labels->at(0), false); // any label from the list is fine 114 } 115 Print(";"); 116 } 117 118 119 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { 120 Print("return "); 121 Visit(node->expression()); 122 Print(";"); 123 } 124 125 126 void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) { 127 Print("<enter with> ("); 128 Visit(node->expression()); 129 Print(") "); 130 } 131 132 133 void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) { 134 Print("<exit with>"); 135 } 136 137 138 void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) { 139 PrintLabels(node->labels()); 140 Print("switch ("); 141 Visit(node->tag()); 142 Print(") { "); 143 ZoneList<CaseClause*>* cases = node->cases(); 144 for (int i = 0; i < cases->length(); i++) 145 PrintCaseClause(cases->at(i)); 146 Print("}"); 147 } 148 149 150 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 151 PrintLabels(node->labels()); 152 Print("do "); 153 Visit(node->body()); 154 Print(" while ("); 155 Visit(node->cond()); 156 Print(");"); 157 } 158 159 160 void PrettyPrinter::VisitWhileStatement(WhileStatement* node) { 161 PrintLabels(node->labels()); 162 Print("while ("); 163 Visit(node->cond()); 164 Print(") "); 165 Visit(node->body()); 166 } 167 168 169 void PrettyPrinter::VisitForStatement(ForStatement* node) { 170 PrintLabels(node->labels()); 171 Print("for ("); 172 if (node->init() != NULL) { 173 Visit(node->init()); 174 Print(" "); 175 } else { 176 Print("; "); 177 } 178 if (node->cond() != NULL) Visit(node->cond()); 179 Print("; "); 180 if (node->next() != NULL) { 181 Visit(node->next()); // prints extra ';', unfortunately 182 // to fix: should use Expression for next 183 } 184 Print(") "); 185 Visit(node->body()); 186 } 187 188 189 void PrettyPrinter::VisitForInStatement(ForInStatement* node) { 190 PrintLabels(node->labels()); 191 Print("for ("); 192 Visit(node->each()); 193 Print(" in "); 194 Visit(node->enumerable()); 195 Print(") "); 196 Visit(node->body()); 197 } 198 199 200 void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 201 Print("try "); 202 Visit(node->try_block()); 203 Print(" catch ("); 204 Visit(node->catch_var()); 205 Print(") "); 206 Visit(node->catch_block()); 207 } 208 209 210 void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 211 Print("try "); 212 Visit(node->try_block()); 213 Print(" finally "); 214 Visit(node->finally_block()); 215 } 216 217 218 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 219 Print("debugger "); 220 } 221 222 223 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 224 Print("("); 225 PrintFunctionLiteral(node); 226 Print(")"); 227 } 228 229 230 void PrettyPrinter::VisitSharedFunctionInfoLiteral( 231 SharedFunctionInfoLiteral* node) { 232 Print("("); 233 PrintLiteral(node->shared_function_info(), true); 234 Print(")"); 235 } 236 237 238 void PrettyPrinter::VisitConditional(Conditional* node) { 239 Visit(node->condition()); 240 Print(" ? "); 241 Visit(node->then_expression()); 242 Print(" : "); 243 Visit(node->else_expression()); 244 } 245 246 247 void PrettyPrinter::VisitLiteral(Literal* node) { 248 PrintLiteral(node->handle(), true); 249 } 250 251 252 void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 253 Print(" RegExp("); 254 PrintLiteral(node->pattern(), false); 255 Print(","); 256 PrintLiteral(node->flags(), false); 257 Print(") "); 258 } 259 260 261 void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) { 262 Print("{ "); 263 for (int i = 0; i < node->properties()->length(); i++) { 264 if (i != 0) Print(","); 265 ObjectLiteral::Property* property = node->properties()->at(i); 266 Print(" "); 267 Visit(property->key()); 268 Print(": "); 269 Visit(property->value()); 270 } 271 Print(" }"); 272 } 273 274 275 void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) { 276 Print("[ "); 277 for (int i = 0; i < node->values()->length(); i++) { 278 if (i != 0) Print(","); 279 Visit(node->values()->at(i)); 280 } 281 Print(" ]"); 282 } 283 284 285 void PrettyPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) { 286 Print("{ "); 287 Visit(node->key()); 288 Print(": "); 289 Visit(node->value()); 290 Print(" }"); 291 } 292 293 294 void PrettyPrinter::VisitSlot(Slot* node) { 295 switch (node->type()) { 296 case Slot::PARAMETER: 297 Print("parameter[%d]", node->index()); 298 break; 299 case Slot::LOCAL: 300 Print("local[%d]", node->index()); 301 break; 302 case Slot::CONTEXT: 303 Print("context[%d]", node->index()); 304 break; 305 case Slot::LOOKUP: 306 Print("lookup["); 307 PrintLiteral(node->var()->name(), false); 308 Print("]"); 309 break; 310 default: 311 UNREACHABLE(); 312 } 313 } 314 315 316 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { 317 PrintLiteral(node->name(), false); 318 } 319 320 321 void PrettyPrinter::VisitAssignment(Assignment* node) { 322 Visit(node->target()); 323 Print(" %s ", Token::String(node->op())); 324 Visit(node->value()); 325 } 326 327 328 void PrettyPrinter::VisitThrow(Throw* node) { 329 Print("throw "); 330 Visit(node->exception()); 331 } 332 333 334 void PrettyPrinter::VisitProperty(Property* node) { 335 Expression* key = node->key(); 336 Literal* literal = key->AsLiteral(); 337 if (literal != NULL && literal->handle()->IsSymbol()) { 338 Print("("); 339 Visit(node->obj()); 340 Print(")."); 341 PrintLiteral(literal->handle(), false); 342 } else { 343 Visit(node->obj()); 344 Print("["); 345 Visit(key); 346 Print("]"); 347 } 348 } 349 350 351 void PrettyPrinter::VisitCall(Call* node) { 352 Visit(node->expression()); 353 PrintArguments(node->arguments()); 354 } 355 356 357 void PrettyPrinter::VisitCallNew(CallNew* node) { 358 Print("new ("); 359 Visit(node->expression()); 360 Print(")"); 361 PrintArguments(node->arguments()); 362 } 363 364 365 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) { 366 Print("%%"); 367 PrintLiteral(node->name(), false); 368 PrintArguments(node->arguments()); 369 } 370 371 372 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) { 373 Print("(%s", Token::String(node->op())); 374 Visit(node->expression()); 375 Print(")"); 376 } 377 378 379 void PrettyPrinter::VisitCountOperation(CountOperation* node) { 380 Print("("); 381 if (node->is_prefix()) Print("%s", Token::String(node->op())); 382 Visit(node->expression()); 383 if (node->is_postfix()) Print("%s", Token::String(node->op())); 384 Print(")"); 385 } 386 387 388 void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) { 389 Print("("); 390 Visit(node->left()); 391 Print("%s", Token::String(node->op())); 392 Visit(node->right()); 393 Print(")"); 394 } 395 396 397 void PrettyPrinter::VisitCompareOperation(CompareOperation* node) { 398 Print("("); 399 Visit(node->left()); 400 Print("%s", Token::String(node->op())); 401 Visit(node->right()); 402 Print(")"); 403 } 404 405 406 void PrettyPrinter::VisitCompareToNull(CompareToNull* node) { 407 Print("("); 408 Visit(node->expression()); 409 Print("%s null)", Token::String(node->op())); 410 } 411 412 413 void PrettyPrinter::VisitThisFunction(ThisFunction* node) { 414 Print("<this-function>"); 415 } 416 417 418 const char* PrettyPrinter::Print(AstNode* node) { 419 Init(); 420 Visit(node); 421 return output_; 422 } 423 424 425 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) { 426 Init(); 427 ExpressionStatement* statement = 428 program->body()->at(0)->AsExpressionStatement(); 429 Visit(statement->expression()); 430 return output_; 431 } 432 433 434 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) { 435 Init(); 436 PrintStatements(program->body()); 437 Print("\n"); 438 return output_; 439 } 440 441 442 void PrettyPrinter::PrintOut(AstNode* node) { 443 PrettyPrinter printer; 444 PrintF("%s", printer.Print(node)); 445 } 446 447 448 void PrettyPrinter::Init() { 449 if (size_ == 0) { 450 ASSERT(output_ == NULL); 451 const int initial_size = 256; 452 output_ = NewArray<char>(initial_size); 453 size_ = initial_size; 454 } 455 output_[0] = '\0'; 456 pos_ = 0; 457 } 458 459 460 void PrettyPrinter::Print(const char* format, ...) { 461 for (;;) { 462 va_list arguments; 463 va_start(arguments, format); 464 int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_, 465 format, 466 arguments); 467 va_end(arguments); 468 469 if (n >= 0) { 470 // there was enough space - we are done 471 pos_ += n; 472 return; 473 } else { 474 // there was not enough space - allocate more and try again 475 const int slack = 32; 476 int new_size = size_ + (size_ >> 1) + slack; 477 char* new_output = NewArray<char>(new_size); 478 memcpy(new_output, output_, pos_); 479 DeleteArray(output_); 480 output_ = new_output; 481 size_ = new_size; 482 } 483 } 484 } 485 486 487 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) { 488 for (int i = 0; i < statements->length(); i++) { 489 if (i != 0) Print(" "); 490 Visit(statements->at(i)); 491 } 492 } 493 494 495 void PrettyPrinter::PrintLabels(ZoneStringList* labels) { 496 if (labels != NULL) { 497 for (int i = 0; i < labels->length(); i++) { 498 PrintLiteral(labels->at(i), false); 499 Print(": "); 500 } 501 } 502 } 503 504 505 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 506 Print("("); 507 for (int i = 0; i < arguments->length(); i++) { 508 if (i != 0) Print(", "); 509 Visit(arguments->at(i)); 510 } 511 Print(")"); 512 } 513 514 515 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) { 516 Object* object = *value; 517 if (object->IsString()) { 518 String* string = String::cast(object); 519 if (quote) Print("\""); 520 for (int i = 0; i < string->length(); i++) { 521 Print("%c", string->Get(i)); 522 } 523 if (quote) Print("\""); 524 } else if (object->IsNull()) { 525 Print("null"); 526 } else if (object->IsTrue()) { 527 Print("true"); 528 } else if (object->IsFalse()) { 529 Print("false"); 530 } else if (object->IsUndefined()) { 531 Print("undefined"); 532 } else if (object->IsNumber()) { 533 Print("%g", object->Number()); 534 } else if (object->IsJSObject()) { 535 // regular expression 536 if (object->IsJSFunction()) { 537 Print("JS-Function"); 538 } else if (object->IsJSArray()) { 539 Print("JS-array[%u]", JSArray::cast(object)->length()); 540 } else if (object->IsJSObject()) { 541 Print("JS-Object"); 542 } else { 543 Print("?UNKNOWN?"); 544 } 545 } else if (object->IsFixedArray()) { 546 Print("FixedArray"); 547 } else { 548 Print("<unknown literal %p>", object); 549 } 550 } 551 552 553 void PrettyPrinter::PrintParameters(Scope* scope) { 554 Print("("); 555 for (int i = 0; i < scope->num_parameters(); i++) { 556 if (i > 0) Print(", "); 557 PrintLiteral(scope->parameter(i)->name(), false); 558 } 559 Print(")"); 560 } 561 562 563 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { 564 for (int i = 0; i < declarations->length(); i++) { 565 if (i > 0) Print(" "); 566 Visit(declarations->at(i)); 567 } 568 } 569 570 571 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) { 572 Print("function "); 573 PrintLiteral(function->name(), false); 574 PrintParameters(function->scope()); 575 Print(" { "); 576 PrintDeclarations(function->scope()->declarations()); 577 PrintStatements(function->body()); 578 Print(" }"); 579 } 580 581 582 void PrettyPrinter::PrintCaseClause(CaseClause* clause) { 583 if (clause->is_default()) { 584 Print("default"); 585 } else { 586 Print("case "); 587 Visit(clause->label()); 588 } 589 Print(": "); 590 PrintStatements(clause->statements()); 591 if (clause->statements()->length() > 0) 592 Print(" "); 593 } 594 595 596 //----------------------------------------------------------------------------- 597 598 class IndentedScope BASE_EMBEDDED { 599 public: 600 explicit IndentedScope(AstPrinter* printer) : ast_printer_(printer) { 601 ast_printer_->inc_indent(); 602 } 603 604 IndentedScope(AstPrinter* printer, const char* txt, AstNode* node = NULL) 605 : ast_printer_(printer) { 606 ast_printer_->PrintIndented(txt); 607 ast_printer_->Print("\n"); 608 ast_printer_->inc_indent(); 609 } 610 611 virtual ~IndentedScope() { 612 ast_printer_->dec_indent(); 613 } 614 615 private: 616 AstPrinter* ast_printer_; 617 }; 618 619 620 //----------------------------------------------------------------------------- 621 622 623 AstPrinter::AstPrinter() : indent_(0) { 624 } 625 626 627 AstPrinter::~AstPrinter() { 628 ASSERT(indent_ == 0); 629 } 630 631 632 void AstPrinter::PrintIndented(const char* txt) { 633 for (int i = 0; i < indent_; i++) { 634 Print(". "); 635 } 636 Print(txt); 637 } 638 639 640 void AstPrinter::PrintLiteralIndented(const char* info, 641 Handle<Object> value, 642 bool quote) { 643 PrintIndented(info); 644 Print(" "); 645 PrintLiteral(value, quote); 646 Print("\n"); 647 } 648 649 650 void AstPrinter::PrintLiteralWithModeIndented(const char* info, 651 Variable* var, 652 Handle<Object> value) { 653 if (var == NULL) { 654 PrintLiteralIndented(info, value, true); 655 } else { 656 EmbeddedVector<char, 256> buf; 657 int pos = OS::SNPrintF(buf, "%s (mode = %s", info, 658 Variable::Mode2String(var->mode())); 659 OS::SNPrintF(buf + pos, ")"); 660 PrintLiteralIndented(buf.start(), value, true); 661 } 662 } 663 664 665 void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) { 666 if (labels != NULL && labels->length() > 0) { 667 if (info == NULL) { 668 PrintIndented("LABELS "); 669 } else { 670 PrintIndented(info); 671 Print(" "); 672 } 673 PrintLabels(labels); 674 } else if (info != NULL) { 675 PrintIndented(info); 676 } 677 Print("\n"); 678 } 679 680 681 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { 682 IndentedScope indent(this, s, node); 683 Visit(node); 684 } 685 686 687 const char* AstPrinter::PrintProgram(FunctionLiteral* program) { 688 Init(); 689 { IndentedScope indent(this, "FUNC"); 690 PrintLiteralIndented("NAME", program->name(), true); 691 PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true); 692 PrintParameters(program->scope()); 693 PrintDeclarations(program->scope()->declarations()); 694 PrintStatements(program->body()); 695 } 696 return Output(); 697 } 698 699 700 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { 701 if (declarations->length() > 0) { 702 IndentedScope indent(this, "DECLS"); 703 for (int i = 0; i < declarations->length(); i++) { 704 Visit(declarations->at(i)); 705 } 706 } 707 } 708 709 710 void AstPrinter::PrintParameters(Scope* scope) { 711 if (scope->num_parameters() > 0) { 712 IndentedScope indent(this, "PARAMS"); 713 for (int i = 0; i < scope->num_parameters(); i++) { 714 PrintLiteralWithModeIndented("VAR", scope->parameter(i), 715 scope->parameter(i)->name()); 716 } 717 } 718 } 719 720 721 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) { 722 for (int i = 0; i < statements->length(); i++) { 723 Visit(statements->at(i)); 724 } 725 } 726 727 728 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 729 for (int i = 0; i < arguments->length(); i++) { 730 Visit(arguments->at(i)); 731 } 732 } 733 734 735 void AstPrinter::PrintCaseClause(CaseClause* clause) { 736 if (clause->is_default()) { 737 IndentedScope indent(this, "DEFAULT"); 738 PrintStatements(clause->statements()); 739 } else { 740 IndentedScope indent(this, "CASE"); 741 Visit(clause->label()); 742 PrintStatements(clause->statements()); 743 } 744 } 745 746 747 void AstPrinter::VisitBlock(Block* node) { 748 const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK"; 749 IndentedScope indent(this, block_txt); 750 PrintStatements(node->statements()); 751 } 752 753 754 void AstPrinter::VisitDeclaration(Declaration* node) { 755 if (node->fun() == NULL) { 756 // var or const declarations 757 PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()), 758 node->proxy()->AsVariable(), 759 node->proxy()->name()); 760 } else { 761 // function declarations 762 PrintIndented("FUNCTION "); 763 PrintLiteral(node->proxy()->name(), true); 764 Print(" = function "); 765 PrintLiteral(node->fun()->name(), false); 766 Print("\n"); 767 } 768 } 769 770 771 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { 772 Visit(node->expression()); 773 } 774 775 776 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { 777 PrintIndented("EMPTY\n"); 778 } 779 780 781 void AstPrinter::VisitIfStatement(IfStatement* node) { 782 PrintIndentedVisit("IF", node->condition()); 783 PrintIndentedVisit("THEN", node->then_statement()); 784 if (node->HasElseStatement()) { 785 PrintIndentedVisit("ELSE", node->else_statement()); 786 } 787 } 788 789 790 void AstPrinter::VisitContinueStatement(ContinueStatement* node) { 791 PrintLabelsIndented("CONTINUE", node->target()->labels()); 792 } 793 794 795 void AstPrinter::VisitBreakStatement(BreakStatement* node) { 796 PrintLabelsIndented("BREAK", node->target()->labels()); 797 } 798 799 800 void AstPrinter::VisitReturnStatement(ReturnStatement* node) { 801 PrintIndentedVisit("RETURN", node->expression()); 802 } 803 804 805 void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) { 806 PrintIndentedVisit("WITH ENTER", node->expression()); 807 } 808 809 810 void AstPrinter::VisitWithExitStatement(WithExitStatement* node) { 811 PrintIndented("WITH EXIT\n"); 812 } 813 814 815 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) { 816 IndentedScope indent(this, "SWITCH"); 817 PrintLabelsIndented(NULL, node->labels()); 818 PrintIndentedVisit("TAG", node->tag()); 819 for (int i = 0; i < node->cases()->length(); i++) { 820 PrintCaseClause(node->cases()->at(i)); 821 } 822 } 823 824 825 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 826 IndentedScope indent(this, "DO"); 827 PrintLabelsIndented(NULL, node->labels()); 828 PrintIndentedVisit("BODY", node->body()); 829 PrintIndentedVisit("COND", node->cond()); 830 } 831 832 833 void AstPrinter::VisitWhileStatement(WhileStatement* node) { 834 IndentedScope indent(this, "WHILE"); 835 PrintLabelsIndented(NULL, node->labels()); 836 PrintIndentedVisit("COND", node->cond()); 837 PrintIndentedVisit("BODY", node->body()); 838 } 839 840 841 void AstPrinter::VisitForStatement(ForStatement* node) { 842 IndentedScope indent(this, "FOR"); 843 PrintLabelsIndented(NULL, node->labels()); 844 if (node->init()) PrintIndentedVisit("INIT", node->init()); 845 if (node->cond()) PrintIndentedVisit("COND", node->cond()); 846 PrintIndentedVisit("BODY", node->body()); 847 if (node->next()) PrintIndentedVisit("NEXT", node->next()); 848 } 849 850 851 void AstPrinter::VisitForInStatement(ForInStatement* node) { 852 IndentedScope indent(this, "FOR IN"); 853 PrintIndentedVisit("FOR", node->each()); 854 PrintIndentedVisit("IN", node->enumerable()); 855 PrintIndentedVisit("BODY", node->body()); 856 } 857 858 859 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 860 IndentedScope indent(this, "TRY CATCH"); 861 PrintIndentedVisit("TRY", node->try_block()); 862 PrintIndentedVisit("CATCHVAR", node->catch_var()); 863 PrintIndentedVisit("CATCH", node->catch_block()); 864 } 865 866 867 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 868 IndentedScope indent(this, "TRY FINALLY"); 869 PrintIndentedVisit("TRY", node->try_block()); 870 PrintIndentedVisit("FINALLY", node->finally_block()); 871 } 872 873 874 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 875 IndentedScope indent(this, "DEBUGGER"); 876 } 877 878 879 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 880 IndentedScope indent(this, "FUNC LITERAL"); 881 PrintLiteralIndented("NAME", node->name(), false); 882 PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false); 883 PrintParameters(node->scope()); 884 // We don't want to see the function literal in this case: it 885 // will be printed via PrintProgram when the code for it is 886 // generated. 887 // PrintStatements(node->body()); 888 } 889 890 891 void AstPrinter::VisitSharedFunctionInfoLiteral( 892 SharedFunctionInfoLiteral* node) { 893 IndentedScope indent(this, "FUNC LITERAL"); 894 PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true); 895 } 896 897 898 void AstPrinter::VisitConditional(Conditional* node) { 899 IndentedScope indent(this, "CONDITIONAL"); 900 PrintIndentedVisit("?", node->condition()); 901 PrintIndentedVisit("THEN", node->then_expression()); 902 PrintIndentedVisit("ELSE", node->else_expression()); 903 } 904 905 906 void AstPrinter::VisitLiteral(Literal* node) { 907 PrintLiteralIndented("LITERAL", node->handle(), true); 908 } 909 910 911 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 912 IndentedScope indent(this, "REGEXP LITERAL"); 913 PrintLiteralIndented("PATTERN", node->pattern(), false); 914 PrintLiteralIndented("FLAGS", node->flags(), false); 915 } 916 917 918 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) { 919 IndentedScope indent(this, "OBJ LITERAL"); 920 for (int i = 0; i < node->properties()->length(); i++) { 921 const char* prop_kind = NULL; 922 switch (node->properties()->at(i)->kind()) { 923 case ObjectLiteral::Property::CONSTANT: 924 prop_kind = "PROPERTY - CONSTANT"; 925 break; 926 case ObjectLiteral::Property::COMPUTED: 927 prop_kind = "PROPERTY - COMPUTED"; 928 break; 929 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 930 prop_kind = "PROPERTY - MATERIALIZED_LITERAL"; 931 break; 932 case ObjectLiteral::Property::PROTOTYPE: 933 prop_kind = "PROPERTY - PROTOTYPE"; 934 break; 935 case ObjectLiteral::Property::GETTER: 936 prop_kind = "PROPERTY - GETTER"; 937 break; 938 case ObjectLiteral::Property::SETTER: 939 prop_kind = "PROPERTY - SETTER"; 940 break; 941 default: 942 UNREACHABLE(); 943 } 944 IndentedScope prop(this, prop_kind); 945 PrintIndentedVisit("KEY", node->properties()->at(i)->key()); 946 PrintIndentedVisit("VALUE", node->properties()->at(i)->value()); 947 } 948 } 949 950 951 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) { 952 IndentedScope indent(this, "ARRAY LITERAL"); 953 if (node->values()->length() > 0) { 954 IndentedScope indent(this, "VALUES"); 955 for (int i = 0; i < node->values()->length(); i++) { 956 Visit(node->values()->at(i)); 957 } 958 } 959 } 960 961 962 void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) { 963 IndentedScope indent(this, "CatchExtensionObject"); 964 PrintIndentedVisit("KEY", node->key()); 965 PrintIndentedVisit("VALUE", node->value()); 966 } 967 968 969 void AstPrinter::VisitSlot(Slot* node) { 970 PrintIndented("SLOT "); 971 PrettyPrinter::VisitSlot(node); 972 Print("\n"); 973 } 974 975 976 void AstPrinter::VisitVariableProxy(VariableProxy* node) { 977 PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name()); 978 Variable* var = node->var(); 979 if (var != NULL && var->rewrite() != NULL) { 980 IndentedScope indent(this); 981 Visit(var->rewrite()); 982 } 983 } 984 985 986 void AstPrinter::VisitAssignment(Assignment* node) { 987 IndentedScope indent(this, Token::Name(node->op()), node); 988 Visit(node->target()); 989 Visit(node->value()); 990 } 991 992 993 void AstPrinter::VisitThrow(Throw* node) { 994 PrintIndentedVisit("THROW", node->exception()); 995 } 996 997 998 void AstPrinter::VisitProperty(Property* node) { 999 IndentedScope indent(this, "PROPERTY", node); 1000 Visit(node->obj()); 1001 Literal* literal = node->key()->AsLiteral(); 1002 if (literal != NULL && literal->handle()->IsSymbol()) { 1003 PrintLiteralIndented("NAME", literal->handle(), false); 1004 } else { 1005 PrintIndentedVisit("KEY", node->key()); 1006 } 1007 } 1008 1009 1010 void AstPrinter::VisitCall(Call* node) { 1011 IndentedScope indent(this, "CALL"); 1012 Visit(node->expression()); 1013 PrintArguments(node->arguments()); 1014 } 1015 1016 1017 void AstPrinter::VisitCallNew(CallNew* node) { 1018 IndentedScope indent(this, "CALL NEW"); 1019 Visit(node->expression()); 1020 PrintArguments(node->arguments()); 1021 } 1022 1023 1024 void AstPrinter::VisitCallRuntime(CallRuntime* node) { 1025 PrintLiteralIndented("CALL RUNTIME ", node->name(), false); 1026 IndentedScope indent(this); 1027 PrintArguments(node->arguments()); 1028 } 1029 1030 1031 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { 1032 PrintIndentedVisit(Token::Name(node->op()), node->expression()); 1033 } 1034 1035 1036 void AstPrinter::VisitCountOperation(CountOperation* node) { 1037 EmbeddedVector<char, 128> buf; 1038 OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"), 1039 Token::Name(node->op())); 1040 PrintIndentedVisit(buf.start(), node->expression()); 1041 } 1042 1043 1044 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) { 1045 IndentedScope indent(this, Token::Name(node->op()), node); 1046 Visit(node->left()); 1047 Visit(node->right()); 1048 } 1049 1050 1051 void AstPrinter::VisitCompareOperation(CompareOperation* node) { 1052 IndentedScope indent(this, Token::Name(node->op()), node); 1053 Visit(node->left()); 1054 Visit(node->right()); 1055 } 1056 1057 1058 void AstPrinter::VisitCompareToNull(CompareToNull* node) { 1059 const char* name = node->is_strict() 1060 ? "COMPARE-TO-NULL-STRICT" 1061 : "COMPARE-TO-NULL"; 1062 IndentedScope indent(this, name, node); 1063 Visit(node->expression()); 1064 } 1065 1066 1067 void AstPrinter::VisitThisFunction(ThisFunction* node) { 1068 IndentedScope indent(this, "THIS-FUNCTION"); 1069 } 1070 1071 1072 TagScope::TagScope(JsonAstBuilder* builder, const char* name) 1073 : builder_(builder), next_(builder->tag()), has_body_(false) { 1074 if (next_ != NULL) { 1075 next_->use(); 1076 builder->Print(",\n"); 1077 } 1078 builder->set_tag(this); 1079 builder->PrintIndented("["); 1080 builder->Print("\"%s\"", name); 1081 builder->increase_indent(JsonAstBuilder::kTagIndentSize); 1082 } 1083 1084 1085 TagScope::~TagScope() { 1086 builder_->decrease_indent(JsonAstBuilder::kTagIndentSize); 1087 if (has_body_) { 1088 builder_->Print("\n"); 1089 builder_->PrintIndented("]"); 1090 } else { 1091 builder_->Print("]"); 1092 } 1093 builder_->set_tag(next_); 1094 } 1095 1096 1097 AttributesScope::AttributesScope(JsonAstBuilder* builder) 1098 : builder_(builder), attribute_count_(0) { 1099 builder->set_attributes(this); 1100 builder->tag()->use(); 1101 builder->Print(",\n"); 1102 builder->PrintIndented("{"); 1103 builder->increase_indent(JsonAstBuilder::kAttributesIndentSize); 1104 } 1105 1106 1107 AttributesScope::~AttributesScope() { 1108 builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize); 1109 if (attribute_count_ > 1) { 1110 builder_->Print("\n"); 1111 builder_->PrintIndented("}"); 1112 } else { 1113 builder_->Print("}"); 1114 } 1115 builder_->set_attributes(NULL); 1116 } 1117 1118 1119 const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) { 1120 Init(); 1121 Visit(program); 1122 Print("\n"); 1123 return Output(); 1124 } 1125 1126 1127 void JsonAstBuilder::AddAttributePrefix(const char* name) { 1128 if (attributes()->is_used()) { 1129 Print(",\n"); 1130 PrintIndented("\""); 1131 } else { 1132 Print("\""); 1133 } 1134 Print("%s\":", name); 1135 attributes()->use(); 1136 } 1137 1138 1139 void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) { 1140 SmartPointer<char> value_string = value->ToCString(); 1141 AddAttributePrefix(name); 1142 Print("\"%s\"", *value_string); 1143 } 1144 1145 1146 void JsonAstBuilder::AddAttribute(const char* name, const char* value) { 1147 AddAttributePrefix(name); 1148 Print("\"%s\"", value); 1149 } 1150 1151 1152 void JsonAstBuilder::AddAttribute(const char* name, int value) { 1153 AddAttributePrefix(name); 1154 Print("%d", value); 1155 } 1156 1157 1158 void JsonAstBuilder::AddAttribute(const char* name, bool value) { 1159 AddAttributePrefix(name); 1160 Print(value ? "true" : "false"); 1161 } 1162 1163 1164 void JsonAstBuilder::VisitBlock(Block* stmt) { 1165 TagScope tag(this, "Block"); 1166 VisitStatements(stmt->statements()); 1167 } 1168 1169 1170 void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { 1171 TagScope tag(this, "ExpressionStatement"); 1172 Visit(stmt->expression()); 1173 } 1174 1175 1176 void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 1177 TagScope tag(this, "EmptyStatement"); 1178 } 1179 1180 1181 void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) { 1182 TagScope tag(this, "IfStatement"); 1183 Visit(stmt->condition()); 1184 Visit(stmt->then_statement()); 1185 Visit(stmt->else_statement()); 1186 } 1187 1188 1189 void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) { 1190 TagScope tag(this, "ContinueStatement"); 1191 } 1192 1193 1194 void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) { 1195 TagScope tag(this, "BreakStatement"); 1196 } 1197 1198 1199 void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) { 1200 TagScope tag(this, "ReturnStatement"); 1201 Visit(stmt->expression()); 1202 } 1203 1204 1205 void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 1206 TagScope tag(this, "WithEnterStatement"); 1207 Visit(stmt->expression()); 1208 } 1209 1210 1211 void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 1212 TagScope tag(this, "WithExitStatement"); 1213 } 1214 1215 1216 void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 1217 TagScope tag(this, "SwitchStatement"); 1218 } 1219 1220 1221 void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 1222 TagScope tag(this, "DoWhileStatement"); 1223 Visit(stmt->body()); 1224 Visit(stmt->cond()); 1225 } 1226 1227 1228 void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) { 1229 TagScope tag(this, "WhileStatement"); 1230 Visit(stmt->cond()); 1231 Visit(stmt->body()); 1232 } 1233 1234 1235 void JsonAstBuilder::VisitForStatement(ForStatement* stmt) { 1236 TagScope tag(this, "ForStatement"); 1237 if (stmt->init() != NULL) Visit(stmt->init()); 1238 if (stmt->cond() != NULL) Visit(stmt->cond()); 1239 Visit(stmt->body()); 1240 if (stmt->next() != NULL) Visit(stmt->next()); 1241 } 1242 1243 1244 void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) { 1245 TagScope tag(this, "ForInStatement"); 1246 Visit(stmt->each()); 1247 Visit(stmt->enumerable()); 1248 Visit(stmt->body()); 1249 } 1250 1251 1252 void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 1253 TagScope tag(this, "TryCatchStatement"); 1254 Visit(stmt->try_block()); 1255 Visit(stmt->catch_var()); 1256 Visit(stmt->catch_block()); 1257 } 1258 1259 1260 void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1261 TagScope tag(this, "TryFinallyStatement"); 1262 Visit(stmt->try_block()); 1263 Visit(stmt->finally_block()); 1264 } 1265 1266 1267 void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 1268 TagScope tag(this, "DebuggerStatement"); 1269 } 1270 1271 1272 void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 1273 TagScope tag(this, "FunctionLiteral"); 1274 { 1275 AttributesScope attributes(this); 1276 AddAttribute("name", expr->name()); 1277 } 1278 VisitDeclarations(expr->scope()->declarations()); 1279 VisitStatements(expr->body()); 1280 } 1281 1282 1283 void JsonAstBuilder::VisitSharedFunctionInfoLiteral( 1284 SharedFunctionInfoLiteral* expr) { 1285 TagScope tag(this, "SharedFunctionInfoLiteral"); 1286 } 1287 1288 1289 void JsonAstBuilder::VisitConditional(Conditional* expr) { 1290 TagScope tag(this, "Conditional"); 1291 } 1292 1293 1294 void JsonAstBuilder::VisitSlot(Slot* expr) { 1295 TagScope tag(this, "Slot"); 1296 { 1297 AttributesScope attributes(this); 1298 switch (expr->type()) { 1299 case Slot::PARAMETER: 1300 AddAttribute("type", "PARAMETER"); 1301 break; 1302 case Slot::LOCAL: 1303 AddAttribute("type", "LOCAL"); 1304 break; 1305 case Slot::CONTEXT: 1306 AddAttribute("type", "CONTEXT"); 1307 break; 1308 case Slot::LOOKUP: 1309 AddAttribute("type", "LOOKUP"); 1310 break; 1311 } 1312 AddAttribute("index", expr->index()); 1313 } 1314 } 1315 1316 1317 void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) { 1318 if (expr->var()->rewrite() == NULL) { 1319 TagScope tag(this, "VariableProxy"); 1320 { 1321 AttributesScope attributes(this); 1322 AddAttribute("name", expr->name()); 1323 AddAttribute("mode", Variable::Mode2String(expr->var()->mode())); 1324 } 1325 } else { 1326 Visit(expr->var()->rewrite()); 1327 } 1328 } 1329 1330 1331 void JsonAstBuilder::VisitLiteral(Literal* expr) { 1332 TagScope tag(this, "Literal"); 1333 { 1334 AttributesScope attributes(this); 1335 Handle<Object> handle = expr->handle(); 1336 if (handle->IsString()) { 1337 AddAttribute("handle", Handle<String>(String::cast(*handle))); 1338 } else if (handle->IsSmi()) { 1339 AddAttribute("handle", Smi::cast(*handle)->value()); 1340 } 1341 } 1342 } 1343 1344 1345 void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 1346 TagScope tag(this, "RegExpLiteral"); 1347 } 1348 1349 1350 void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 1351 TagScope tag(this, "ObjectLiteral"); 1352 } 1353 1354 1355 void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 1356 TagScope tag(this, "ArrayLiteral"); 1357 } 1358 1359 1360 void JsonAstBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 1361 TagScope tag(this, "CatchExtensionObject"); 1362 Visit(expr->key()); 1363 Visit(expr->value()); 1364 } 1365 1366 1367 void JsonAstBuilder::VisitAssignment(Assignment* expr) { 1368 TagScope tag(this, "Assignment"); 1369 { 1370 AttributesScope attributes(this); 1371 AddAttribute("op", Token::Name(expr->op())); 1372 } 1373 Visit(expr->target()); 1374 Visit(expr->value()); 1375 } 1376 1377 1378 void JsonAstBuilder::VisitThrow(Throw* expr) { 1379 TagScope tag(this, "Throw"); 1380 Visit(expr->exception()); 1381 } 1382 1383 1384 void JsonAstBuilder::VisitProperty(Property* expr) { 1385 TagScope tag(this, "Property"); 1386 { 1387 AttributesScope attributes(this); 1388 AddAttribute("type", expr->is_synthetic() ? "SYNTHETIC" : "NORMAL"); 1389 } 1390 Visit(expr->obj()); 1391 Visit(expr->key()); 1392 } 1393 1394 1395 void JsonAstBuilder::VisitCall(Call* expr) { 1396 TagScope tag(this, "Call"); 1397 Visit(expr->expression()); 1398 VisitExpressions(expr->arguments()); 1399 } 1400 1401 1402 void JsonAstBuilder::VisitCallNew(CallNew* expr) { 1403 TagScope tag(this, "CallNew"); 1404 Visit(expr->expression()); 1405 VisitExpressions(expr->arguments()); 1406 } 1407 1408 1409 void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) { 1410 TagScope tag(this, "CallRuntime"); 1411 { 1412 AttributesScope attributes(this); 1413 AddAttribute("name", expr->name()); 1414 } 1415 VisitExpressions(expr->arguments()); 1416 } 1417 1418 1419 void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) { 1420 TagScope tag(this, "UnaryOperation"); 1421 { 1422 AttributesScope attributes(this); 1423 AddAttribute("op", Token::Name(expr->op())); 1424 } 1425 Visit(expr->expression()); 1426 } 1427 1428 1429 void JsonAstBuilder::VisitCountOperation(CountOperation* expr) { 1430 TagScope tag(this, "CountOperation"); 1431 { 1432 AttributesScope attributes(this); 1433 AddAttribute("is_prefix", expr->is_prefix()); 1434 AddAttribute("op", Token::Name(expr->op())); 1435 } 1436 Visit(expr->expression()); 1437 } 1438 1439 1440 void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) { 1441 TagScope tag(this, "BinaryOperation"); 1442 { 1443 AttributesScope attributes(this); 1444 AddAttribute("op", Token::Name(expr->op())); 1445 } 1446 Visit(expr->left()); 1447 Visit(expr->right()); 1448 } 1449 1450 1451 void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) { 1452 TagScope tag(this, "CompareOperation"); 1453 { 1454 AttributesScope attributes(this); 1455 AddAttribute("op", Token::Name(expr->op())); 1456 } 1457 Visit(expr->left()); 1458 Visit(expr->right()); 1459 } 1460 1461 1462 void JsonAstBuilder::VisitCompareToNull(CompareToNull* expr) { 1463 TagScope tag(this, "CompareToNull"); 1464 { 1465 AttributesScope attributes(this); 1466 AddAttribute("is_strict", expr->is_strict()); 1467 } 1468 Visit(expr->expression()); 1469 } 1470 1471 1472 void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) { 1473 TagScope tag(this, "ThisFunction"); 1474 } 1475 1476 1477 void JsonAstBuilder::VisitDeclaration(Declaration* decl) { 1478 TagScope tag(this, "Declaration"); 1479 { 1480 AttributesScope attributes(this); 1481 AddAttribute("mode", Variable::Mode2String(decl->mode())); 1482 } 1483 Visit(decl->proxy()); 1484 if (decl->fun() != NULL) Visit(decl->fun()); 1485 } 1486 1487 1488 #endif // DEBUG 1489 1490 } } // namespace v8::internal 1491