• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PrettyPrinter()41 PrettyPrinter::PrettyPrinter() {
42   output_ = NULL;
43   size_ = 0;
44   pos_ = 0;
45 }
46 
47 
~PrettyPrinter()48 PrettyPrinter::~PrettyPrinter() {
49   DeleteArray(output_);
50 }
51 
52 
VisitBlock(Block * node)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 
VisitDeclaration(Declaration * node)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 
VisitExpressionStatement(ExpressionStatement * node)72 void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
73   Visit(node->expression());
74   Print(";");
75 }
76 
77 
VisitEmptyStatement(EmptyStatement * node)78 void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
79   Print(";");
80 }
81 
82 
VisitIfStatement(IfStatement * node)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 
VisitContinueStatement(ContinueStatement * node)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 
VisitBreakStatement(BreakStatement * node)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 
VisitReturnStatement(ReturnStatement * node)119 void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
120   Print("return ");
121   Visit(node->expression());
122   Print(";");
123 }
124 
125 
VisitWithEnterStatement(WithEnterStatement * node)126 void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
127   Print("<enter with> (");
128   Visit(node->expression());
129   Print(") ");
130 }
131 
132 
VisitWithExitStatement(WithExitStatement * node)133 void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) {
134   Print("<exit with>");
135 }
136 
137 
VisitSwitchStatement(SwitchStatement * node)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 
VisitDoWhileStatement(DoWhileStatement * node)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 
VisitWhileStatement(WhileStatement * node)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 
VisitForStatement(ForStatement * node)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 
VisitForInStatement(ForInStatement * node)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 
VisitTryCatchStatement(TryCatchStatement * node)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 
VisitTryFinallyStatement(TryFinallyStatement * node)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 
VisitDebuggerStatement(DebuggerStatement * node)218 void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
219   Print("debugger ");
220 }
221 
222 
VisitFunctionLiteral(FunctionLiteral * node)223 void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
224   Print("(");
225   PrintFunctionLiteral(node);
226   Print(")");
227 }
228 
229 
VisitFunctionBoilerplateLiteral(FunctionBoilerplateLiteral * node)230 void PrettyPrinter::VisitFunctionBoilerplateLiteral(
231     FunctionBoilerplateLiteral* node) {
232   Print("(");
233   PrintLiteral(node->boilerplate(), true);
234   Print(")");
235 }
236 
237 
VisitConditional(Conditional * node)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 
VisitLiteral(Literal * node)247 void PrettyPrinter::VisitLiteral(Literal* node) {
248   PrintLiteral(node->handle(), true);
249 }
250 
251 
VisitRegExpLiteral(RegExpLiteral * node)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 
VisitObjectLiteral(ObjectLiteral * node)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 
VisitArrayLiteral(ArrayLiteral * node)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 
VisitCatchExtensionObject(CatchExtensionObject * node)285 void PrettyPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
286   Print("{ ");
287   Visit(node->key());
288   Print(": ");
289   Visit(node->value());
290   Print(" }");
291 }
292 
293 
VisitSlot(Slot * node)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 
VisitVariableProxy(VariableProxy * node)316 void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
317   PrintLiteral(node->name(), false);
318 }
319 
320 
VisitAssignment(Assignment * node)321 void PrettyPrinter::VisitAssignment(Assignment* node) {
322   Visit(node->target());
323   Print(" %s ", Token::String(node->op()));
324   Visit(node->value());
325 }
326 
327 
VisitThrow(Throw * node)328 void PrettyPrinter::VisitThrow(Throw* node) {
329   Print("throw ");
330   Visit(node->exception());
331 }
332 
333 
VisitProperty(Property * node)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 
VisitCall(Call * node)351 void PrettyPrinter::VisitCall(Call* node) {
352   Visit(node->expression());
353   PrintArguments(node->arguments());
354 }
355 
356 
VisitCallNew(CallNew * node)357 void PrettyPrinter::VisitCallNew(CallNew* node) {
358   Print("new (");
359   Visit(node->expression());
360   Print(")");
361   PrintArguments(node->arguments());
362 }
363 
364 
VisitCallRuntime(CallRuntime * node)365 void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
366   Print("%%");
367   PrintLiteral(node->name(), false);
368   PrintArguments(node->arguments());
369 }
370 
371 
VisitUnaryOperation(UnaryOperation * node)372 void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) {
373   Print("(%s", Token::String(node->op()));
374   Visit(node->expression());
375   Print(")");
376 }
377 
378 
VisitCountOperation(CountOperation * node)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 
VisitBinaryOperation(BinaryOperation * node)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 
VisitCompareOperation(CompareOperation * node)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 
VisitThisFunction(ThisFunction * node)406 void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
407   Print("<this-function>");
408 }
409 
410 
Print(AstNode * node)411 const char* PrettyPrinter::Print(AstNode* node) {
412   Init();
413   Visit(node);
414   return output_;
415 }
416 
417 
PrintExpression(FunctionLiteral * program)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 
PrintProgram(FunctionLiteral * program)427 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
428   Init();
429   PrintStatements(program->body());
430   Print("\n");
431   return output_;
432 }
433 
434 
PrintOut(AstNode * node)435 void PrettyPrinter::PrintOut(AstNode* node) {
436   PrettyPrinter printer;
437   PrintF("%s", printer.Print(node));
438 }
439 
440 
Init()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 
Print(const char * format,...)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 
PrintStatements(ZoneList<Statement * > * statements)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 
PrintLabels(ZoneStringList * labels)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 
PrintArguments(ZoneList<Expression * > * arguments)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 
PrintLiteral(Handle<Object> value,bool quote)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 
PrintParameters(Scope * scope)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 
PrintDeclarations(ZoneList<Declaration * > * declarations)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 
PrintFunctionLiteral(FunctionLiteral * function)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 
PrintCaseClause(CaseClause * clause)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:
IndentedScope()593   IndentedScope() {
594     ast_printer_->inc_indent();
595   }
596 
IndentedScope(const char * txt,AstNode * node=NULL)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 
~IndentedScope()618   virtual ~IndentedScope() {
619     ast_printer_->dec_indent();
620   }
621 
SetAstPrinter(AstPrinter * a)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 
AstPrinter()637 AstPrinter::AstPrinter() {
638   ASSERT(indent_ == 0);
639   IndentedScope::SetAstPrinter(this);
640 }
641 
642 
~AstPrinter()643 AstPrinter::~AstPrinter() {
644   ASSERT(indent_ == 0);
645   IndentedScope::SetAstPrinter(NULL);
646 }
647 
648 
PrintIndented(const char * txt)649 void AstPrinter::PrintIndented(const char* txt) {
650   for (int i = 0; i < indent_; i++) {
651     Print(". ");
652   }
653   Print(txt);
654 }
655 
656 
PrintLiteralIndented(const char * info,Handle<Object> value,bool quote)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 
PrintLiteralWithModeIndented(const char * info,Variable * var,Handle<Object> value,StaticType * type,int num)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 
PrintLabelsIndented(const char * info,ZoneStringList * labels)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 
PrintIndentedVisit(const char * s,AstNode * node)707 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
708   IndentedScope indent(s, node);
709   Visit(node);
710 }
711 
712 
PrintProgram(FunctionLiteral * program)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 
PrintDeclarations(ZoneList<Declaration * > * declarations)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 
PrintParameters(Scope * scope)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 
PrintStatements(ZoneList<Statement * > * statements)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 
PrintArguments(ZoneList<Expression * > * arguments)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 
PrintCaseClause(CaseClause * clause)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 
VisitBlock(Block * node)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 
VisitDeclaration(Declaration * node)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 
VisitExpressionStatement(ExpressionStatement * node)801 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
802   Visit(node->expression());
803 }
804 
805 
VisitEmptyStatement(EmptyStatement * node)806 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
807   PrintIndented("EMPTY\n");
808 }
809 
810 
VisitIfStatement(IfStatement * node)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 
VisitContinueStatement(ContinueStatement * node)820 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
821   PrintLabelsIndented("CONTINUE", node->target()->labels());
822 }
823 
824 
VisitBreakStatement(BreakStatement * node)825 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
826   PrintLabelsIndented("BREAK", node->target()->labels());
827 }
828 
829 
VisitReturnStatement(ReturnStatement * node)830 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
831   PrintIndentedVisit("RETURN", node->expression());
832 }
833 
834 
VisitWithEnterStatement(WithEnterStatement * node)835 void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
836   PrintIndentedVisit("WITH ENTER", node->expression());
837 }
838 
839 
VisitWithExitStatement(WithExitStatement * node)840 void AstPrinter::VisitWithExitStatement(WithExitStatement* node) {
841   PrintIndented("WITH EXIT\n");
842 }
843 
844 
VisitSwitchStatement(SwitchStatement * node)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 
VisitDoWhileStatement(DoWhileStatement * node)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 
VisitWhileStatement(WhileStatement * node)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 
VisitForStatement(ForStatement * node)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 
VisitForInStatement(ForInStatement * node)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 
VisitTryCatchStatement(TryCatchStatement * node)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 
VisitTryFinallyStatement(TryFinallyStatement * node)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 
VisitDebuggerStatement(DebuggerStatement * node)904 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
905   IndentedScope indent("DEBUGGER");
906 }
907 
908 
VisitFunctionLiteral(FunctionLiteral * node)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 
VisitFunctionBoilerplateLiteral(FunctionBoilerplateLiteral * node)921 void AstPrinter::VisitFunctionBoilerplateLiteral(
922     FunctionBoilerplateLiteral* node) {
923   IndentedScope indent("FUNC LITERAL");
924   PrintLiteralIndented("BOILERPLATE", node->boilerplate(), true);
925 }
926 
927 
VisitConditional(Conditional * node)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 
VisitLiteral(Literal * node)936 void AstPrinter::VisitLiteral(Literal* node) {
937   PrintLiteralIndented("LITERAL", node->handle(), true);
938 }
939 
940 
VisitRegExpLiteral(RegExpLiteral * node)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 
VisitObjectLiteral(ObjectLiteral * node)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 
VisitArrayLiteral(ArrayLiteral * node)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 
VisitCatchExtensionObject(CatchExtensionObject * node)992 void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
993   IndentedScope indent("CatchExtensionObject");
994   PrintIndentedVisit("KEY", node->key());
995   PrintIndentedVisit("VALUE", node->value());
996 }
997 
998 
VisitSlot(Slot * node)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 
VisitVariableProxy(VariableProxy * node)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 
VisitAssignment(Assignment * node)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 
VisitThrow(Throw * node)1041 void AstPrinter::VisitThrow(Throw* node) {
1042   PrintIndentedVisit("THROW", node->exception());
1043 }
1044 
1045 
VisitProperty(Property * node)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 
VisitCall(Call * node)1058 void AstPrinter::VisitCall(Call* node) {
1059   IndentedScope indent("CALL");
1060   Visit(node->expression());
1061   PrintArguments(node->arguments());
1062 }
1063 
1064 
VisitCallNew(CallNew * node)1065 void AstPrinter::VisitCallNew(CallNew* node) {
1066   IndentedScope indent("CALL NEW");
1067   Visit(node->expression());
1068   PrintArguments(node->arguments());
1069 }
1070 
1071 
VisitCallRuntime(CallRuntime * node)1072 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1073   PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
1074   IndentedScope indent;
1075   PrintArguments(node->arguments());
1076 }
1077 
1078 
VisitUnaryOperation(UnaryOperation * node)1079 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1080   PrintIndentedVisit(Token::Name(node->op()), node->expression());
1081 }
1082 
1083 
VisitCountOperation(CountOperation * node)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 
VisitBinaryOperation(BinaryOperation * node)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 
VisitCompareOperation(CompareOperation * node)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 
VisitThisFunction(ThisFunction * node)1113 void AstPrinter::VisitThisFunction(ThisFunction* node) {
1114   IndentedScope indent("THIS-FUNCTION");
1115 }
1116 
1117 
TagScope(JsonAstBuilder * builder,const char * name)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 
~TagScope()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 
AttributesScope(JsonAstBuilder * builder)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 
~AttributesScope()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 
BuildProgram(FunctionLiteral * program)1165 const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) {
1166   Init();
1167   Visit(program);
1168   Print("\n");
1169   return Output();
1170 }
1171 
1172 
AddAttributePrefix(const char * name)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 
AddAttribute(const char * name,Handle<String> value)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 
AddAttribute(const char * name,const char * value)1192 void JsonAstBuilder::AddAttribute(const char* name, const char* value) {
1193   AddAttributePrefix(name);
1194   Print("\"%s\"", value);
1195 }
1196 
1197 
AddAttribute(const char * name,int value)1198 void JsonAstBuilder::AddAttribute(const char* name, int value) {
1199   AddAttributePrefix(name);
1200   Print("%d", value);
1201 }
1202 
1203 
AddAttribute(const char * name,bool value)1204 void JsonAstBuilder::AddAttribute(const char* name, bool value) {
1205   AddAttributePrefix(name);
1206   Print(value ? "true" : "false");
1207 }
1208 
1209 
VisitBlock(Block * stmt)1210 void JsonAstBuilder::VisitBlock(Block* stmt) {
1211   TagScope tag(this, "Block");
1212   VisitStatements(stmt->statements());
1213 }
1214 
1215 
VisitExpressionStatement(ExpressionStatement * stmt)1216 void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1217   TagScope tag(this, "ExpressionStatement");
1218   Visit(stmt->expression());
1219 }
1220 
1221 
VisitEmptyStatement(EmptyStatement * stmt)1222 void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1223   TagScope tag(this, "EmptyStatement");
1224 }
1225 
1226 
VisitIfStatement(IfStatement * stmt)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 
VisitContinueStatement(ContinueStatement * stmt)1235 void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) {
1236   TagScope tag(this, "ContinueStatement");
1237 }
1238 
1239 
VisitBreakStatement(BreakStatement * stmt)1240 void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) {
1241   TagScope tag(this, "BreakStatement");
1242 }
1243 
1244 
VisitReturnStatement(ReturnStatement * stmt)1245 void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1246   TagScope tag(this, "ReturnStatement");
1247   Visit(stmt->expression());
1248 }
1249 
1250 
VisitWithEnterStatement(WithEnterStatement * stmt)1251 void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
1252   TagScope tag(this, "WithEnterStatement");
1253   Visit(stmt->expression());
1254 }
1255 
1256 
VisitWithExitStatement(WithExitStatement * stmt)1257 void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
1258   TagScope tag(this, "WithExitStatement");
1259 }
1260 
1261 
VisitSwitchStatement(SwitchStatement * stmt)1262 void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1263   TagScope tag(this, "SwitchStatement");
1264 }
1265 
1266 
VisitDoWhileStatement(DoWhileStatement * stmt)1267 void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1268   TagScope tag(this, "DoWhileStatement");
1269   Visit(stmt->body());
1270   Visit(stmt->cond());
1271 }
1272 
1273 
VisitWhileStatement(WhileStatement * stmt)1274 void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) {
1275   TagScope tag(this, "WhileStatement");
1276   Visit(stmt->cond());
1277   Visit(stmt->body());
1278 }
1279 
1280 
VisitForStatement(ForStatement * stmt)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 
VisitForInStatement(ForInStatement * stmt)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 
VisitTryCatchStatement(TryCatchStatement * stmt)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 
VisitTryFinallyStatement(TryFinallyStatement * stmt)1306 void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1307   TagScope tag(this, "TryFinallyStatement");
1308   Visit(stmt->try_block());
1309   Visit(stmt->finally_block());
1310 }
1311 
1312 
VisitDebuggerStatement(DebuggerStatement * stmt)1313 void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1314   TagScope tag(this, "DebuggerStatement");
1315 }
1316 
1317 
VisitFunctionLiteral(FunctionLiteral * expr)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 
VisitFunctionBoilerplateLiteral(FunctionBoilerplateLiteral * expr)1329 void JsonAstBuilder::VisitFunctionBoilerplateLiteral(
1330     FunctionBoilerplateLiteral* expr) {
1331   TagScope tag(this, "FunctionBoilerplateLiteral");
1332 }
1333 
1334 
VisitConditional(Conditional * expr)1335 void JsonAstBuilder::VisitConditional(Conditional* expr) {
1336   TagScope tag(this, "Conditional");
1337 }
1338 
1339 
VisitSlot(Slot * expr)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 
VisitVariableProxy(VariableProxy * expr)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 
VisitLiteral(Literal * expr)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 
VisitRegExpLiteral(RegExpLiteral * expr)1391 void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1392   TagScope tag(this, "RegExpLiteral");
1393 }
1394 
1395 
VisitObjectLiteral(ObjectLiteral * expr)1396 void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1397   TagScope tag(this, "ObjectLiteral");
1398 }
1399 
1400 
VisitArrayLiteral(ArrayLiteral * expr)1401 void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1402   TagScope tag(this, "ArrayLiteral");
1403 }
1404 
1405 
VisitCatchExtensionObject(CatchExtensionObject * expr)1406 void JsonAstBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
1407   TagScope tag(this, "CatchExtensionObject");
1408   Visit(expr->key());
1409   Visit(expr->value());
1410 }
1411 
1412 
VisitAssignment(Assignment * expr)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 
VisitThrow(Throw * expr)1424 void JsonAstBuilder::VisitThrow(Throw* expr) {
1425   TagScope tag(this, "Throw");
1426   Visit(expr->exception());
1427 }
1428 
1429 
VisitProperty(Property * expr)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 
VisitCall(Call * expr)1441 void JsonAstBuilder::VisitCall(Call* expr) {
1442   TagScope tag(this, "Call");
1443   Visit(expr->expression());
1444   VisitExpressions(expr->arguments());
1445 }
1446 
1447 
VisitCallNew(CallNew * expr)1448 void JsonAstBuilder::VisitCallNew(CallNew* expr) {
1449   TagScope tag(this, "CallNew");
1450   Visit(expr->expression());
1451   VisitExpressions(expr->arguments());
1452 }
1453 
1454 
VisitCallRuntime(CallRuntime * expr)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 
VisitUnaryOperation(UnaryOperation * expr)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 
VisitCountOperation(CountOperation * expr)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 
VisitBinaryOperation(BinaryOperation * expr)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 
VisitCompareOperation(CompareOperation * expr)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 
VisitThisFunction(ThisFunction * expr)1508 void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) {
1509   TagScope tag(this, "ThisFunction");
1510 }
1511 
1512 
VisitDeclaration(Declaration * decl)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