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 14namespace v8 { 15namespace internal { 16 17#ifdef DEBUG 18 19PrettyPrinter::PrettyPrinter(Zone* zone) { 20 output_ = NULL; 21 size_ = 0; 22 pos_ = 0; 23 InitializeAstVisitor(zone); 24} 25 26 27PrettyPrinter::~PrettyPrinter() { 28 DeleteArray(output_); 29} 30 31 32void 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 40void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 41 Print("var "); 42 PrintLiteral(node->proxy()->name(), false); 43 Print(";"); 44} 45 46 47void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { 48 Print("function "); 49 PrintLiteral(node->proxy()->name(), false); 50 Print(" = "); 51 PrintFunctionLiteral(node->fun()); 52 Print(";"); 53} 54 55 56void PrettyPrinter::VisitModuleDeclaration(ModuleDeclaration* node) { 57 Print("module "); 58 PrintLiteral(node->proxy()->name(), false); 59 Print(" = "); 60 Visit(node->module()); 61 Print(";"); 62} 63 64 65void 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 74void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) { 75 Print("export "); 76 PrintLiteral(node->proxy()->name(), false); 77 Print(";"); 78} 79 80 81void PrettyPrinter::VisitModuleLiteral(ModuleLiteral* node) { 82 VisitBlock(node->body()); 83} 84 85 86void PrettyPrinter::VisitModuleVariable(ModuleVariable* node) { 87 Visit(node->proxy()); 88} 89 90 91void PrettyPrinter::VisitModulePath(ModulePath* node) { 92 Visit(node->module()); 93 Print("."); 94 PrintLiteral(node->name(), false); 95} 96 97 98void PrettyPrinter::VisitModuleUrl(ModuleUrl* node) { 99 Print("at "); 100 PrintLiteral(node->url(), true); 101} 102 103 104void PrettyPrinter::VisitModuleStatement(ModuleStatement* node) { 105 Print("module "); 106 PrintLiteral(node->proxy()->name(), false); 107 Print(" "); 108 Visit(node->body()); 109} 110 111 112void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) { 113 Visit(node->expression()); 114 Print(";"); 115} 116 117 118void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) { 119 Print(";"); 120} 121 122 123void 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 135void 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 147void 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 159void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { 160 Print("return "); 161 Visit(node->expression()); 162 Print(";"); 163} 164 165 166void PrettyPrinter::VisitWithStatement(WithStatement* node) { 167 Print("with ("); 168 Visit(node->expression()); 169 Print(") "); 170 Visit(node->statement()); 171} 172 173 174void 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 186void 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 200void 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 210void PrettyPrinter::VisitWhileStatement(WhileStatement* node) { 211 PrintLabels(node->labels()); 212 Print("while ("); 213 Visit(node->cond()); 214 Print(") "); 215 Visit(node->body()); 216} 217 218 219void 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 239void 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 250void 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 261void 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 272void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 273 Print("try "); 274 Visit(node->try_block()); 275 Print(" finally "); 276 Visit(node->finally_block()); 277} 278 279 280void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 281 Print("debugger "); 282} 283 284 285void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 286 Print("("); 287 PrintFunctionLiteral(node); 288 Print(")"); 289} 290 291 292void 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 307void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { 308 Print("("); 309 PrintLiteral(node->name(), false); 310 Print(")"); 311} 312 313 314void 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 323void PrettyPrinter::VisitLiteral(Literal* node) { 324 PrintLiteral(node->value(), true); 325} 326 327 328void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 329 Print(" RegExp("); 330 PrintLiteral(node->pattern(), false); 331 Print(","); 332 PrintLiteral(node->flags(), false); 333 Print(") "); 334} 335 336 337void 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 347void 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 357void 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 367void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { 368 PrintLiteral(node->name(), false); 369} 370 371 372void PrettyPrinter::VisitAssignment(Assignment* node) { 373 Visit(node->target()); 374 Print(" %s ", Token::String(node->op())); 375 Visit(node->value()); 376} 377 378 379void PrettyPrinter::VisitYield(Yield* node) { 380 Print("yield "); 381 Visit(node->expression()); 382} 383 384 385void PrettyPrinter::VisitThrow(Throw* node) { 386 Print("throw "); 387 Visit(node->exception()); 388} 389 390 391void 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 408void PrettyPrinter::VisitCall(Call* node) { 409 Visit(node->expression()); 410 PrintArguments(node->arguments()); 411} 412 413 414void PrettyPrinter::VisitCallNew(CallNew* node) { 415 Print("new ("); 416 Visit(node->expression()); 417 Print(")"); 418 PrintArguments(node->arguments()); 419} 420 421 422void PrettyPrinter::VisitCallRuntime(CallRuntime* node) { 423 Print("%%"); 424 PrintLiteral(node->name(), false); 425 PrintArguments(node->arguments()); 426} 427 428 429void 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 439void 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 448void 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 457void 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 466void PrettyPrinter::VisitThisFunction(ThisFunction* node) { 467 Print("<this-function>"); 468} 469 470 471void PrettyPrinter::VisitSuperReference(SuperReference* node) { 472 Print("<super-reference>"); 473} 474 475 476const char* PrettyPrinter::Print(AstNode* node) { 477 Init(); 478 Visit(node); 479 return output_; 480} 481 482 483const 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 492const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) { 493 Init(); 494 PrintStatements(program->body()); 495 Print("\n"); 496 return output_; 497} 498 499 500void PrettyPrinter::PrintOut(Zone* zone, AstNode* node) { 501 PrettyPrinter printer(zone); 502 PrintF("%s", printer.Print(node)); 503} 504 505 506void 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 518void 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 545void 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 554void 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 564void 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 574void 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 612void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) { 613 PrintLiteral(value->string(), quote); 614} 615 616 617void 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 627void 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 635void 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 648class 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 669AstPrinter::AstPrinter(Zone* zone) : PrettyPrinter(zone), indent_(0) { 670} 671 672 673AstPrinter::~AstPrinter() { 674 DCHECK(indent_ == 0); 675} 676 677 678void AstPrinter::PrintIndented(const char* txt) { 679 for (int i = 0; i < indent_; i++) { 680 Print(". "); 681 } 682 Print(txt); 683} 684 685 686void 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 696void 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 711void 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 719void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { 720 IndentedScope indent(this, s); 721 Visit(node); 722} 723 724 725const 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 738void 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 748void 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 759void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) { 760 for (int i = 0; i < statements->length(); i++) { 761 Visit(statements->at(i)); 762 } 763} 764 765 766void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 767 for (int i = 0; i < arguments->length(); i++) { 768 Visit(arguments->at(i)); 769 } 770} 771 772 773void 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. 781void 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. 789void 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 798void AstPrinter::VisitModuleDeclaration(ModuleDeclaration* node) { 799 IndentedScope indent(this, "MODULE"); 800 PrintLiteralIndented("NAME", node->proxy()->name(), true); 801 Visit(node->module()); 802} 803 804 805void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) { 806 IndentedScope indent(this, "IMPORT"); 807 PrintLiteralIndented("NAME", node->proxy()->name(), true); 808 Visit(node->module()); 809} 810 811 812void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) { 813 IndentedScope indent(this, "EXPORT "); 814 PrintLiteral(node->proxy()->name(), true); 815} 816 817 818void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) { 819 IndentedScope indent(this, "MODULE LITERAL"); 820 VisitBlock(node->body()); 821} 822 823 824void AstPrinter::VisitModuleVariable(ModuleVariable* node) { 825 IndentedScope indent(this, "MODULE VARIABLE"); 826 Visit(node->proxy()); 827} 828 829 830void 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 837void AstPrinter::VisitModuleUrl(ModuleUrl* node) { 838 PrintLiteralIndented("URL", node->url(), true); 839} 840 841 842void 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 849void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { 850 IndentedScope indent(this, "EXPRESSION STATEMENT"); 851 Visit(node->expression()); 852} 853 854 855void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { 856 IndentedScope indent(this, "EMPTY"); 857} 858 859 860void 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 870void AstPrinter::VisitContinueStatement(ContinueStatement* node) { 871 IndentedScope indent(this, "CONTINUE"); 872 PrintLabelsIndented(node->target()->labels()); 873} 874 875 876void AstPrinter::VisitBreakStatement(BreakStatement* node) { 877 IndentedScope indent(this, "BREAK"); 878 PrintLabelsIndented(node->target()->labels()); 879} 880 881 882void AstPrinter::VisitReturnStatement(ReturnStatement* node) { 883 IndentedScope indent(this, "RETURN"); 884 Visit(node->expression()); 885} 886 887 888void AstPrinter::VisitWithStatement(WithStatement* node) { 889 IndentedScope indent(this, "WITH"); 890 PrintIndentedVisit("OBJECT", node->expression()); 891 PrintIndentedVisit("BODY", node->statement()); 892} 893 894 895void 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 905void 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 917void 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 925void 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 933void 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 943void 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 951void 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 959void 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 969void 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 976void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 977 IndentedScope indent(this, "DEBUGGER"); 978} 979 980 981void 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 993void AstPrinter::VisitClassLiteral(ClassLiteral* node) { 994 IndentedScope indent(this, "CLASS LITERAL"); 995 PrintLiteralIndented("NAME", node->name(), false); 996} 997 998 999void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { 1000 IndentedScope indent(this, "NATIVE FUNC LITERAL"); 1001 PrintLiteralIndented("NAME", node->name(), false); 1002} 1003 1004 1005void 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. 1014void AstPrinter::VisitLiteral(Literal* node) { 1015 PrintLiteralIndented("LITERAL", node->value(), true); 1016} 1017 1018 1019void 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 1026void 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 1059void 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. 1071void 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 1095void AstPrinter::VisitAssignment(Assignment* node) { 1096 IndentedScope indent(this, Token::Name(node->op())); 1097 Visit(node->target()); 1098 Visit(node->value()); 1099} 1100 1101 1102void AstPrinter::VisitYield(Yield* node) { 1103 IndentedScope indent(this, "YIELD"); 1104 Visit(node->expression()); 1105} 1106 1107 1108void AstPrinter::VisitThrow(Throw* node) { 1109 IndentedScope indent(this, "THROW"); 1110 Visit(node->exception()); 1111} 1112 1113 1114void 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 1126void AstPrinter::VisitCall(Call* node) { 1127 IndentedScope indent(this, "CALL"); 1128 Visit(node->expression()); 1129 PrintArguments(node->arguments()); 1130} 1131 1132 1133void AstPrinter::VisitCallNew(CallNew* node) { 1134 IndentedScope indent(this, "CALL NEW"); 1135 Visit(node->expression()); 1136 PrintArguments(node->arguments()); 1137} 1138 1139 1140void AstPrinter::VisitCallRuntime(CallRuntime* node) { 1141 IndentedScope indent(this, "CALL RUNTIME"); 1142 PrintLiteralIndented("NAME", node->name(), false); 1143 PrintArguments(node->arguments()); 1144} 1145 1146 1147void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { 1148 IndentedScope indent(this, Token::Name(node->op())); 1149 Visit(node->expression()); 1150} 1151 1152 1153void 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 1162void AstPrinter::VisitBinaryOperation(BinaryOperation* node) { 1163 IndentedScope indent(this, Token::Name(node->op())); 1164 Visit(node->left()); 1165 Visit(node->right()); 1166} 1167 1168 1169void AstPrinter::VisitCompareOperation(CompareOperation* node) { 1170 IndentedScope indent(this, Token::Name(node->op())); 1171 Visit(node->left()); 1172 Visit(node->right()); 1173} 1174 1175 1176void AstPrinter::VisitThisFunction(ThisFunction* node) { 1177 IndentedScope indent(this, "THIS-FUNCTION"); 1178} 1179 1180 1181void AstPrinter::VisitSuperReference(SuperReference* node) { 1182 IndentedScope indent(this, "SUPER-REFERENCE"); 1183} 1184 1185#endif // DEBUG 1186 1187} } // namespace v8::internal 1188