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 13namespace v8 { 14namespace internal { 15 16CallPrinter::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 28CallPrinter::~CallPrinter() { DeleteArray(output_); } 29 30 31const char* CallPrinter::Print(FunctionLiteral* program, int position) { 32 Init(); 33 position_ = position; 34 Find(program); 35 return output_; 36} 37 38 39void 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 54void 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 66void 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 92void CallPrinter::VisitBlock(Block* node) { 93 FindStatements(node->statements()); 94} 95 96 97void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {} 98 99 100void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {} 101 102 103void CallPrinter::VisitImportDeclaration(ImportDeclaration* node) { 104} 105 106 107void CallPrinter::VisitExportDeclaration(ExportDeclaration* node) {} 108 109 110void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) { 111 Find(node->expression()); 112} 113 114 115void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {} 116 117 118void CallPrinter::VisitSloppyBlockFunctionStatement( 119 SloppyBlockFunctionStatement* node) { 120 Find(node->statement()); 121} 122 123 124void 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 133void CallPrinter::VisitContinueStatement(ContinueStatement* node) {} 134 135 136void CallPrinter::VisitBreakStatement(BreakStatement* node) {} 137 138 139void CallPrinter::VisitReturnStatement(ReturnStatement* node) { 140 Find(node->expression()); 141} 142 143 144void CallPrinter::VisitWithStatement(WithStatement* node) { 145 Find(node->expression()); 146 Find(node->statement()); 147} 148 149 150void 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 157void CallPrinter::VisitCaseClause(CaseClause* clause) { 158 if (!clause->is_default()) { 159 Find(clause->label()); 160 } 161 FindStatements(clause->statements()); 162} 163 164 165void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) { 166 Find(node->body()); 167 Find(node->cond()); 168} 169 170 171void CallPrinter::VisitWhileStatement(WhileStatement* node) { 172 Find(node->cond()); 173 Find(node->body()); 174} 175 176 177void 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 187void CallPrinter::VisitForInStatement(ForInStatement* node) { 188 Find(node->each()); 189 Find(node->enumerable()); 190 Find(node->body()); 191} 192 193 194void 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 202void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) { 203 Find(node->try_block()); 204 Find(node->catch_block()); 205} 206 207 208void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 209 Find(node->try_block()); 210 Find(node->finally_block()); 211} 212 213 214void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {} 215 216 217void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 218 FindStatements(node->body()); 219} 220 221 222void 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 230void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {} 231 232 233void CallPrinter::VisitDoExpression(DoExpression* node) { Find(node->block()); } 234 235 236void CallPrinter::VisitConditional(Conditional* node) { 237 Find(node->condition()); 238 Find(node->then_expression()); 239 Find(node->else_expression()); 240} 241 242 243void CallPrinter::VisitLiteral(Literal* node) { 244 PrintLiteral(*node->value(), true); 245} 246 247 248void 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 260void 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 267void 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 277void 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 287void CallPrinter::VisitAssignment(Assignment* node) { 288 Find(node->target()); 289 Find(node->value()); 290} 291 292 293void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); } 294 295 296void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); } 297 298 299void 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 315void 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 333void 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 350void CallPrinter::VisitCallRuntime(CallRuntime* node) { 351 FindArguments(node->arguments()); 352} 353 354 355void 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 365void 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 374void 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 383void 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 392void CallPrinter::VisitSpread(Spread* node) { 393 Print("(..."); 394 Find(node->expression(), true); 395 Print(")"); 396} 397 398 399void CallPrinter::VisitEmptyParentheses(EmptyParentheses* node) { 400 UNREACHABLE(); 401} 402 403 404void CallPrinter::VisitThisFunction(ThisFunction* node) {} 405 406 407void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {} 408 409 410void CallPrinter::VisitSuperCallReference(SuperCallReference* node) { 411 Print("super"); 412} 413 414 415void CallPrinter::VisitRewritableAssignmentExpression( 416 RewritableAssignmentExpression* node) { 417 Find(node->expression()); 418} 419 420 421void 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 429void 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 437void 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 460void 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. 471static 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 481PrettyPrinter::PrettyPrinter(Isolate* isolate) { 482 output_ = NULL; 483 size_ = 0; 484 pos_ = 0; 485 InitializeAstVisitor(isolate); 486} 487 488 489PrettyPrinter::~PrettyPrinter() { 490 DeleteArray(output_); 491} 492 493 494void 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 502void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) { 503 Print("var "); 504 PrintLiteral(node->proxy()->name(), false); 505 Print(";"); 506} 507 508 509void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { 510 Print("function "); 511 PrintLiteral(node->proxy()->name(), false); 512 Print(" = "); 513 PrintFunctionLiteral(node->fun()); 514 Print(";"); 515} 516 517 518void 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 527void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) { 528 Print("export "); 529 PrintLiteral(node->proxy()->name(), false); 530 Print(";"); 531} 532 533 534void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) { 535 Visit(node->expression()); 536 Print(";"); 537} 538 539 540void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) { 541 Print(";"); 542} 543 544 545void PrettyPrinter::VisitSloppyBlockFunctionStatement( 546 SloppyBlockFunctionStatement* node) { 547 Visit(node->statement()); 548} 549 550 551void 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 563void 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 575void 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 587void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { 588 Print("return "); 589 Visit(node->expression()); 590 Print(";"); 591} 592 593 594void PrettyPrinter::VisitWithStatement(WithStatement* node) { 595 Print("with ("); 596 Visit(node->expression()); 597 Print(") "); 598 Visit(node->statement()); 599} 600 601 602void 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 614void 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 628void 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 638void PrettyPrinter::VisitWhileStatement(WhileStatement* node) { 639 PrintLabels(node->labels()); 640 Print("while ("); 641 Visit(node->cond()); 642 Print(") "); 643 Visit(node->body()); 644} 645 646 647void 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 667void 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 678void 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 689void 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 700void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { 701 Print("try "); 702 Visit(node->try_block()); 703 Print(" finally "); 704 Visit(node->finally_block()); 705} 706 707 708void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 709 Print("debugger "); 710} 711 712 713void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { 714 Print("("); 715 PrintFunctionLiteral(node); 716 Print(")"); 717} 718 719 720void 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 735void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { 736 Print("("); 737 PrintLiteral(node->name(), false); 738 Print(")"); 739} 740 741 742void PrettyPrinter::VisitDoExpression(DoExpression* node) { 743 Print("(do {"); 744 PrintStatements(node->block()->statements()); 745 Print("})"); 746} 747 748 749void 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 758void PrettyPrinter::VisitLiteral(Literal* node) { 759 PrintLiteral(node->value(), true); 760} 761 762 763void 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 776void 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 786void 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 796void 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 807void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { 808 PrintLiteral(node->name(), false); 809} 810 811 812void PrettyPrinter::VisitAssignment(Assignment* node) { 813 Visit(node->target()); 814 Print(" %s ", Token::String(node->op())); 815 Visit(node->value()); 816} 817 818 819void PrettyPrinter::VisitYield(Yield* node) { 820 Print("yield "); 821 Visit(node->expression()); 822} 823 824 825void PrettyPrinter::VisitThrow(Throw* node) { 826 Print("throw "); 827 Visit(node->exception()); 828} 829 830 831void 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 848void PrettyPrinter::VisitCall(Call* node) { 849 Visit(node->expression()); 850 PrintArguments(node->arguments()); 851} 852 853 854void PrettyPrinter::VisitCallNew(CallNew* node) { 855 Print("new ("); 856 Visit(node->expression()); 857 Print(")"); 858 PrintArguments(node->arguments()); 859} 860 861 862void PrettyPrinter::VisitCallRuntime(CallRuntime* node) { 863 Print("%%%s\n", node->debug_name()); 864 PrintArguments(node->arguments()); 865} 866 867 868void 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 878void 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 887void 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 896void 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 905void PrettyPrinter::VisitSpread(Spread* node) { 906 Print("(..."); 907 Visit(node->expression()); 908 Print(")"); 909} 910 911 912void PrettyPrinter::VisitEmptyParentheses(EmptyParentheses* node) { 913 Print("()"); 914} 915 916 917void PrettyPrinter::VisitThisFunction(ThisFunction* node) { 918 Print("<this-function>"); 919} 920 921 922void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) { 923 Print("<super-property-reference>"); 924} 925 926 927void PrettyPrinter::VisitSuperCallReference(SuperCallReference* node) { 928 Print("<super-call-reference>"); 929} 930 931 932void PrettyPrinter::VisitRewritableAssignmentExpression( 933 RewritableAssignmentExpression* node) { 934 Visit(node->expression()); 935} 936 937 938const char* PrettyPrinter::Print(AstNode* node) { 939 Init(); 940 Visit(node); 941 return output_; 942} 943 944 945const 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 954const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) { 955 Init(); 956 PrintStatements(program->body()); 957 Print("\n"); 958 return output_; 959} 960 961 962void PrettyPrinter::PrintOut(Isolate* isolate, AstNode* node) { 963 PrettyPrinter printer(isolate); 964 PrintF("%s\n", printer.Print(node)); 965} 966 967 968void 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 980void 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 1007void 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 1016void 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 1026void 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 1036void 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 1074void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) { 1075 PrintLiteral(value->string(), quote); 1076} 1077 1078 1079void 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 1089void 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 1097void 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 1110class 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 1138AstPrinter::AstPrinter(Isolate* isolate) : PrettyPrinter(isolate), indent_(0) {} 1139 1140 1141AstPrinter::~AstPrinter() { 1142 DCHECK(indent_ == 0); 1143} 1144 1145 1146void AstPrinter::PrintIndented(const char* txt) { 1147 for (int i = 0; i < indent_; i++) { 1148 Print(". "); 1149 } 1150 Print(txt); 1151} 1152 1153 1154void 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 1164void 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 1179void 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 1187void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { 1188 IndentedScope indent(this, s, node->position()); 1189 Visit(node); 1190} 1191 1192 1193const 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 1206void 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 1216void 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 1227void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) { 1228 for (int i = 0; i < statements->length(); i++) { 1229 Visit(statements->at(i)); 1230 } 1231} 1232 1233 1234void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) { 1235 for (int i = 0; i < arguments->length(); i++) { 1236 Visit(arguments->at(i)); 1237 } 1238} 1239 1240 1241void 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. 1250void 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. 1258void 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 1267void 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 1274void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) { 1275 IndentedScope indent(this, "EXPORT", node->position()); 1276 PrintLiteral(node->proxy()->name(), true); 1277} 1278 1279 1280void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { 1281 IndentedScope indent(this, "EXPRESSION STATEMENT", node->position()); 1282 Visit(node->expression()); 1283} 1284 1285 1286void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { 1287 IndentedScope indent(this, "EMPTY", node->position()); 1288} 1289 1290 1291void AstPrinter::VisitSloppyBlockFunctionStatement( 1292 SloppyBlockFunctionStatement* node) { 1293 Visit(node->statement()); 1294} 1295 1296 1297void 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 1307void AstPrinter::VisitContinueStatement(ContinueStatement* node) { 1308 IndentedScope indent(this, "CONTINUE", node->position()); 1309 PrintLabelsIndented(node->target()->labels()); 1310} 1311 1312 1313void AstPrinter::VisitBreakStatement(BreakStatement* node) { 1314 IndentedScope indent(this, "BREAK", node->position()); 1315 PrintLabelsIndented(node->target()->labels()); 1316} 1317 1318 1319void AstPrinter::VisitReturnStatement(ReturnStatement* node) { 1320 IndentedScope indent(this, "RETURN", node->position()); 1321 Visit(node->expression()); 1322} 1323 1324 1325void AstPrinter::VisitWithStatement(WithStatement* node) { 1326 IndentedScope indent(this, "WITH", node->position()); 1327 PrintIndentedVisit("OBJECT", node->expression()); 1328 PrintIndentedVisit("BODY", node->statement()); 1329} 1330 1331 1332void 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 1342void 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 1354void 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 1362void 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 1370void 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 1380void 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 1388void 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 1396void 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 1406void 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 1413void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { 1414 IndentedScope indent(this, "DEBUGGER", node->position()); 1415} 1416 1417 1418void 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 1430void 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 1442void 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 1477void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { 1478 IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position()); 1479 PrintLiteralIndented("NAME", node->name(), false); 1480} 1481 1482 1483void AstPrinter::VisitDoExpression(DoExpression* node) { 1484 IndentedScope indent(this, "DO EXPRESSION", node->position()); 1485 PrintStatements(node->block()->statements()); 1486} 1487 1488 1489void 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. 1498void AstPrinter::VisitLiteral(Literal* node) { 1499 PrintLiteralIndented("LITERAL", node->value(), true); 1500} 1501 1502 1503void 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 1522void 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 1531void 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 1546void 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 1575void 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 1582void AstPrinter::VisitYield(Yield* node) { 1583 IndentedScope indent(this, "YIELD", node->position()); 1584 Visit(node->expression()); 1585} 1586 1587 1588void AstPrinter::VisitThrow(Throw* node) { 1589 IndentedScope indent(this, "THROW", node->position()); 1590 Visit(node->exception()); 1591} 1592 1593 1594void 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 1609void 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 1619void AstPrinter::VisitCallNew(CallNew* node) { 1620 IndentedScope indent(this, "CALL NEW", node->position()); 1621 Visit(node->expression()); 1622 PrintArguments(node->arguments()); 1623} 1624 1625 1626void 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 1634void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { 1635 IndentedScope indent(this, Token::Name(node->op()), node->position()); 1636 Visit(node->expression()); 1637} 1638 1639 1640void 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 1649void 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 1656void 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 1663void AstPrinter::VisitSpread(Spread* node) { 1664 IndentedScope indent(this, "...", node->position()); 1665 Visit(node->expression()); 1666} 1667 1668 1669void AstPrinter::VisitEmptyParentheses(EmptyParentheses* node) { 1670 IndentedScope indent(this, "()", node->position()); 1671} 1672 1673 1674void AstPrinter::VisitThisFunction(ThisFunction* node) { 1675 IndentedScope indent(this, "THIS-FUNCTION", node->position()); 1676} 1677 1678 1679void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) { 1680 IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE", node->position()); 1681} 1682 1683 1684void AstPrinter::VisitSuperCallReference(SuperCallReference* node) { 1685 IndentedScope indent(this, "SUPER-CALL-REFERENCE", node->position()); 1686} 1687 1688 1689void AstPrinter::VisitRewritableAssignmentExpression( 1690 RewritableAssignmentExpression* node) { 1691 Visit(node->expression()); 1692} 1693 1694 1695#endif // DEBUG 1696 1697} // namespace internal 1698} // namespace v8 1699