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 36namespace v8 { 37namespace internal { 38 39#ifdef DEBUG 40 41PrettyPrinter::PrettyPrinter() { 42 output_ = NULL; 43 size_ = 0; 44 pos_ = 0; 45} 46 47 48PrettyPrinter::~PrettyPrinter() { 49 DeleteArray(output_); 50} 51 52 53void PrettyPrinter::VisitBlock(Block* node) { 54 if (!node->is_initializer_block()) Print("{ "); 55 PrintStatements(node->statements()); 56 if (node->statements()->length() > 0) Print(" "); 57 if (!node->is_initializer_block()) Print("}"); 58} 59 60 61void PrettyPrinter::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 72void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) { 73 Visit(node->expression()); 74 Print(";"); 75} 76 77 78void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) { 79 Print(";"); 80} 81 82 83void 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 95void 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 107void 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 119void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { 120 Print("return "); 121 Visit(node->expression()); 122 Print(";"); 123} 124 125 126void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) { 127 Print("<enter with> ("); 128 Visit(node->expression()); 129 Print(") "); 130} 131 132 133void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) { 134 Print("<exit with>"); 135} 136 137 138void 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 150void 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 160void PrettyPrinter::VisitWhileStatement(WhileStatement* node) { 161 PrintLabels(node->labels()); 162 Print("while ("); 163 Visit(node->cond()); 164 Print(") "); 165 Visit(node->body()); 166} 167 168 169void 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 189void 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 200void 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 210void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 211 Print("try "); 212 Visit(node->try_block()); 213 Print(" finally "); 214 Visit(node->finally_block()); 215} 216 217 218void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 219 Print("debugger "); 220} 221 222 223void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 224 Print("("); 225 PrintFunctionLiteral(node); 226 Print(")"); 227} 228 229 230void PrettyPrinter::VisitFunctionBoilerplateLiteral( 231 FunctionBoilerplateLiteral* node) { 232 Print("("); 233 PrintLiteral(node->boilerplate(), true); 234 Print(")"); 235} 236 237 238void 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 247void PrettyPrinter::VisitLiteral(Literal* node) { 248 PrintLiteral(node->handle(), true); 249} 250 251 252void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 253 Print(" RegExp("); 254 PrintLiteral(node->pattern(), false); 255 Print(","); 256 PrintLiteral(node->flags(), false); 257 Print(") "); 258} 259 260 261void 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 275void 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 285void PrettyPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) { 286 Print("{ "); 287 Visit(node->key()); 288 Print(": "); 289 Visit(node->value()); 290 Print(" }"); 291} 292 293 294void 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("frame[%d]", node->index()); 301 break; 302 case Slot::CONTEXT: 303 Print(".context[%d]", node->index()); 304 break; 305 case Slot::LOOKUP: 306 Print(".context["); 307 PrintLiteral(node->var()->name(), false); 308 Print("]"); 309 break; 310 default: 311 UNREACHABLE(); 312 } 313} 314 315 316void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { 317 PrintLiteral(node->name(), false); 318} 319 320 321void PrettyPrinter::VisitAssignment(Assignment* node) { 322 Visit(node->target()); 323 Print(" %s ", Token::String(node->op())); 324 Visit(node->value()); 325} 326 327 328void PrettyPrinter::VisitThrow(Throw* node) { 329 Print("throw "); 330 Visit(node->exception()); 331} 332 333 334void 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 351void PrettyPrinter::VisitCall(Call* node) { 352 Visit(node->expression()); 353 PrintArguments(node->arguments()); 354} 355 356 357void PrettyPrinter::VisitCallNew(CallNew* node) { 358 Print("new ("); 359 Visit(node->expression()); 360 Print(")"); 361 PrintArguments(node->arguments()); 362} 363 364 365void PrettyPrinter::VisitCallRuntime(CallRuntime* node) { 366 Print("%%"); 367 PrintLiteral(node->name(), false); 368 PrintArguments(node->arguments()); 369} 370 371 372void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) { 373 Print("(%s", Token::String(node->op())); 374 Visit(node->expression()); 375 Print(")"); 376} 377 378 379void 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 388void 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 397void 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 406void PrettyPrinter::VisitThisFunction(ThisFunction* node) { 407 Print("<this-function>"); 408} 409 410 411const char* PrettyPrinter::Print(AstNode* node) { 412 Init(); 413 Visit(node); 414 return output_; 415} 416 417 418const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) { 419 Init(); 420 ExpressionStatement* statement = 421 program->body()->at(0)->AsExpressionStatement(); 422 Visit(statement->expression()); 423 return output_; 424} 425 426 427const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) { 428 Init(); 429 PrintStatements(program->body()); 430 Print("\n"); 431 return output_; 432} 433 434 435void PrettyPrinter::PrintOut(AstNode* node) { 436 PrettyPrinter printer; 437 PrintF("%s", printer.Print(node)); 438} 439 440 441void PrettyPrinter::Init() { 442 if (size_ == 0) { 443 ASSERT(output_ == NULL); 444 const int initial_size = 256; 445 output_ = NewArray<char>(initial_size); 446 size_ = initial_size; 447 } 448 output_[0] = '\0'; 449 pos_ = 0; 450} 451 452 453void PrettyPrinter::Print(const char* format, ...) { 454 for (;;) { 455 va_list arguments; 456 va_start(arguments, format); 457 int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_, 458 format, 459 arguments); 460 va_end(arguments); 461 462 if (n >= 0) { 463 // there was enough space - we are done 464 pos_ += n; 465 return; 466 } else { 467 // there was not enough space - allocate more and try again 468 const int slack = 32; 469 int new_size = size_ + (size_ >> 1) + slack; 470 char* new_output = NewArray<char>(new_size); 471 memcpy(new_output, output_, pos_); 472 DeleteArray(output_); 473 output_ = new_output; 474 size_ = new_size; 475 } 476 } 477} 478 479 480void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) { 481 for (int i = 0; i < statements->length(); i++) { 482 if (i != 0) Print(" "); 483 Visit(statements->at(i)); 484 } 485} 486 487 488void PrettyPrinter::PrintLabels(ZoneStringList* labels) { 489 if (labels != NULL) { 490 for (int i = 0; i < labels->length(); i++) { 491 PrintLiteral(labels->at(i), false); 492 Print(": "); 493 } 494 } 495} 496 497 498void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 499 Print("("); 500 for (int i = 0; i < arguments->length(); i++) { 501 if (i != 0) Print(", "); 502 Visit(arguments->at(i)); 503 } 504 Print(")"); 505} 506 507 508void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) { 509 Object* object = *value; 510 if (object->IsString()) { 511 String* string = String::cast(object); 512 if (quote) Print("\""); 513 for (int i = 0; i < string->length(); i++) { 514 Print("%c", string->Get(i)); 515 } 516 if (quote) Print("\""); 517 } else if (object == Heap::null_value()) { 518 Print("null"); 519 } else if (object == Heap::true_value()) { 520 Print("true"); 521 } else if (object == Heap::false_value()) { 522 Print("false"); 523 } else if (object == Heap::undefined_value()) { 524 Print("undefined"); 525 } else if (object->IsNumber()) { 526 Print("%g", object->Number()); 527 } else if (object->IsJSObject()) { 528 // regular expression 529 if (object->IsJSFunction()) { 530 Print("JS-Function"); 531 } else if (object->IsJSArray()) { 532 Print("JS-array[%u]", JSArray::cast(object)->length()); 533 } else if (object->IsJSObject()) { 534 Print("JS-Object"); 535 } else { 536 Print("?UNKNOWN?"); 537 } 538 } else if (object->IsFixedArray()) { 539 Print("FixedArray"); 540 } else { 541 Print("<unknown literal %p>", object); 542 } 543} 544 545 546void PrettyPrinter::PrintParameters(Scope* scope) { 547 Print("("); 548 for (int i = 0; i < scope->num_parameters(); i++) { 549 if (i > 0) Print(", "); 550 PrintLiteral(scope->parameter(i)->name(), false); 551 } 552 Print(")"); 553} 554 555 556void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { 557 for (int i = 0; i < declarations->length(); i++) { 558 if (i > 0) Print(" "); 559 Visit(declarations->at(i)); 560 } 561} 562 563 564void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) { 565 Print("function "); 566 PrintLiteral(function->name(), false); 567 PrintParameters(function->scope()); 568 Print(" { "); 569 PrintDeclarations(function->scope()->declarations()); 570 PrintStatements(function->body()); 571 Print(" }"); 572} 573 574 575void PrettyPrinter::PrintCaseClause(CaseClause* clause) { 576 if (clause->is_default()) { 577 Print("default"); 578 } else { 579 Print("case "); 580 Visit(clause->label()); 581 } 582 Print(": "); 583 PrintStatements(clause->statements()); 584 if (clause->statements()->length() > 0) 585 Print(" "); 586} 587 588 589//----------------------------------------------------------------------------- 590 591class IndentedScope BASE_EMBEDDED { 592 public: 593 IndentedScope() { 594 ast_printer_->inc_indent(); 595 } 596 597 explicit IndentedScope(const char* txt, AstNode* node = NULL) { 598 ast_printer_->PrintIndented(txt); 599 if (node != NULL && node->AsExpression() != NULL) { 600 Expression* expr = node->AsExpression(); 601 bool printed_first = false; 602 if ((expr->type() != NULL) && (expr->type()->IsKnown())) { 603 ast_printer_->Print(" (type = "); 604 ast_printer_->Print(StaticType::Type2String(expr->type())); 605 printed_first = true; 606 } 607 if (expr->num() != Expression::kNoLabel) { 608 ast_printer_->Print(printed_first ? ", num = " : " (num = "); 609 ast_printer_->Print("%d", expr->num()); 610 printed_first = true; 611 } 612 if (printed_first) ast_printer_->Print(")"); 613 } 614 ast_printer_->Print("\n"); 615 ast_printer_->inc_indent(); 616 } 617 618 virtual ~IndentedScope() { 619 ast_printer_->dec_indent(); 620 } 621 622 static void SetAstPrinter(AstPrinter* a) { ast_printer_ = a; } 623 624 private: 625 static AstPrinter* ast_printer_; 626}; 627 628 629AstPrinter* IndentedScope::ast_printer_ = NULL; 630 631 632//----------------------------------------------------------------------------- 633 634int AstPrinter::indent_ = 0; 635 636 637AstPrinter::AstPrinter() { 638 ASSERT(indent_ == 0); 639 IndentedScope::SetAstPrinter(this); 640} 641 642 643AstPrinter::~AstPrinter() { 644 ASSERT(indent_ == 0); 645 IndentedScope::SetAstPrinter(NULL); 646} 647 648 649void AstPrinter::PrintIndented(const char* txt) { 650 for (int i = 0; i < indent_; i++) { 651 Print(". "); 652 } 653 Print(txt); 654} 655 656 657void AstPrinter::PrintLiteralIndented(const char* info, 658 Handle<Object> value, 659 bool quote) { 660 PrintIndented(info); 661 Print(" "); 662 PrintLiteral(value, quote); 663 Print("\n"); 664} 665 666 667void AstPrinter::PrintLiteralWithModeIndented(const char* info, 668 Variable* var, 669 Handle<Object> value, 670 StaticType* type, 671 int num) { 672 if (var == NULL) { 673 PrintLiteralIndented(info, value, true); 674 } else { 675 EmbeddedVector<char, 256> buf; 676 int pos = OS::SNPrintF(buf, "%s (mode = %s", info, 677 Variable::Mode2String(var->mode())); 678 if (type->IsKnown()) { 679 pos += OS::SNPrintF(buf + pos, ", type = %s", 680 StaticType::Type2String(type)); 681 } 682 if (num != Expression::kNoLabel) { 683 pos += OS::SNPrintF(buf + pos, ", num = %d", num); 684 } 685 OS::SNPrintF(buf + pos, ")"); 686 PrintLiteralIndented(buf.start(), value, true); 687 } 688} 689 690 691void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) { 692 if (labels != NULL && labels->length() > 0) { 693 if (info == NULL) { 694 PrintIndented("LABELS "); 695 } else { 696 PrintIndented(info); 697 Print(" "); 698 } 699 PrintLabels(labels); 700 } else if (info != NULL) { 701 PrintIndented(info); 702 } 703 Print("\n"); 704} 705 706 707void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { 708 IndentedScope indent(s, node); 709 Visit(node); 710} 711 712 713const char* AstPrinter::PrintProgram(FunctionLiteral* program) { 714 Init(); 715 { IndentedScope indent("FUNC"); 716 PrintLiteralIndented("NAME", program->name(), true); 717 PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true); 718 PrintParameters(program->scope()); 719 PrintDeclarations(program->scope()->declarations()); 720 PrintStatements(program->body()); 721 } 722 return Output(); 723} 724 725 726void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { 727 if (declarations->length() > 0) { 728 IndentedScope indent("DECLS"); 729 for (int i = 0; i < declarations->length(); i++) { 730 Visit(declarations->at(i)); 731 } 732 } 733} 734 735 736void AstPrinter::PrintParameters(Scope* scope) { 737 if (scope->num_parameters() > 0) { 738 IndentedScope indent("PARAMS"); 739 for (int i = 0; i < scope->num_parameters(); i++) { 740 PrintLiteralWithModeIndented("VAR", scope->parameter(i), 741 scope->parameter(i)->name(), 742 scope->parameter(i)->type(), 743 Expression::kNoLabel); 744 } 745 } 746} 747 748 749void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) { 750 for (int i = 0; i < statements->length(); i++) { 751 Visit(statements->at(i)); 752 } 753} 754 755 756void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 757 for (int i = 0; i < arguments->length(); i++) { 758 Visit(arguments->at(i)); 759 } 760} 761 762 763void AstPrinter::PrintCaseClause(CaseClause* clause) { 764 if (clause->is_default()) { 765 IndentedScope indent("DEFAULT"); 766 PrintStatements(clause->statements()); 767 } else { 768 IndentedScope indent("CASE"); 769 Visit(clause->label()); 770 PrintStatements(clause->statements()); 771 } 772} 773 774 775void AstPrinter::VisitBlock(Block* node) { 776 const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK"; 777 IndentedScope indent(block_txt); 778 PrintStatements(node->statements()); 779} 780 781 782void AstPrinter::VisitDeclaration(Declaration* node) { 783 if (node->fun() == NULL) { 784 // var or const declarations 785 PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()), 786 node->proxy()->AsVariable(), 787 node->proxy()->name(), 788 node->proxy()->AsVariable()->type(), 789 Expression::kNoLabel); 790 } else { 791 // function declarations 792 PrintIndented("FUNCTION "); 793 PrintLiteral(node->proxy()->name(), true); 794 Print(" = function "); 795 PrintLiteral(node->fun()->name(), false); 796 Print("\n"); 797 } 798} 799 800 801void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { 802 Visit(node->expression()); 803} 804 805 806void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { 807 PrintIndented("EMPTY\n"); 808} 809 810 811void AstPrinter::VisitIfStatement(IfStatement* node) { 812 PrintIndentedVisit("IF", node->condition()); 813 PrintIndentedVisit("THEN", node->then_statement()); 814 if (node->HasElseStatement()) { 815 PrintIndentedVisit("ELSE", node->else_statement()); 816 } 817} 818 819 820void AstPrinter::VisitContinueStatement(ContinueStatement* node) { 821 PrintLabelsIndented("CONTINUE", node->target()->labels()); 822} 823 824 825void AstPrinter::VisitBreakStatement(BreakStatement* node) { 826 PrintLabelsIndented("BREAK", node->target()->labels()); 827} 828 829 830void AstPrinter::VisitReturnStatement(ReturnStatement* node) { 831 PrintIndentedVisit("RETURN", node->expression()); 832} 833 834 835void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) { 836 PrintIndentedVisit("WITH ENTER", node->expression()); 837} 838 839 840void AstPrinter::VisitWithExitStatement(WithExitStatement* node) { 841 PrintIndented("WITH EXIT\n"); 842} 843 844 845void AstPrinter::VisitSwitchStatement(SwitchStatement* node) { 846 IndentedScope indent("SWITCH"); 847 PrintLabelsIndented(NULL, node->labels()); 848 PrintIndentedVisit("TAG", node->tag()); 849 for (int i = 0; i < node->cases()->length(); i++) { 850 PrintCaseClause(node->cases()->at(i)); 851 } 852} 853 854 855void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 856 IndentedScope indent("DO"); 857 PrintLabelsIndented(NULL, node->labels()); 858 PrintIndentedVisit("BODY", node->body()); 859 PrintIndentedVisit("COND", node->cond()); 860} 861 862 863void AstPrinter::VisitWhileStatement(WhileStatement* node) { 864 IndentedScope indent("WHILE"); 865 PrintLabelsIndented(NULL, node->labels()); 866 PrintIndentedVisit("COND", node->cond()); 867 PrintIndentedVisit("BODY", node->body()); 868} 869 870 871void AstPrinter::VisitForStatement(ForStatement* node) { 872 IndentedScope indent("FOR"); 873 PrintLabelsIndented(NULL, node->labels()); 874 if (node->init()) PrintIndentedVisit("INIT", node->init()); 875 if (node->cond()) PrintIndentedVisit("COND", node->cond()); 876 PrintIndentedVisit("BODY", node->body()); 877 if (node->next()) PrintIndentedVisit("NEXT", node->next()); 878} 879 880 881void AstPrinter::VisitForInStatement(ForInStatement* node) { 882 IndentedScope indent("FOR IN"); 883 PrintIndentedVisit("FOR", node->each()); 884 PrintIndentedVisit("IN", node->enumerable()); 885 PrintIndentedVisit("BODY", node->body()); 886} 887 888 889void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 890 IndentedScope indent("TRY CATCH"); 891 PrintIndentedVisit("TRY", node->try_block()); 892 PrintIndentedVisit("CATCHVAR", node->catch_var()); 893 PrintIndentedVisit("CATCH", node->catch_block()); 894} 895 896 897void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 898 IndentedScope indent("TRY FINALLY"); 899 PrintIndentedVisit("TRY", node->try_block()); 900 PrintIndentedVisit("FINALLY", node->finally_block()); 901} 902 903 904void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 905 IndentedScope indent("DEBUGGER"); 906} 907 908 909void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 910 IndentedScope indent("FUNC LITERAL"); 911 PrintLiteralIndented("NAME", node->name(), false); 912 PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false); 913 PrintParameters(node->scope()); 914 // We don't want to see the function literal in this case: it 915 // will be printed via PrintProgram when the code for it is 916 // generated. 917 // PrintStatements(node->body()); 918} 919 920 921void AstPrinter::VisitFunctionBoilerplateLiteral( 922 FunctionBoilerplateLiteral* node) { 923 IndentedScope indent("FUNC LITERAL"); 924 PrintLiteralIndented("BOILERPLATE", node->boilerplate(), true); 925} 926 927 928void AstPrinter::VisitConditional(Conditional* node) { 929 IndentedScope indent("CONDITIONAL"); 930 PrintIndentedVisit("?", node->condition()); 931 PrintIndentedVisit("THEN", node->then_expression()); 932 PrintIndentedVisit("ELSE", node->else_expression()); 933} 934 935 936void AstPrinter::VisitLiteral(Literal* node) { 937 PrintLiteralIndented("LITERAL", node->handle(), true); 938} 939 940 941void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 942 IndentedScope indent("REGEXP LITERAL"); 943 PrintLiteralIndented("PATTERN", node->pattern(), false); 944 PrintLiteralIndented("FLAGS", node->flags(), false); 945} 946 947 948void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) { 949 IndentedScope indent("OBJ LITERAL"); 950 for (int i = 0; i < node->properties()->length(); i++) { 951 const char* prop_kind = NULL; 952 switch (node->properties()->at(i)->kind()) { 953 case ObjectLiteral::Property::CONSTANT: 954 prop_kind = "PROPERTY - CONSTANT"; 955 break; 956 case ObjectLiteral::Property::COMPUTED: 957 prop_kind = "PROPERTY - COMPUTED"; 958 break; 959 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 960 prop_kind = "PROPERTY - MATERIALIZED_LITERAL"; 961 break; 962 case ObjectLiteral::Property::PROTOTYPE: 963 prop_kind = "PROPERTY - PROTOTYPE"; 964 break; 965 case ObjectLiteral::Property::GETTER: 966 prop_kind = "PROPERTY - GETTER"; 967 break; 968 case ObjectLiteral::Property::SETTER: 969 prop_kind = "PROPERTY - SETTER"; 970 break; 971 default: 972 UNREACHABLE(); 973 } 974 IndentedScope prop(prop_kind); 975 PrintIndentedVisit("KEY", node->properties()->at(i)->key()); 976 PrintIndentedVisit("VALUE", node->properties()->at(i)->value()); 977 } 978} 979 980 981void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) { 982 IndentedScope indent("ARRAY LITERAL"); 983 if (node->values()->length() > 0) { 984 IndentedScope indent("VALUES"); 985 for (int i = 0; i < node->values()->length(); i++) { 986 Visit(node->values()->at(i)); 987 } 988 } 989} 990 991 992void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) { 993 IndentedScope indent("CatchExtensionObject"); 994 PrintIndentedVisit("KEY", node->key()); 995 PrintIndentedVisit("VALUE", node->value()); 996} 997 998 999void AstPrinter::VisitSlot(Slot* node) { 1000 PrintIndented("SLOT "); 1001 switch (node->type()) { 1002 case Slot::PARAMETER: 1003 Print("parameter[%d]", node->index()); 1004 break; 1005 case Slot::LOCAL: 1006 Print("frame[%d]", node->index()); 1007 break; 1008 case Slot::CONTEXT: 1009 Print(".context[%d]", node->index()); 1010 break; 1011 case Slot::LOOKUP: 1012 Print(".context["); 1013 PrintLiteral(node->var()->name(), false); 1014 Print("]"); 1015 break; 1016 default: 1017 UNREACHABLE(); 1018 } 1019 Print("\n"); 1020} 1021 1022 1023void AstPrinter::VisitVariableProxy(VariableProxy* node) { 1024 PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name(), 1025 node->type(), node->num()); 1026 Variable* var = node->var(); 1027 if (var != NULL && var->rewrite() != NULL) { 1028 IndentedScope indent; 1029 Visit(var->rewrite()); 1030 } 1031} 1032 1033 1034void AstPrinter::VisitAssignment(Assignment* node) { 1035 IndentedScope indent(Token::Name(node->op()), node); 1036 Visit(node->target()); 1037 Visit(node->value()); 1038} 1039 1040 1041void AstPrinter::VisitThrow(Throw* node) { 1042 PrintIndentedVisit("THROW", node->exception()); 1043} 1044 1045 1046void AstPrinter::VisitProperty(Property* node) { 1047 IndentedScope indent("PROPERTY", node); 1048 Visit(node->obj()); 1049 Literal* literal = node->key()->AsLiteral(); 1050 if (literal != NULL && literal->handle()->IsSymbol()) { 1051 PrintLiteralIndented("NAME", literal->handle(), false); 1052 } else { 1053 PrintIndentedVisit("KEY", node->key()); 1054 } 1055} 1056 1057 1058void AstPrinter::VisitCall(Call* node) { 1059 IndentedScope indent("CALL"); 1060 Visit(node->expression()); 1061 PrintArguments(node->arguments()); 1062} 1063 1064 1065void AstPrinter::VisitCallNew(CallNew* node) { 1066 IndentedScope indent("CALL NEW"); 1067 Visit(node->expression()); 1068 PrintArguments(node->arguments()); 1069} 1070 1071 1072void AstPrinter::VisitCallRuntime(CallRuntime* node) { 1073 PrintLiteralIndented("CALL RUNTIME ", node->name(), false); 1074 IndentedScope indent; 1075 PrintArguments(node->arguments()); 1076} 1077 1078 1079void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { 1080 PrintIndentedVisit(Token::Name(node->op()), node->expression()); 1081} 1082 1083 1084void AstPrinter::VisitCountOperation(CountOperation* node) { 1085 EmbeddedVector<char, 128> buf; 1086 if (node->type()->IsKnown()) { 1087 OS::SNPrintF(buf, "%s %s (type = %s)", 1088 (node->is_prefix() ? "PRE" : "POST"), 1089 Token::Name(node->op()), 1090 StaticType::Type2String(node->type())); 1091 } else { 1092 OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"), 1093 Token::Name(node->op())); 1094 } 1095 PrintIndentedVisit(buf.start(), node->expression()); 1096} 1097 1098 1099void AstPrinter::VisitBinaryOperation(BinaryOperation* node) { 1100 IndentedScope indent(Token::Name(node->op()), node); 1101 Visit(node->left()); 1102 Visit(node->right()); 1103} 1104 1105 1106void AstPrinter::VisitCompareOperation(CompareOperation* node) { 1107 IndentedScope indent(Token::Name(node->op()), node); 1108 Visit(node->left()); 1109 Visit(node->right()); 1110} 1111 1112 1113void AstPrinter::VisitThisFunction(ThisFunction* node) { 1114 IndentedScope indent("THIS-FUNCTION"); 1115} 1116 1117 1118TagScope::TagScope(JsonAstBuilder* builder, const char* name) 1119 : builder_(builder), next_(builder->tag()), has_body_(false) { 1120 if (next_ != NULL) { 1121 next_->use(); 1122 builder->Print(",\n"); 1123 } 1124 builder->set_tag(this); 1125 builder->PrintIndented("["); 1126 builder->Print("\"%s\"", name); 1127 builder->increase_indent(JsonAstBuilder::kTagIndentSize); 1128} 1129 1130 1131TagScope::~TagScope() { 1132 builder_->decrease_indent(JsonAstBuilder::kTagIndentSize); 1133 if (has_body_) { 1134 builder_->Print("\n"); 1135 builder_->PrintIndented("]"); 1136 } else { 1137 builder_->Print("]"); 1138 } 1139 builder_->set_tag(next_); 1140} 1141 1142 1143AttributesScope::AttributesScope(JsonAstBuilder* builder) 1144 : builder_(builder), attribute_count_(0) { 1145 builder->set_attributes(this); 1146 builder->tag()->use(); 1147 builder->Print(",\n"); 1148 builder->PrintIndented("{"); 1149 builder->increase_indent(JsonAstBuilder::kAttributesIndentSize); 1150} 1151 1152 1153AttributesScope::~AttributesScope() { 1154 builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize); 1155 if (attribute_count_ > 1) { 1156 builder_->Print("\n"); 1157 builder_->PrintIndented("}"); 1158 } else { 1159 builder_->Print("}"); 1160 } 1161 builder_->set_attributes(NULL); 1162} 1163 1164 1165const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) { 1166 Init(); 1167 Visit(program); 1168 Print("\n"); 1169 return Output(); 1170} 1171 1172 1173void JsonAstBuilder::AddAttributePrefix(const char* name) { 1174 if (attributes()->is_used()) { 1175 Print(",\n"); 1176 PrintIndented("\""); 1177 } else { 1178 Print("\""); 1179 } 1180 Print("%s\":", name); 1181 attributes()->use(); 1182} 1183 1184 1185void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) { 1186 SmartPointer<char> value_string = value->ToCString(); 1187 AddAttributePrefix(name); 1188 Print("\"%s\"", *value_string); 1189} 1190 1191 1192void JsonAstBuilder::AddAttribute(const char* name, const char* value) { 1193 AddAttributePrefix(name); 1194 Print("\"%s\"", value); 1195} 1196 1197 1198void JsonAstBuilder::AddAttribute(const char* name, int value) { 1199 AddAttributePrefix(name); 1200 Print("%d", value); 1201} 1202 1203 1204void JsonAstBuilder::AddAttribute(const char* name, bool value) { 1205 AddAttributePrefix(name); 1206 Print(value ? "true" : "false"); 1207} 1208 1209 1210void JsonAstBuilder::VisitBlock(Block* stmt) { 1211 TagScope tag(this, "Block"); 1212 VisitStatements(stmt->statements()); 1213} 1214 1215 1216void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { 1217 TagScope tag(this, "ExpressionStatement"); 1218 Visit(stmt->expression()); 1219} 1220 1221 1222void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 1223 TagScope tag(this, "EmptyStatement"); 1224} 1225 1226 1227void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) { 1228 TagScope tag(this, "IfStatement"); 1229 Visit(stmt->condition()); 1230 Visit(stmt->then_statement()); 1231 Visit(stmt->else_statement()); 1232} 1233 1234 1235void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) { 1236 TagScope tag(this, "ContinueStatement"); 1237} 1238 1239 1240void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) { 1241 TagScope tag(this, "BreakStatement"); 1242} 1243 1244 1245void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) { 1246 TagScope tag(this, "ReturnStatement"); 1247 Visit(stmt->expression()); 1248} 1249 1250 1251void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 1252 TagScope tag(this, "WithEnterStatement"); 1253 Visit(stmt->expression()); 1254} 1255 1256 1257void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 1258 TagScope tag(this, "WithExitStatement"); 1259} 1260 1261 1262void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 1263 TagScope tag(this, "SwitchStatement"); 1264} 1265 1266 1267void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 1268 TagScope tag(this, "DoWhileStatement"); 1269 Visit(stmt->body()); 1270 Visit(stmt->cond()); 1271} 1272 1273 1274void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) { 1275 TagScope tag(this, "WhileStatement"); 1276 Visit(stmt->cond()); 1277 Visit(stmt->body()); 1278} 1279 1280 1281void JsonAstBuilder::VisitForStatement(ForStatement* stmt) { 1282 TagScope tag(this, "ForStatement"); 1283 if (stmt->init() != NULL) Visit(stmt->init()); 1284 if (stmt->cond() != NULL) Visit(stmt->cond()); 1285 Visit(stmt->body()); 1286 if (stmt->next() != NULL) Visit(stmt->next()); 1287} 1288 1289 1290void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) { 1291 TagScope tag(this, "ForInStatement"); 1292 Visit(stmt->each()); 1293 Visit(stmt->enumerable()); 1294 Visit(stmt->body()); 1295} 1296 1297 1298void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 1299 TagScope tag(this, "TryCatchStatement"); 1300 Visit(stmt->try_block()); 1301 Visit(stmt->catch_var()); 1302 Visit(stmt->catch_block()); 1303} 1304 1305 1306void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1307 TagScope tag(this, "TryFinallyStatement"); 1308 Visit(stmt->try_block()); 1309 Visit(stmt->finally_block()); 1310} 1311 1312 1313void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 1314 TagScope tag(this, "DebuggerStatement"); 1315} 1316 1317 1318void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 1319 TagScope tag(this, "FunctionLiteral"); 1320 { 1321 AttributesScope attributes(this); 1322 AddAttribute("name", expr->name()); 1323 } 1324 VisitDeclarations(expr->scope()->declarations()); 1325 VisitStatements(expr->body()); 1326} 1327 1328 1329void JsonAstBuilder::VisitFunctionBoilerplateLiteral( 1330 FunctionBoilerplateLiteral* expr) { 1331 TagScope tag(this, "FunctionBoilerplateLiteral"); 1332} 1333 1334 1335void JsonAstBuilder::VisitConditional(Conditional* expr) { 1336 TagScope tag(this, "Conditional"); 1337} 1338 1339 1340void JsonAstBuilder::VisitSlot(Slot* expr) { 1341 TagScope tag(this, "Slot"); 1342 { 1343 AttributesScope attributes(this); 1344 switch (expr->type()) { 1345 case Slot::PARAMETER: 1346 AddAttribute("type", "PARAMETER"); 1347 break; 1348 case Slot::LOCAL: 1349 AddAttribute("type", "LOCAL"); 1350 break; 1351 case Slot::CONTEXT: 1352 AddAttribute("type", "CONTEXT"); 1353 break; 1354 case Slot::LOOKUP: 1355 AddAttribute("type", "LOOKUP"); 1356 break; 1357 } 1358 AddAttribute("index", expr->index()); 1359 } 1360} 1361 1362 1363void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) { 1364 if (expr->var()->rewrite() == NULL) { 1365 TagScope tag(this, "VariableProxy"); 1366 { 1367 AttributesScope attributes(this); 1368 AddAttribute("name", expr->name()); 1369 AddAttribute("mode", Variable::Mode2String(expr->var()->mode())); 1370 } 1371 } else { 1372 Visit(expr->var()->rewrite()); 1373 } 1374} 1375 1376 1377void JsonAstBuilder::VisitLiteral(Literal* expr) { 1378 TagScope tag(this, "Literal"); 1379 { 1380 AttributesScope attributes(this); 1381 Handle<Object> handle = expr->handle(); 1382 if (handle->IsString()) { 1383 AddAttribute("handle", Handle<String>(String::cast(*handle))); 1384 } else if (handle->IsSmi()) { 1385 AddAttribute("handle", Smi::cast(*handle)->value()); 1386 } 1387 } 1388} 1389 1390 1391void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 1392 TagScope tag(this, "RegExpLiteral"); 1393} 1394 1395 1396void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 1397 TagScope tag(this, "ObjectLiteral"); 1398} 1399 1400 1401void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 1402 TagScope tag(this, "ArrayLiteral"); 1403} 1404 1405 1406void JsonAstBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 1407 TagScope tag(this, "CatchExtensionObject"); 1408 Visit(expr->key()); 1409 Visit(expr->value()); 1410} 1411 1412 1413void JsonAstBuilder::VisitAssignment(Assignment* expr) { 1414 TagScope tag(this, "Assignment"); 1415 { 1416 AttributesScope attributes(this); 1417 AddAttribute("op", Token::Name(expr->op())); 1418 } 1419 Visit(expr->target()); 1420 Visit(expr->value()); 1421} 1422 1423 1424void JsonAstBuilder::VisitThrow(Throw* expr) { 1425 TagScope tag(this, "Throw"); 1426 Visit(expr->exception()); 1427} 1428 1429 1430void JsonAstBuilder::VisitProperty(Property* expr) { 1431 TagScope tag(this, "Property"); 1432 { 1433 AttributesScope attributes(this); 1434 AddAttribute("type", expr->is_synthetic() ? "SYNTHETIC" : "NORMAL"); 1435 } 1436 Visit(expr->obj()); 1437 Visit(expr->key()); 1438} 1439 1440 1441void JsonAstBuilder::VisitCall(Call* expr) { 1442 TagScope tag(this, "Call"); 1443 Visit(expr->expression()); 1444 VisitExpressions(expr->arguments()); 1445} 1446 1447 1448void JsonAstBuilder::VisitCallNew(CallNew* expr) { 1449 TagScope tag(this, "CallNew"); 1450 Visit(expr->expression()); 1451 VisitExpressions(expr->arguments()); 1452} 1453 1454 1455void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) { 1456 TagScope tag(this, "CallRuntime"); 1457 { 1458 AttributesScope attributes(this); 1459 AddAttribute("name", expr->name()); 1460 } 1461 VisitExpressions(expr->arguments()); 1462} 1463 1464 1465void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) { 1466 TagScope tag(this, "UnaryOperation"); 1467 { 1468 AttributesScope attributes(this); 1469 AddAttribute("op", Token::Name(expr->op())); 1470 } 1471 Visit(expr->expression()); 1472} 1473 1474 1475void JsonAstBuilder::VisitCountOperation(CountOperation* expr) { 1476 TagScope tag(this, "CountOperation"); 1477 { 1478 AttributesScope attributes(this); 1479 AddAttribute("is_prefix", expr->is_prefix()); 1480 AddAttribute("op", Token::Name(expr->op())); 1481 } 1482 Visit(expr->expression()); 1483} 1484 1485 1486void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) { 1487 TagScope tag(this, "BinaryOperation"); 1488 { 1489 AttributesScope attributes(this); 1490 AddAttribute("op", Token::Name(expr->op())); 1491 } 1492 Visit(expr->left()); 1493 Visit(expr->right()); 1494} 1495 1496 1497void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) { 1498 TagScope tag(this, "CompareOperation"); 1499 { 1500 AttributesScope attributes(this); 1501 AddAttribute("op", Token::Name(expr->op())); 1502 } 1503 Visit(expr->left()); 1504 Visit(expr->right()); 1505} 1506 1507 1508void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) { 1509 TagScope tag(this, "ThisFunction"); 1510} 1511 1512 1513void JsonAstBuilder::VisitDeclaration(Declaration* decl) { 1514 TagScope tag(this, "Declaration"); 1515 { 1516 AttributesScope attributes(this); 1517 AddAttribute("mode", Variable::Mode2String(decl->mode())); 1518 } 1519 Visit(decl->proxy()); 1520 if (decl->fun() != NULL) Visit(decl->fun()); 1521} 1522 1523 1524#endif // DEBUG 1525 1526} } // namespace v8::internal 1527