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 "src/ast/prettyprinter.h" 6 7 #include <stdarg.h> 8 9 #include "src/ast/ast-value-factory.h" 10 #include "src/ast/scopes.h" 11 #include "src/base/platform/platform.h" 12 13 namespace v8 { 14 namespace internal { 15 16 CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin) { 17 output_ = NULL; 18 size_ = 0; 19 pos_ = 0; 20 position_ = 0; 21 found_ = false; 22 done_ = false; 23 is_builtin_ = is_builtin; 24 InitializeAstVisitor(isolate); 25 } 26 27 28 CallPrinter::~CallPrinter() { DeleteArray(output_); } 29 30 31 const char* CallPrinter::Print(FunctionLiteral* program, int position) { 32 Init(); 33 position_ = position; 34 Find(program); 35 return output_; 36 } 37 38 39 void CallPrinter::Find(AstNode* node, bool print) { 40 if (done_) return; 41 if (found_) { 42 if (print) { 43 int start = pos_; 44 Visit(node); 45 if (start != pos_) return; 46 } 47 Print("(intermediate value)"); 48 } else { 49 Visit(node); 50 } 51 } 52 53 54 void CallPrinter::Init() { 55 if (size_ == 0) { 56 DCHECK(output_ == NULL); 57 const int initial_size = 256; 58 output_ = NewArray<char>(initial_size); 59 size_ = initial_size; 60 } 61 output_[0] = '\0'; 62 pos_ = 0; 63 } 64 65 66 void CallPrinter::Print(const char* format, ...) { 67 if (!found_ || done_) return; 68 for (;;) { 69 va_list arguments; 70 va_start(arguments, format); 71 int n = VSNPrintF(Vector<char>(output_, size_) + pos_, format, arguments); 72 va_end(arguments); 73 74 if (n >= 0) { 75 // there was enough space - we are done 76 pos_ += n; 77 return; 78 } else { 79 // there was not enough space - allocate more and try again 80 const int slack = 32; 81 int new_size = size_ + (size_ >> 1) + slack; 82 char* new_output = NewArray<char>(new_size); 83 MemCopy(new_output, output_, pos_); 84 DeleteArray(output_); 85 output_ = new_output; 86 size_ = new_size; 87 } 88 } 89 } 90 91 92 void CallPrinter::VisitBlock(Block* node) { 93 FindStatements(node->statements()); 94 } 95 96 97 void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {} 98 99 100 void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {} 101 102 103 void CallPrinter::VisitImportDeclaration(ImportDeclaration* node) { 104 } 105 106 107 void CallPrinter::VisitExportDeclaration(ExportDeclaration* node) {} 108 109 110 void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) { 111 Find(node->expression()); 112 } 113 114 115 void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {} 116 117 118 void CallPrinter::VisitSloppyBlockFunctionStatement( 119 SloppyBlockFunctionStatement* node) { 120 Find(node->statement()); 121 } 122 123 124 void CallPrinter::VisitIfStatement(IfStatement* node) { 125 Find(node->condition()); 126 Find(node->then_statement()); 127 if (node->HasElseStatement()) { 128 Find(node->else_statement()); 129 } 130 } 131 132 133 void CallPrinter::VisitContinueStatement(ContinueStatement* node) {} 134 135 136 void CallPrinter::VisitBreakStatement(BreakStatement* node) {} 137 138 139 void CallPrinter::VisitReturnStatement(ReturnStatement* node) { 140 Find(node->expression()); 141 } 142 143 144 void CallPrinter::VisitWithStatement(WithStatement* node) { 145 Find(node->expression()); 146 Find(node->statement()); 147 } 148 149 150 void CallPrinter::VisitSwitchStatement(SwitchStatement* node) { 151 Find(node->tag()); 152 ZoneList<CaseClause*>* cases = node->cases(); 153 for (int i = 0; i < cases->length(); i++) Find(cases->at(i)); 154 } 155 156 157 void CallPrinter::VisitCaseClause(CaseClause* clause) { 158 if (!clause->is_default()) { 159 Find(clause->label()); 160 } 161 FindStatements(clause->statements()); 162 } 163 164 165 void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 166 Find(node->body()); 167 Find(node->cond()); 168 } 169 170 171 void CallPrinter::VisitWhileStatement(WhileStatement* node) { 172 Find(node->cond()); 173 Find(node->body()); 174 } 175 176 177 void CallPrinter::VisitForStatement(ForStatement* node) { 178 if (node->init() != NULL) { 179 Find(node->init()); 180 } 181 if (node->cond() != NULL) Find(node->cond()); 182 if (node->next() != NULL) Find(node->next()); 183 Find(node->body()); 184 } 185 186 187 void CallPrinter::VisitForInStatement(ForInStatement* node) { 188 Find(node->each()); 189 Find(node->enumerable()); 190 Find(node->body()); 191 } 192 193 194 void CallPrinter::VisitForOfStatement(ForOfStatement* node) { 195 Find(node->each()); 196 Find(node->assign_iterator()); 197 Find(node->body()); 198 Find(node->next_result()); 199 } 200 201 202 void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 203 Find(node->try_block()); 204 Find(node->catch_block()); 205 } 206 207 208 void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 209 Find(node->try_block()); 210 Find(node->finally_block()); 211 } 212 213 214 void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {} 215 216 217 void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 218 FindStatements(node->body()); 219 } 220 221 222 void CallPrinter::VisitClassLiteral(ClassLiteral* node) { 223 if (node->extends()) Find(node->extends()); 224 for (int i = 0; i < node->properties()->length(); i++) { 225 Find(node->properties()->at(i)->value()); 226 } 227 } 228 229 230 void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {} 231 232 233 void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); } 234 235 236 void CallPrinter::VisitConditional(Conditional* node) { 237 Find(node->condition()); 238 Find(node->then_expression()); 239 Find(node->else_expression()); 240 } 241 242 243 void CallPrinter::VisitLiteral(Literal* node) { 244 PrintLiteral(*node->value(), true); 245 } 246 247 248 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 249 Print("/"); 250 PrintLiteral(*node->pattern(), false); 251 Print("/"); 252 if (node->flags() & RegExp::kGlobal) Print("g"); 253 if (node->flags() & RegExp::kIgnoreCase) Print("i"); 254 if (node->flags() & RegExp::kMultiline) Print("m"); 255 if (node->flags() & RegExp::kUnicode) Print("u"); 256 if (node->flags() & RegExp::kSticky) Print("y"); 257 } 258 259 260 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) { 261 for (int i = 0; i < node->properties()->length(); i++) { 262 Find(node->properties()->at(i)->value()); 263 } 264 } 265 266 267 void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) { 268 Print("["); 269 for (int i = 0; i < node->values()->length(); i++) { 270 if (i != 0) Print(","); 271 Find(node->values()->at(i), true); 272 } 273 Print("]"); 274 } 275 276 277 void CallPrinter::VisitVariableProxy(VariableProxy* node) { 278 if (is_builtin_) { 279 // Variable names of builtins are meaningless due to minification. 280 Print("(var)"); 281 } else { 282 PrintLiteral(*node->name(), false); 283 } 284 } 285 286 287 void CallPrinter::VisitAssignment(Assignment* node) { 288 Find(node->target()); 289 Find(node->value()); 290 } 291 292 293 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); } 294 295 296 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); } 297 298 299 void CallPrinter::VisitProperty(Property* node) { 300 Expression* key = node->key(); 301 Literal* literal = key->AsLiteral(); 302 if (literal != NULL && literal->value()->IsInternalizedString()) { 303 Find(node->obj(), true); 304 Print("."); 305 PrintLiteral(*literal->value(), false); 306 } else { 307 Find(node->obj(), true); 308 Print("["); 309 Find(key, true); 310 Print("]"); 311 } 312 } 313 314 315 void CallPrinter::VisitCall(Call* node) { 316 bool was_found = !found_ && node->position() == position_; 317 if (was_found) { 318 // Bail out if the error is caused by a direct call to a variable in builtin 319 // code. The variable name is meaningless due to minification. 320 if (is_builtin_ && node->expression()->IsVariableProxy()) { 321 done_ = true; 322 return; 323 } 324 found_ = true; 325 } 326 Find(node->expression(), true); 327 if (!was_found) Print("(...)"); 328 FindArguments(node->arguments()); 329 if (was_found) done_ = true; 330 } 331 332 333 void CallPrinter::VisitCallNew(CallNew* node) { 334 bool was_found = !found_ && node->position() == position_; 335 if (was_found) { 336 // Bail out if the error is caused by a direct call to a variable in builtin 337 // code. The variable name is meaningless due to minification. 338 if (is_builtin_ && node->expression()->IsVariableProxy()) { 339 done_ = true; 340 return; 341 } 342 found_ = true; 343 } 344 Find(node->expression(), was_found); 345 FindArguments(node->arguments()); 346 if (was_found) done_ = true; 347 } 348 349 350 void CallPrinter::VisitCallRuntime(CallRuntime* node) { 351 FindArguments(node->arguments()); 352 } 353 354 355 void CallPrinter::VisitUnaryOperation(UnaryOperation* node) { 356 Token::Value op = node->op(); 357 bool needsSpace = 358 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; 359 Print("(%s%s", Token::String(op), needsSpace ? " " : ""); 360 Find(node->expression(), true); 361 Print(")"); 362 } 363 364 365 void CallPrinter::VisitCountOperation(CountOperation* node) { 366 Print("("); 367 if (node->is_prefix()) Print("%s", Token::String(node->op())); 368 Find(node->expression(), true); 369 if (node->is_postfix()) Print("%s", Token::String(node->op())); 370 Print(")"); 371 } 372 373 374 void CallPrinter::VisitBinaryOperation(BinaryOperation* node) { 375 Print("("); 376 Find(node->left(), true); 377 Print(" %s ", Token::String(node->op())); 378 Find(node->right(), true); 379 Print(")"); 380 } 381 382 383 void CallPrinter::VisitCompareOperation(CompareOperation* node) { 384 Print("("); 385 Find(node->left(), true); 386 Print(" %s ", Token::String(node->op())); 387 Find(node->right(), true); 388 Print(")"); 389 } 390 391 392 void CallPrinter::VisitSpread(Spread* node) { 393 Print("(..."); 394 Find(node->expression(), true); 395 Print(")"); 396 } 397 398 399 void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) { 400 UNREACHABLE(); 401 } 402 403 404 void CallPrinter::VisitThisFunction(ThisFunction* node) {} 405 406 407 void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {} 408 409 410 void CallPrinter::VisitSuperCallReference(SuperCallReference* node) { 411 Print("super"); 412 } 413 414 415 void CallPrinter::VisitRewritableAssignmentExpression( 416 RewritableAssignmentExpression* node) { 417 Find(node->expression()); 418 } 419 420 421 void CallPrinter::FindStatements(ZoneList<Statement*>* statements) { 422 if (statements == NULL) return; 423 for (int i = 0; i < statements->length(); i++) { 424 Find(statements->at(i)); 425 } 426 } 427 428 429 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) { 430 if (found_) return; 431 for (int i = 0; i < arguments->length(); i++) { 432 Find(arguments->at(i)); 433 } 434 } 435 436 437 void CallPrinter::PrintLiteral(Object* value, bool quote) { 438 Object* object = value; 439 if (object->IsString()) { 440 if (quote) Print("\""); 441 Print("%s", String::cast(object)->ToCString().get()); 442 if (quote) Print("\""); 443 } else if (object->IsNull()) { 444 Print("null"); 445 } else if (object->IsTrue()) { 446 Print("true"); 447 } else if (object->IsFalse()) { 448 Print("false"); 449 } else if (object->IsUndefined()) { 450 Print("undefined"); 451 } else if (object->IsNumber()) { 452 Print("%g", object->Number()); 453 } else if (object->IsSymbol()) { 454 // Symbols can only occur as literals if they were inserted by the parser. 455 PrintLiteral(Symbol::cast(object)->name(), false); 456 } 457 } 458 459 460 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) { 461 PrintLiteral(*value->string(), quote); 462 } 463 464 465 //----------------------------------------------------------------------------- 466 467 468 #ifdef DEBUG 469 470 // A helper for ast nodes that use FeedbackVectorSlots. 471 static int FormatSlotNode(Vector<char>* buf, Expression* node, 472 const char* node_name, FeedbackVectorSlot slot) { 473 int pos = SNPrintF(*buf, "%s", node_name); 474 if (!slot.IsInvalid()) { 475 pos = SNPrintF(*buf + pos, " Slot(%d)", slot.ToInt()); 476 } 477 return pos; 478 } 479 480 481 PrettyPrinter::PrettyPrinter(Isolate* isolate) { 482 output_ = NULL; 483 size_ = 0; 484 pos_ = 0; 485 InitializeAstVisitor(isolate); 486 } 487 488 489 PrettyPrinter::~PrettyPrinter() { 490 DeleteArray(output_); 491 } 492 493 494 void PrettyPrinter::VisitBlock(Block* node) { 495 if (!node->ignore_completion_value()) Print("{ "); 496 PrintStatements(node->statements()); 497 if (node->statements()->length() > 0) Print(" "); 498 if (!node->ignore_completion_value()) Print("}"); 499 } 500 501 502 void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 503 Print("var "); 504 PrintLiteral(node->proxy()->name(), false); 505 Print(";"); 506 } 507 508 509 void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { 510 Print("function "); 511 PrintLiteral(node->proxy()->name(), false); 512 Print(" = "); 513 PrintFunctionLiteral(node->fun()); 514 Print(";"); 515 } 516 517 518 void PrettyPrinter::VisitImportDeclaration(ImportDeclaration* node) { 519 Print("import "); 520 PrintLiteral(node->proxy()->name(), false); 521 Print(" from "); 522 PrintLiteral(node->module_specifier()->string(), true); 523 Print(";"); 524 } 525 526 527 void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) { 528 Print("export "); 529 PrintLiteral(node->proxy()->name(), false); 530 Print(";"); 531 } 532 533 534 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) { 535 Visit(node->expression()); 536 Print(";"); 537 } 538 539 540 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) { 541 Print(";"); 542 } 543 544 545 void PrettyPrinter::VisitSloppyBlockFunctionStatement( 546 SloppyBlockFunctionStatement* node) { 547 Visit(node->statement()); 548 } 549 550 551 void PrettyPrinter::VisitIfStatement(IfStatement* node) { 552 Print("if ("); 553 Visit(node->condition()); 554 Print(") "); 555 Visit(node->then_statement()); 556 if (node->HasElseStatement()) { 557 Print(" else "); 558 Visit(node->else_statement()); 559 } 560 } 561 562 563 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) { 564 Print("continue"); 565 ZoneList<const AstRawString*>* labels = node->target()->labels(); 566 if (labels != NULL) { 567 Print(" "); 568 DCHECK(labels->length() > 0); // guaranteed to have at least one entry 569 PrintLiteral(labels->at(0), false); // any label from the list is fine 570 } 571 Print(";"); 572 } 573 574 575 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) { 576 Print("break"); 577 ZoneList<const AstRawString*>* labels = node->target()->labels(); 578 if (labels != NULL) { 579 Print(" "); 580 DCHECK(labels->length() > 0); // guaranteed to have at least one entry 581 PrintLiteral(labels->at(0), false); // any label from the list is fine 582 } 583 Print(";"); 584 } 585 586 587 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { 588 Print("return "); 589 Visit(node->expression()); 590 Print(";"); 591 } 592 593 594 void PrettyPrinter::VisitWithStatement(WithStatement* node) { 595 Print("with ("); 596 Visit(node->expression()); 597 Print(") "); 598 Visit(node->statement()); 599 } 600 601 602 void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) { 603 PrintLabels(node->labels()); 604 Print("switch ("); 605 Visit(node->tag()); 606 Print(") { "); 607 ZoneList<CaseClause*>* cases = node->cases(); 608 for (int i = 0; i < cases->length(); i++) 609 Visit(cases->at(i)); 610 Print("}"); 611 } 612 613 614 void PrettyPrinter::VisitCaseClause(CaseClause* clause) { 615 if (clause->is_default()) { 616 Print("default"); 617 } else { 618 Print("case "); 619 Visit(clause->label()); 620 } 621 Print(": "); 622 PrintStatements(clause->statements()); 623 if (clause->statements()->length() > 0) 624 Print(" "); 625 } 626 627 628 void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 629 PrintLabels(node->labels()); 630 Print("do "); 631 Visit(node->body()); 632 Print(" while ("); 633 Visit(node->cond()); 634 Print(");"); 635 } 636 637 638 void PrettyPrinter::VisitWhileStatement(WhileStatement* node) { 639 PrintLabels(node->labels()); 640 Print("while ("); 641 Visit(node->cond()); 642 Print(") "); 643 Visit(node->body()); 644 } 645 646 647 void PrettyPrinter::VisitForStatement(ForStatement* node) { 648 PrintLabels(node->labels()); 649 Print("for ("); 650 if (node->init() != NULL) { 651 Visit(node->init()); 652 Print(" "); 653 } else { 654 Print("; "); 655 } 656 if (node->cond() != NULL) Visit(node->cond()); 657 Print("; "); 658 if (node->next() != NULL) { 659 Visit(node->next()); // prints extra ';', unfortunately 660 // to fix: should use Expression for next 661 } 662 Print(") "); 663 Visit(node->body()); 664 } 665 666 667 void PrettyPrinter::VisitForInStatement(ForInStatement* node) { 668 PrintLabels(node->labels()); 669 Print("for ("); 670 Visit(node->each()); 671 Print(" in "); 672 Visit(node->enumerable()); 673 Print(") "); 674 Visit(node->body()); 675 } 676 677 678 void PrettyPrinter::VisitForOfStatement(ForOfStatement* node) { 679 PrintLabels(node->labels()); 680 Print("for ("); 681 Visit(node->each()); 682 Print(" of "); 683 Visit(node->iterable()); 684 Print(") "); 685 Visit(node->body()); 686 } 687 688 689 void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 690 Print("try "); 691 Visit(node->try_block()); 692 Print(" catch ("); 693 const bool quote = false; 694 PrintLiteral(node->variable()->name(), quote); 695 Print(") "); 696 Visit(node->catch_block()); 697 } 698 699 700 void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 701 Print("try "); 702 Visit(node->try_block()); 703 Print(" finally "); 704 Visit(node->finally_block()); 705 } 706 707 708 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 709 Print("debugger "); 710 } 711 712 713 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 714 Print("("); 715 PrintFunctionLiteral(node); 716 Print(")"); 717 } 718 719 720 void PrettyPrinter::VisitClassLiteral(ClassLiteral* node) { 721 Print("(class "); 722 PrintLiteral(node->name(), false); 723 if (node->extends()) { 724 Print(" extends "); 725 Visit(node->extends()); 726 } 727 Print(" { "); 728 for (int i = 0; i < node->properties()->length(); i++) { 729 PrintObjectLiteralProperty(node->properties()->at(i)); 730 } 731 Print(" })"); 732 } 733 734 735 void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { 736 Print("("); 737 PrintLiteral(node->name(), false); 738 Print(")"); 739 } 740 741 742 void PrettyPrinter::VisitDoExpression(DoExpression* node) { 743 Print("(do {"); 744 PrintStatements(node->block()->statements()); 745 Print("})"); 746 } 747 748 749 void PrettyPrinter::VisitConditional(Conditional* node) { 750 Visit(node->condition()); 751 Print(" ? "); 752 Visit(node->then_expression()); 753 Print(" : "); 754 Visit(node->else_expression()); 755 } 756 757 758 void PrettyPrinter::VisitLiteral(Literal* node) { 759 PrintLiteral(node->value(), true); 760 } 761 762 763 void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 764 Print(" RegExp("); 765 PrintLiteral(node->pattern(), false); 766 Print(","); 767 if (node->flags() & RegExp::kGlobal) Print("g"); 768 if (node->flags() & RegExp::kIgnoreCase) Print("i"); 769 if (node->flags() & RegExp::kMultiline) Print("m"); 770 if (node->flags() & RegExp::kUnicode) Print("u"); 771 if (node->flags() & RegExp::kSticky) Print("y"); 772 Print(") "); 773 } 774 775 776 void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) { 777 Print("{ "); 778 for (int i = 0; i < node->properties()->length(); i++) { 779 if (i != 0) Print(","); 780 PrintObjectLiteralProperty(node->properties()->at(i)); 781 } 782 Print(" }"); 783 } 784 785 786 void PrettyPrinter::PrintObjectLiteralProperty( 787 ObjectLiteralProperty* property) { 788 // TODO(arv): Better printing of methods etc. 789 Print(" "); 790 Visit(property->key()); 791 Print(": "); 792 Visit(property->value()); 793 } 794 795 796 void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) { 797 Print("[ "); 798 Print(" literal_index = %d", node->literal_index()); 799 for (int i = 0; i < node->values()->length(); i++) { 800 if (i != 0) Print(","); 801 Visit(node->values()->at(i)); 802 } 803 Print(" ]"); 804 } 805 806 807 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { 808 PrintLiteral(node->name(), false); 809 } 810 811 812 void PrettyPrinter::VisitAssignment(Assignment* node) { 813 Visit(node->target()); 814 Print(" %s ", Token::String(node->op())); 815 Visit(node->value()); 816 } 817 818 819 void PrettyPrinter::VisitYield(Yield* node) { 820 Print("yield "); 821 Visit(node->expression()); 822 } 823 824 825 void PrettyPrinter::VisitThrow(Throw* node) { 826 Print("throw "); 827 Visit(node->exception()); 828 } 829 830 831 void PrettyPrinter::VisitProperty(Property* node) { 832 Expression* key = node->key(); 833 Literal* literal = key->AsLiteral(); 834 if (literal != NULL && literal->value()->IsInternalizedString()) { 835 Print("("); 836 Visit(node->obj()); 837 Print(")."); 838 PrintLiteral(literal->value(), false); 839 } else { 840 Visit(node->obj()); 841 Print("["); 842 Visit(key); 843 Print("]"); 844 } 845 } 846 847 848 void PrettyPrinter::VisitCall(Call* node) { 849 Visit(node->expression()); 850 PrintArguments(node->arguments()); 851 } 852 853 854 void PrettyPrinter::VisitCallNew(CallNew* node) { 855 Print("new ("); 856 Visit(node->expression()); 857 Print(")"); 858 PrintArguments(node->arguments()); 859 } 860 861 862 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) { 863 Print("%%%s\n", node->debug_name()); 864 PrintArguments(node->arguments()); 865 } 866 867 868 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) { 869 Token::Value op = node->op(); 870 bool needsSpace = 871 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; 872 Print("(%s%s", Token::String(op), needsSpace ? " " : ""); 873 Visit(node->expression()); 874 Print(")"); 875 } 876 877 878 void PrettyPrinter::VisitCountOperation(CountOperation* node) { 879 Print("("); 880 if (node->is_prefix()) Print("%s", Token::String(node->op())); 881 Visit(node->expression()); 882 if (node->is_postfix()) Print("%s", Token::String(node->op())); 883 Print(")"); 884 } 885 886 887 void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) { 888 Print("("); 889 Visit(node->left()); 890 Print(" %s ", Token::String(node->op())); 891 Visit(node->right()); 892 Print(")"); 893 } 894 895 896 void PrettyPrinter::VisitCompareOperation(CompareOperation* node) { 897 Print("("); 898 Visit(node->left()); 899 Print(" %s ", Token::String(node->op())); 900 Visit(node->right()); 901 Print(")"); 902 } 903 904 905 void PrettyPrinter::VisitSpread(Spread* node) { 906 Print("(..."); 907 Visit(node->expression()); 908 Print(")"); 909 } 910 911 912 void PrettyPrinter::VisitEmptyParentheses(EmptyParentheses* node) { 913 Print("()"); 914 } 915 916 917 void PrettyPrinter::VisitThisFunction(ThisFunction* node) { 918 Print("<this-function>"); 919 } 920 921 922 void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) { 923 Print("<super-property-reference>"); 924 } 925 926 927 void PrettyPrinter::VisitSuperCallReference(SuperCallReference* node) { 928 Print("<super-call-reference>"); 929 } 930 931 932 void PrettyPrinter::VisitRewritableAssignmentExpression( 933 RewritableAssignmentExpression* node) { 934 Visit(node->expression()); 935 } 936 937 938 const char* PrettyPrinter::Print(AstNode* node) { 939 Init(); 940 Visit(node); 941 return output_; 942 } 943 944 945 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) { 946 Init(); 947 ExpressionStatement* statement = 948 program->body()->at(0)->AsExpressionStatement(); 949 Visit(statement->expression()); 950 return output_; 951 } 952 953 954 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) { 955 Init(); 956 PrintStatements(program->body()); 957 Print("\n"); 958 return output_; 959 } 960 961 962 void PrettyPrinter::PrintOut(Isolate* isolate, AstNode* node) { 963 PrettyPrinter printer(isolate); 964 PrintF("%s\n", printer.Print(node)); 965 } 966 967 968 void PrettyPrinter::Init() { 969 if (size_ == 0) { 970 DCHECK(output_ == NULL); 971 const int initial_size = 256; 972 output_ = NewArray<char>(initial_size); 973 size_ = initial_size; 974 } 975 output_[0] = '\0'; 976 pos_ = 0; 977 } 978 979 980 void PrettyPrinter::Print(const char* format, ...) { 981 for (;;) { 982 va_list arguments; 983 va_start(arguments, format); 984 int n = VSNPrintF(Vector<char>(output_, size_) + pos_, 985 format, 986 arguments); 987 va_end(arguments); 988 989 if (n >= 0) { 990 // there was enough space - we are done 991 pos_ += n; 992 return; 993 } else { 994 // there was not enough space - allocate more and try again 995 const int slack = 32; 996 int new_size = size_ + (size_ >> 1) + slack; 997 char* new_output = NewArray<char>(new_size); 998 MemCopy(new_output, output_, pos_); 999 DeleteArray(output_); 1000 output_ = new_output; 1001 size_ = new_size; 1002 } 1003 } 1004 } 1005 1006 1007 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) { 1008 if (statements == NULL) return; 1009 for (int i = 0; i < statements->length(); i++) { 1010 if (i != 0) Print(" "); 1011 Visit(statements->at(i)); 1012 } 1013 } 1014 1015 1016 void PrettyPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) { 1017 if (labels != NULL) { 1018 for (int i = 0; i < labels->length(); i++) { 1019 PrintLiteral(labels->at(i), false); 1020 Print(": "); 1021 } 1022 } 1023 } 1024 1025 1026 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 1027 Print("("); 1028 for (int i = 0; i < arguments->length(); i++) { 1029 if (i != 0) Print(", "); 1030 Visit(arguments->at(i)); 1031 } 1032 Print(")"); 1033 } 1034 1035 1036 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) { 1037 Object* object = *value; 1038 if (object->IsString()) { 1039 String* string = String::cast(object); 1040 if (quote) Print("\""); 1041 for (int i = 0; i < string->length(); i++) { 1042 Print("%c", string->Get(i)); 1043 } 1044 if (quote) Print("\""); 1045 } else if (object->IsNull()) { 1046 Print("null"); 1047 } else if (object->IsTrue()) { 1048 Print("true"); 1049 } else if (object->IsFalse()) { 1050 Print("false"); 1051 } else if (object->IsUndefined()) { 1052 Print("undefined"); 1053 } else if (object->IsNumber()) { 1054 Print("%g", object->Number()); 1055 } else if (object->IsJSObject()) { 1056 // regular expression 1057 if (object->IsJSFunction()) { 1058 Print("JS-Function"); 1059 } else if (object->IsJSArray()) { 1060 Print("JS-array[%u]", JSArray::cast(object)->length()); 1061 } else if (object->IsJSObject()) { 1062 Print("JS-Object"); 1063 } else { 1064 Print("?UNKNOWN?"); 1065 } 1066 } else if (object->IsFixedArray()) { 1067 Print("FixedArray"); 1068 } else { 1069 Print("<unknown literal %p>", object); 1070 } 1071 } 1072 1073 1074 void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) { 1075 PrintLiteral(value->string(), quote); 1076 } 1077 1078 1079 void PrettyPrinter::PrintParameters(Scope* scope) { 1080 Print("("); 1081 for (int i = 0; i < scope->num_parameters(); i++) { 1082 if (i > 0) Print(", "); 1083 PrintLiteral(scope->parameter(i)->name(), false); 1084 } 1085 Print(")"); 1086 } 1087 1088 1089 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { 1090 for (int i = 0; i < declarations->length(); i++) { 1091 if (i > 0) Print(" "); 1092 Visit(declarations->at(i)); 1093 } 1094 } 1095 1096 1097 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) { 1098 Print("function "); 1099 PrintLiteral(function->name(), false); 1100 PrintParameters(function->scope()); 1101 Print(" { "); 1102 PrintDeclarations(function->scope()->declarations()); 1103 PrintStatements(function->body()); 1104 Print(" }"); 1105 } 1106 1107 1108 //----------------------------------------------------------------------------- 1109 1110 class IndentedScope BASE_EMBEDDED { 1111 public: 1112 IndentedScope(AstPrinter* printer, const char* txt) 1113 : ast_printer_(printer) { 1114 ast_printer_->PrintIndented(txt); 1115 ast_printer_->Print("\n"); 1116 ast_printer_->inc_indent(); 1117 } 1118 1119 IndentedScope(AstPrinter* printer, const char* txt, int pos) 1120 : ast_printer_(printer) { 1121 ast_printer_->PrintIndented(txt); 1122 ast_printer_->Print(" at %d\n", pos); 1123 ast_printer_->inc_indent(); 1124 } 1125 1126 virtual ~IndentedScope() { 1127 ast_printer_->dec_indent(); 1128 } 1129 1130 private: 1131 AstPrinter* ast_printer_; 1132 }; 1133 1134 1135 //----------------------------------------------------------------------------- 1136 1137 1138 AstPrinter::AstPrinter(Isolate* isolate) : PrettyPrinter(isolate), indent_(0) {} 1139 1140 1141 AstPrinter::~AstPrinter() { 1142 DCHECK(indent_ == 0); 1143 } 1144 1145 1146 void AstPrinter::PrintIndented(const char* txt) { 1147 for (int i = 0; i < indent_; i++) { 1148 Print(". "); 1149 } 1150 Print(txt); 1151 } 1152 1153 1154 void AstPrinter::PrintLiteralIndented(const char* info, 1155 Handle<Object> value, 1156 bool quote) { 1157 PrintIndented(info); 1158 Print(" "); 1159 PrintLiteral(value, quote); 1160 Print("\n"); 1161 } 1162 1163 1164 void AstPrinter::PrintLiteralWithModeIndented(const char* info, 1165 Variable* var, 1166 Handle<Object> value) { 1167 if (var == NULL) { 1168 PrintLiteralIndented(info, value, true); 1169 } else { 1170 EmbeddedVector<char, 256> buf; 1171 int pos = SNPrintF(buf, "%s (mode = %s", info, 1172 Variable::Mode2String(var->mode())); 1173 SNPrintF(buf + pos, ")"); 1174 PrintLiteralIndented(buf.start(), value, true); 1175 } 1176 } 1177 1178 1179 void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) { 1180 if (labels == NULL || labels->length() == 0) return; 1181 PrintIndented("LABELS "); 1182 PrintLabels(labels); 1183 Print("\n"); 1184 } 1185 1186 1187 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { 1188 IndentedScope indent(this, s, node->position()); 1189 Visit(node); 1190 } 1191 1192 1193 const char* AstPrinter::PrintProgram(FunctionLiteral* program) { 1194 Init(); 1195 { IndentedScope indent(this, "FUNC", program->position()); 1196 PrintLiteralIndented("NAME", program->name(), true); 1197 PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true); 1198 PrintParameters(program->scope()); 1199 PrintDeclarations(program->scope()->declarations()); 1200 PrintStatements(program->body()); 1201 } 1202 return Output(); 1203 } 1204 1205 1206 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { 1207 if (declarations->length() > 0) { 1208 IndentedScope indent(this, "DECLS"); 1209 for (int i = 0; i < declarations->length(); i++) { 1210 Visit(declarations->at(i)); 1211 } 1212 } 1213 } 1214 1215 1216 void AstPrinter::PrintParameters(Scope* scope) { 1217 if (scope->num_parameters() > 0) { 1218 IndentedScope indent(this, "PARAMS"); 1219 for (int i = 0; i < scope->num_parameters(); i++) { 1220 PrintLiteralWithModeIndented("VAR", scope->parameter(i), 1221 scope->parameter(i)->name()); 1222 } 1223 } 1224 } 1225 1226 1227 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) { 1228 for (int i = 0; i < statements->length(); i++) { 1229 Visit(statements->at(i)); 1230 } 1231 } 1232 1233 1234 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 1235 for (int i = 0; i < arguments->length(); i++) { 1236 Visit(arguments->at(i)); 1237 } 1238 } 1239 1240 1241 void AstPrinter::VisitBlock(Block* node) { 1242 const char* block_txt = 1243 node->ignore_completion_value() ? "BLOCK NOCOMPLETIONS" : "BLOCK"; 1244 IndentedScope indent(this, block_txt, node->position()); 1245 PrintStatements(node->statements()); 1246 } 1247 1248 1249 // TODO(svenpanne) Start with IndentedScope. 1250 void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 1251 PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()), 1252 node->proxy()->var(), 1253 node->proxy()->name()); 1254 } 1255 1256 1257 // TODO(svenpanne) Start with IndentedScope. 1258 void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { 1259 PrintIndented("FUNCTION "); 1260 PrintLiteral(node->proxy()->name(), true); 1261 Print(" = function "); 1262 PrintLiteral(node->fun()->name(), false); 1263 Print("\n"); 1264 } 1265 1266 1267 void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) { 1268 IndentedScope indent(this, "IMPORT", node->position()); 1269 PrintLiteralIndented("NAME", node->proxy()->name(), true); 1270 PrintLiteralIndented("FROM", node->module_specifier()->string(), true); 1271 } 1272 1273 1274 void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) { 1275 IndentedScope indent(this, "EXPORT", node->position()); 1276 PrintLiteral(node->proxy()->name(), true); 1277 } 1278 1279 1280 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { 1281 IndentedScope indent(this, "EXPRESSION STATEMENT", node->position()); 1282 Visit(node->expression()); 1283 } 1284 1285 1286 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { 1287 IndentedScope indent(this, "EMPTY", node->position()); 1288 } 1289 1290 1291 void AstPrinter::VisitSloppyBlockFunctionStatement( 1292 SloppyBlockFunctionStatement* node) { 1293 Visit(node->statement()); 1294 } 1295 1296 1297 void AstPrinter::VisitIfStatement(IfStatement* node) { 1298 IndentedScope indent(this, "IF", node->position()); 1299 PrintIndentedVisit("CONDITION", node->condition()); 1300 PrintIndentedVisit("THEN", node->then_statement()); 1301 if (node->HasElseStatement()) { 1302 PrintIndentedVisit("ELSE", node->else_statement()); 1303 } 1304 } 1305 1306 1307 void AstPrinter::VisitContinueStatement(ContinueStatement* node) { 1308 IndentedScope indent(this, "CONTINUE", node->position()); 1309 PrintLabelsIndented(node->target()->labels()); 1310 } 1311 1312 1313 void AstPrinter::VisitBreakStatement(BreakStatement* node) { 1314 IndentedScope indent(this, "BREAK", node->position()); 1315 PrintLabelsIndented(node->target()->labels()); 1316 } 1317 1318 1319 void AstPrinter::VisitReturnStatement(ReturnStatement* node) { 1320 IndentedScope indent(this, "RETURN", node->position()); 1321 Visit(node->expression()); 1322 } 1323 1324 1325 void AstPrinter::VisitWithStatement(WithStatement* node) { 1326 IndentedScope indent(this, "WITH", node->position()); 1327 PrintIndentedVisit("OBJECT", node->expression()); 1328 PrintIndentedVisit("BODY", node->statement()); 1329 } 1330 1331 1332 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) { 1333 IndentedScope indent(this, "SWITCH", node->position()); 1334 PrintLabelsIndented(node->labels()); 1335 PrintIndentedVisit("TAG", node->tag()); 1336 for (int i = 0; i < node->cases()->length(); i++) { 1337 Visit(node->cases()->at(i)); 1338 } 1339 } 1340 1341 1342 void AstPrinter::VisitCaseClause(CaseClause* clause) { 1343 if (clause->is_default()) { 1344 IndentedScope indent(this, "DEFAULT", clause->position()); 1345 PrintStatements(clause->statements()); 1346 } else { 1347 IndentedScope indent(this, "CASE", clause->position()); 1348 Visit(clause->label()); 1349 PrintStatements(clause->statements()); 1350 } 1351 } 1352 1353 1354 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 1355 IndentedScope indent(this, "DO", node->position()); 1356 PrintLabelsIndented(node->labels()); 1357 PrintIndentedVisit("BODY", node->body()); 1358 PrintIndentedVisit("COND", node->cond()); 1359 } 1360 1361 1362 void AstPrinter::VisitWhileStatement(WhileStatement* node) { 1363 IndentedScope indent(this, "WHILE", node->position()); 1364 PrintLabelsIndented(node->labels()); 1365 PrintIndentedVisit("COND", node->cond()); 1366 PrintIndentedVisit("BODY", node->body()); 1367 } 1368 1369 1370 void AstPrinter::VisitForStatement(ForStatement* node) { 1371 IndentedScope indent(this, "FOR", node->position()); 1372 PrintLabelsIndented(node->labels()); 1373 if (node->init()) PrintIndentedVisit("INIT", node->init()); 1374 if (node->cond()) PrintIndentedVisit("COND", node->cond()); 1375 PrintIndentedVisit("BODY", node->body()); 1376 if (node->next()) PrintIndentedVisit("NEXT", node->next()); 1377 } 1378 1379 1380 void AstPrinter::VisitForInStatement(ForInStatement* node) { 1381 IndentedScope indent(this, "FOR IN", node->position()); 1382 PrintIndentedVisit("FOR", node->each()); 1383 PrintIndentedVisit("IN", node->enumerable()); 1384 PrintIndentedVisit("BODY", node->body()); 1385 } 1386 1387 1388 void AstPrinter::VisitForOfStatement(ForOfStatement* node) { 1389 IndentedScope indent(this, "FOR OF", node->position()); 1390 PrintIndentedVisit("FOR", node->each()); 1391 PrintIndentedVisit("OF", node->iterable()); 1392 PrintIndentedVisit("BODY", node->body()); 1393 } 1394 1395 1396 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 1397 IndentedScope indent(this, "TRY CATCH", node->position()); 1398 PrintIndentedVisit("TRY", node->try_block()); 1399 PrintLiteralWithModeIndented("CATCHVAR", 1400 node->variable(), 1401 node->variable()->name()); 1402 PrintIndentedVisit("CATCH", node->catch_block()); 1403 } 1404 1405 1406 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 1407 IndentedScope indent(this, "TRY FINALLY", node->position()); 1408 PrintIndentedVisit("TRY", node->try_block()); 1409 PrintIndentedVisit("FINALLY", node->finally_block()); 1410 } 1411 1412 1413 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 1414 IndentedScope indent(this, "DEBUGGER", node->position()); 1415 } 1416 1417 1418 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 1419 IndentedScope indent(this, "FUNC LITERAL", node->position()); 1420 PrintLiteralIndented("NAME", node->name(), false); 1421 PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false); 1422 PrintParameters(node->scope()); 1423 // We don't want to see the function literal in this case: it 1424 // will be printed via PrintProgram when the code for it is 1425 // generated. 1426 // PrintStatements(node->body()); 1427 } 1428 1429 1430 void AstPrinter::VisitClassLiteral(ClassLiteral* node) { 1431 IndentedScope indent(this, "CLASS LITERAL", node->position()); 1432 if (node->raw_name() != nullptr) { 1433 PrintLiteralIndented("NAME", node->name(), false); 1434 } 1435 if (node->extends() != nullptr) { 1436 PrintIndentedVisit("EXTENDS", node->extends()); 1437 } 1438 PrintProperties(node->properties()); 1439 } 1440 1441 1442 void AstPrinter::PrintProperties( 1443 ZoneList<ObjectLiteral::Property*>* properties) { 1444 for (int i = 0; i < properties->length(); i++) { 1445 ObjectLiteral::Property* property = properties->at(i); 1446 const char* prop_kind = nullptr; 1447 switch (property->kind()) { 1448 case ObjectLiteral::Property::CONSTANT: 1449 prop_kind = "CONSTANT"; 1450 break; 1451 case ObjectLiteral::Property::COMPUTED: 1452 prop_kind = "COMPUTED"; 1453 break; 1454 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1455 prop_kind = "MATERIALIZED_LITERAL"; 1456 break; 1457 case ObjectLiteral::Property::PROTOTYPE: 1458 prop_kind = "PROTOTYPE"; 1459 break; 1460 case ObjectLiteral::Property::GETTER: 1461 prop_kind = "GETTER"; 1462 break; 1463 case ObjectLiteral::Property::SETTER: 1464 prop_kind = "SETTER"; 1465 break; 1466 } 1467 EmbeddedVector<char, 128> buf; 1468 SNPrintF(buf, "PROPERTY%s - %s", property->is_static() ? " - STATIC" : "", 1469 prop_kind); 1470 IndentedScope prop(this, buf.start()); 1471 PrintIndentedVisit("KEY", properties->at(i)->key()); 1472 PrintIndentedVisit("VALUE", properties->at(i)->value()); 1473 } 1474 } 1475 1476 1477 void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { 1478 IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position()); 1479 PrintLiteralIndented("NAME", node->name(), false); 1480 } 1481 1482 1483 void AstPrinter::VisitDoExpression(DoExpression* node) { 1484 IndentedScope indent(this, "DO EXPRESSION", node->position()); 1485 PrintStatements(node->block()->statements()); 1486 } 1487 1488 1489 void AstPrinter::VisitConditional(Conditional* node) { 1490 IndentedScope indent(this, "CONDITIONAL", node->position()); 1491 PrintIndentedVisit("CONDITION", node->condition()); 1492 PrintIndentedVisit("THEN", node->then_expression()); 1493 PrintIndentedVisit("ELSE", node->else_expression()); 1494 } 1495 1496 1497 // TODO(svenpanne) Start with IndentedScope. 1498 void AstPrinter::VisitLiteral(Literal* node) { 1499 PrintLiteralIndented("LITERAL", node->value(), true); 1500 } 1501 1502 1503 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { 1504 IndentedScope indent(this, "REGEXP LITERAL", node->position()); 1505 EmbeddedVector<char, 128> buf; 1506 SNPrintF(buf, "literal_index = %d\n", node->literal_index()); 1507 PrintIndented(buf.start()); 1508 PrintLiteralIndented("PATTERN", node->pattern(), false); 1509 int i = 0; 1510 if (node->flags() & RegExp::kGlobal) buf[i++] = 'g'; 1511 if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i'; 1512 if (node->flags() & RegExp::kMultiline) buf[i++] = 'm'; 1513 if (node->flags() & RegExp::kUnicode) buf[i++] = 'u'; 1514 if (node->flags() & RegExp::kSticky) buf[i++] = 'y'; 1515 buf[i] = '\0'; 1516 PrintIndented("FLAGS "); 1517 Print(buf.start()); 1518 Print("\n"); 1519 } 1520 1521 1522 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) { 1523 IndentedScope indent(this, "OBJ LITERAL", node->position()); 1524 EmbeddedVector<char, 128> buf; 1525 SNPrintF(buf, "literal_index = %d\n", node->literal_index()); 1526 PrintIndented(buf.start()); 1527 PrintProperties(node->properties()); 1528 } 1529 1530 1531 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) { 1532 IndentedScope indent(this, "ARRAY LITERAL", node->position()); 1533 1534 EmbeddedVector<char, 128> buf; 1535 SNPrintF(buf, "literal_index = %d\n", node->literal_index()); 1536 PrintIndented(buf.start()); 1537 if (node->values()->length() > 0) { 1538 IndentedScope indent(this, "VALUES", node->position()); 1539 for (int i = 0; i < node->values()->length(); i++) { 1540 Visit(node->values()->at(i)); 1541 } 1542 } 1543 } 1544 1545 1546 void AstPrinter::VisitVariableProxy(VariableProxy* node) { 1547 Variable* var = node->var(); 1548 EmbeddedVector<char, 128> buf; 1549 int pos = 1550 FormatSlotNode(&buf, node, "VAR PROXY", node->VariableFeedbackSlot()); 1551 1552 switch (var->location()) { 1553 case VariableLocation::UNALLOCATED: 1554 break; 1555 case VariableLocation::PARAMETER: 1556 SNPrintF(buf + pos, " parameter[%d]", var->index()); 1557 break; 1558 case VariableLocation::LOCAL: 1559 SNPrintF(buf + pos, " local[%d]", var->index()); 1560 break; 1561 case VariableLocation::CONTEXT: 1562 SNPrintF(buf + pos, " context[%d]", var->index()); 1563 break; 1564 case VariableLocation::GLOBAL: 1565 SNPrintF(buf + pos, " global[%d]", var->index()); 1566 break; 1567 case VariableLocation::LOOKUP: 1568 SNPrintF(buf + pos, " lookup"); 1569 break; 1570 } 1571 PrintLiteralWithModeIndented(buf.start(), var, node->name()); 1572 } 1573 1574 1575 void AstPrinter::VisitAssignment(Assignment* node) { 1576 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1577 Visit(node->target()); 1578 Visit(node->value()); 1579 } 1580 1581 1582 void AstPrinter::VisitYield(Yield* node) { 1583 IndentedScope indent(this, "YIELD", node->position()); 1584 Visit(node->expression()); 1585 } 1586 1587 1588 void AstPrinter::VisitThrow(Throw* node) { 1589 IndentedScope indent(this, "THROW", node->position()); 1590 Visit(node->exception()); 1591 } 1592 1593 1594 void AstPrinter::VisitProperty(Property* node) { 1595 EmbeddedVector<char, 128> buf; 1596 FormatSlotNode(&buf, node, "PROPERTY", node->PropertyFeedbackSlot()); 1597 IndentedScope indent(this, buf.start(), node->position()); 1598 1599 Visit(node->obj()); 1600 Literal* literal = node->key()->AsLiteral(); 1601 if (literal != NULL && literal->value()->IsInternalizedString()) { 1602 PrintLiteralIndented("NAME", literal->value(), false); 1603 } else { 1604 PrintIndentedVisit("KEY", node->key()); 1605 } 1606 } 1607 1608 1609 void AstPrinter::VisitCall(Call* node) { 1610 EmbeddedVector<char, 128> buf; 1611 FormatSlotNode(&buf, node, "CALL", node->CallFeedbackICSlot()); 1612 IndentedScope indent(this, buf.start()); 1613 1614 Visit(node->expression()); 1615 PrintArguments(node->arguments()); 1616 } 1617 1618 1619 void AstPrinter::VisitCallNew(CallNew* node) { 1620 IndentedScope indent(this, "CALL NEW", node->position()); 1621 Visit(node->expression()); 1622 PrintArguments(node->arguments()); 1623 } 1624 1625 1626 void AstPrinter::VisitCallRuntime(CallRuntime* node) { 1627 EmbeddedVector<char, 128> buf; 1628 SNPrintF(buf, "CALL RUNTIME %s", node->debug_name()); 1629 IndentedScope indent(this, buf.start(), node->position()); 1630 PrintArguments(node->arguments()); 1631 } 1632 1633 1634 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { 1635 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1636 Visit(node->expression()); 1637 } 1638 1639 1640 void AstPrinter::VisitCountOperation(CountOperation* node) { 1641 EmbeddedVector<char, 128> buf; 1642 SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"), 1643 Token::Name(node->op())); 1644 IndentedScope indent(this, buf.start(), node->position()); 1645 Visit(node->expression()); 1646 } 1647 1648 1649 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) { 1650 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1651 Visit(node->left()); 1652 Visit(node->right()); 1653 } 1654 1655 1656 void AstPrinter::VisitCompareOperation(CompareOperation* node) { 1657 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1658 Visit(node->left()); 1659 Visit(node->right()); 1660 } 1661 1662 1663 void AstPrinter::VisitSpread(Spread* node) { 1664 IndentedScope indent(this, "...", node->position()); 1665 Visit(node->expression()); 1666 } 1667 1668 1669 void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) { 1670 IndentedScope indent(this, "()", node->position()); 1671 } 1672 1673 1674 void AstPrinter::VisitThisFunction(ThisFunction* node) { 1675 IndentedScope indent(this, "THIS-FUNCTION", node->position()); 1676 } 1677 1678 1679 void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) { 1680 IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position()); 1681 } 1682 1683 1684 void AstPrinter::VisitSuperCallReference(SuperCallReference* node) { 1685 IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position()); 1686 } 1687 1688 1689 void AstPrinter::VisitRewritableAssignmentExpression( 1690 RewritableAssignmentExpression* node) { 1691 Visit(node->expression()); 1692 } 1693 1694 1695 #endif // DEBUG 1696 1697 } // namespace internal 1698 } // namespace v8 1699