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