• 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 
VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral * node)230 void PrettyPrinter::VisitSharedFunctionInfoLiteral(
231     SharedFunctionInfoLiteral* node) {
232   Print("(");
233   PrintLiteral(node->shared_function_info(), 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("local[%d]", node->index());
301       break;
302     case Slot::CONTEXT:
303       Print("context[%d]", node->index());
304       break;
305     case Slot::LOOKUP:
306       Print("lookup[");
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 
VisitCompareToNull(CompareToNull * node)406 void PrettyPrinter::VisitCompareToNull(CompareToNull* node) {
407   Print("(");
408   Visit(node->expression());
409   Print("%s null)", Token::String(node->op()));
410 }
411 
412 
VisitThisFunction(ThisFunction * node)413 void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
414   Print("<this-function>");
415 }
416 
417 
Print(AstNode * node)418 const char* PrettyPrinter::Print(AstNode* node) {
419   Init();
420   Visit(node);
421   return output_;
422 }
423 
424 
PrintExpression(FunctionLiteral * program)425 const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
426   Init();
427   ExpressionStatement* statement =
428     program->body()->at(0)->AsExpressionStatement();
429   Visit(statement->expression());
430   return output_;
431 }
432 
433 
PrintProgram(FunctionLiteral * program)434 const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
435   Init();
436   PrintStatements(program->body());
437   Print("\n");
438   return output_;
439 }
440 
441 
PrintOut(AstNode * node)442 void PrettyPrinter::PrintOut(AstNode* node) {
443   PrettyPrinter printer;
444   PrintF("%s", printer.Print(node));
445 }
446 
447 
Init()448 void PrettyPrinter::Init() {
449   if (size_ == 0) {
450     ASSERT(output_ == NULL);
451     const int initial_size = 256;
452     output_ = NewArray<char>(initial_size);
453     size_ = initial_size;
454   }
455   output_[0] = '\0';
456   pos_ = 0;
457 }
458 
459 
Print(const char * format,...)460 void PrettyPrinter::Print(const char* format, ...) {
461   for (;;) {
462     va_list arguments;
463     va_start(arguments, format);
464     int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_,
465                           format,
466                           arguments);
467     va_end(arguments);
468 
469     if (n >= 0) {
470       // there was enough space - we are done
471       pos_ += n;
472       return;
473     } else {
474       // there was not enough space - allocate more and try again
475       const int slack = 32;
476       int new_size = size_ + (size_ >> 1) + slack;
477       char* new_output = NewArray<char>(new_size);
478       memcpy(new_output, output_, pos_);
479       DeleteArray(output_);
480       output_ = new_output;
481       size_ = new_size;
482     }
483   }
484 }
485 
486 
PrintStatements(ZoneList<Statement * > * statements)487 void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
488   for (int i = 0; i < statements->length(); i++) {
489     if (i != 0) Print(" ");
490     Visit(statements->at(i));
491   }
492 }
493 
494 
PrintLabels(ZoneStringList * labels)495 void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
496   if (labels != NULL) {
497     for (int i = 0; i < labels->length(); i++) {
498       PrintLiteral(labels->at(i), false);
499       Print(": ");
500     }
501   }
502 }
503 
504 
PrintArguments(ZoneList<Expression * > * arguments)505 void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
506   Print("(");
507   for (int i = 0; i < arguments->length(); i++) {
508     if (i != 0) Print(", ");
509     Visit(arguments->at(i));
510   }
511   Print(")");
512 }
513 
514 
PrintLiteral(Handle<Object> value,bool quote)515 void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
516   Object* object = *value;
517   if (object->IsString()) {
518     String* string = String::cast(object);
519     if (quote) Print("\"");
520     for (int i = 0; i < string->length(); i++) {
521       Print("%c", string->Get(i));
522     }
523     if (quote) Print("\"");
524   } else if (object->IsNull()) {
525     Print("null");
526   } else if (object->IsTrue()) {
527     Print("true");
528   } else if (object->IsFalse()) {
529     Print("false");
530   } else if (object->IsUndefined()) {
531     Print("undefined");
532   } else if (object->IsNumber()) {
533     Print("%g", object->Number());
534   } else if (object->IsJSObject()) {
535     // regular expression
536     if (object->IsJSFunction()) {
537       Print("JS-Function");
538     } else if (object->IsJSArray()) {
539       Print("JS-array[%u]", JSArray::cast(object)->length());
540     } else if (object->IsJSObject()) {
541       Print("JS-Object");
542     } else {
543       Print("?UNKNOWN?");
544     }
545   } else if (object->IsFixedArray()) {
546     Print("FixedArray");
547   } else {
548     Print("<unknown literal %p>", object);
549   }
550 }
551 
552 
PrintParameters(Scope * scope)553 void PrettyPrinter::PrintParameters(Scope* scope) {
554   Print("(");
555   for (int i = 0; i < scope->num_parameters(); i++) {
556     if (i  > 0) Print(", ");
557     PrintLiteral(scope->parameter(i)->name(), false);
558   }
559   Print(")");
560 }
561 
562 
PrintDeclarations(ZoneList<Declaration * > * declarations)563 void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
564   for (int i = 0; i < declarations->length(); i++) {
565     if (i > 0) Print(" ");
566     Visit(declarations->at(i));
567   }
568 }
569 
570 
PrintFunctionLiteral(FunctionLiteral * function)571 void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
572   Print("function ");
573   PrintLiteral(function->name(), false);
574   PrintParameters(function->scope());
575   Print(" { ");
576   PrintDeclarations(function->scope()->declarations());
577   PrintStatements(function->body());
578   Print(" }");
579 }
580 
581 
PrintCaseClause(CaseClause * clause)582 void PrettyPrinter::PrintCaseClause(CaseClause* clause) {
583   if (clause->is_default()) {
584     Print("default");
585   } else {
586     Print("case ");
587     Visit(clause->label());
588   }
589   Print(": ");
590   PrintStatements(clause->statements());
591   if (clause->statements()->length() > 0)
592     Print(" ");
593 }
594 
595 
596 //-----------------------------------------------------------------------------
597 
598 class IndentedScope BASE_EMBEDDED {
599  public:
IndentedScope(AstPrinter * printer)600   explicit IndentedScope(AstPrinter* printer) : ast_printer_(printer) {
601     ast_printer_->inc_indent();
602   }
603 
IndentedScope(AstPrinter * printer,const char * txt,AstNode * node=NULL)604   IndentedScope(AstPrinter* printer, const char* txt, AstNode* node = NULL)
605       : ast_printer_(printer) {
606     ast_printer_->PrintIndented(txt);
607     ast_printer_->Print("\n");
608     ast_printer_->inc_indent();
609   }
610 
~IndentedScope()611   virtual ~IndentedScope() {
612     ast_printer_->dec_indent();
613   }
614 
615  private:
616   AstPrinter* ast_printer_;
617 };
618 
619 
620 //-----------------------------------------------------------------------------
621 
622 
AstPrinter()623 AstPrinter::AstPrinter() : indent_(0) {
624 }
625 
626 
~AstPrinter()627 AstPrinter::~AstPrinter() {
628   ASSERT(indent_ == 0);
629 }
630 
631 
PrintIndented(const char * txt)632 void AstPrinter::PrintIndented(const char* txt) {
633   for (int i = 0; i < indent_; i++) {
634     Print(". ");
635   }
636   Print(txt);
637 }
638 
639 
PrintLiteralIndented(const char * info,Handle<Object> value,bool quote)640 void AstPrinter::PrintLiteralIndented(const char* info,
641                                       Handle<Object> value,
642                                       bool quote) {
643   PrintIndented(info);
644   Print(" ");
645   PrintLiteral(value, quote);
646   Print("\n");
647 }
648 
649 
PrintLiteralWithModeIndented(const char * info,Variable * var,Handle<Object> value)650 void AstPrinter::PrintLiteralWithModeIndented(const char* info,
651                                               Variable* var,
652                                               Handle<Object> value) {
653   if (var == NULL) {
654     PrintLiteralIndented(info, value, true);
655   } else {
656     EmbeddedVector<char, 256> buf;
657     int pos = OS::SNPrintF(buf, "%s (mode = %s", info,
658                            Variable::Mode2String(var->mode()));
659     OS::SNPrintF(buf + pos, ")");
660     PrintLiteralIndented(buf.start(), value, true);
661   }
662 }
663 
664 
PrintLabelsIndented(const char * info,ZoneStringList * labels)665 void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) {
666   if (labels != NULL && labels->length() > 0) {
667     if (info == NULL) {
668       PrintIndented("LABELS ");
669     } else {
670       PrintIndented(info);
671       Print(" ");
672     }
673     PrintLabels(labels);
674   } else if (info != NULL) {
675     PrintIndented(info);
676   }
677   Print("\n");
678 }
679 
680 
PrintIndentedVisit(const char * s,AstNode * node)681 void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
682   IndentedScope indent(this, s, node);
683   Visit(node);
684 }
685 
686 
PrintProgram(FunctionLiteral * program)687 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
688   Init();
689   { IndentedScope indent(this, "FUNC");
690     PrintLiteralIndented("NAME", program->name(), true);
691     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
692     PrintParameters(program->scope());
693     PrintDeclarations(program->scope()->declarations());
694     PrintStatements(program->body());
695   }
696   return Output();
697 }
698 
699 
PrintDeclarations(ZoneList<Declaration * > * declarations)700 void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
701   if (declarations->length() > 0) {
702     IndentedScope indent(this, "DECLS");
703     for (int i = 0; i < declarations->length(); i++) {
704       Visit(declarations->at(i));
705     }
706   }
707 }
708 
709 
PrintParameters(Scope * scope)710 void AstPrinter::PrintParameters(Scope* scope) {
711   if (scope->num_parameters() > 0) {
712     IndentedScope indent(this, "PARAMS");
713     for (int i = 0; i < scope->num_parameters(); i++) {
714       PrintLiteralWithModeIndented("VAR", scope->parameter(i),
715                                    scope->parameter(i)->name());
716     }
717   }
718 }
719 
720 
PrintStatements(ZoneList<Statement * > * statements)721 void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
722   for (int i = 0; i < statements->length(); i++) {
723     Visit(statements->at(i));
724   }
725 }
726 
727 
PrintArguments(ZoneList<Expression * > * arguments)728 void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
729   for (int i = 0; i < arguments->length(); i++) {
730     Visit(arguments->at(i));
731   }
732 }
733 
734 
PrintCaseClause(CaseClause * clause)735 void AstPrinter::PrintCaseClause(CaseClause* clause) {
736   if (clause->is_default()) {
737     IndentedScope indent(this, "DEFAULT");
738     PrintStatements(clause->statements());
739   } else {
740     IndentedScope indent(this, "CASE");
741     Visit(clause->label());
742     PrintStatements(clause->statements());
743   }
744 }
745 
746 
VisitBlock(Block * node)747 void AstPrinter::VisitBlock(Block* node) {
748   const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
749   IndentedScope indent(this, block_txt);
750   PrintStatements(node->statements());
751 }
752 
753 
VisitDeclaration(Declaration * node)754 void AstPrinter::VisitDeclaration(Declaration* node) {
755   if (node->fun() == NULL) {
756     // var or const declarations
757     PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
758                                  node->proxy()->AsVariable(),
759                                  node->proxy()->name());
760   } else {
761     // function declarations
762     PrintIndented("FUNCTION ");
763     PrintLiteral(node->proxy()->name(), true);
764     Print(" = function ");
765     PrintLiteral(node->fun()->name(), false);
766     Print("\n");
767   }
768 }
769 
770 
VisitExpressionStatement(ExpressionStatement * node)771 void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
772   Visit(node->expression());
773 }
774 
775 
VisitEmptyStatement(EmptyStatement * node)776 void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
777   PrintIndented("EMPTY\n");
778 }
779 
780 
VisitIfStatement(IfStatement * node)781 void AstPrinter::VisitIfStatement(IfStatement* node) {
782   PrintIndentedVisit("IF", node->condition());
783   PrintIndentedVisit("THEN", node->then_statement());
784   if (node->HasElseStatement()) {
785     PrintIndentedVisit("ELSE", node->else_statement());
786   }
787 }
788 
789 
VisitContinueStatement(ContinueStatement * node)790 void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
791   PrintLabelsIndented("CONTINUE", node->target()->labels());
792 }
793 
794 
VisitBreakStatement(BreakStatement * node)795 void AstPrinter::VisitBreakStatement(BreakStatement* node) {
796   PrintLabelsIndented("BREAK", node->target()->labels());
797 }
798 
799 
VisitReturnStatement(ReturnStatement * node)800 void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
801   PrintIndentedVisit("RETURN", node->expression());
802 }
803 
804 
VisitWithEnterStatement(WithEnterStatement * node)805 void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
806   PrintIndentedVisit("WITH ENTER", node->expression());
807 }
808 
809 
VisitWithExitStatement(WithExitStatement * node)810 void AstPrinter::VisitWithExitStatement(WithExitStatement* node) {
811   PrintIndented("WITH EXIT\n");
812 }
813 
814 
VisitSwitchStatement(SwitchStatement * node)815 void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
816   IndentedScope indent(this, "SWITCH");
817   PrintLabelsIndented(NULL, node->labels());
818   PrintIndentedVisit("TAG", node->tag());
819   for (int i = 0; i < node->cases()->length(); i++) {
820     PrintCaseClause(node->cases()->at(i));
821   }
822 }
823 
824 
VisitDoWhileStatement(DoWhileStatement * node)825 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
826   IndentedScope indent(this, "DO");
827   PrintLabelsIndented(NULL, node->labels());
828   PrintIndentedVisit("BODY", node->body());
829   PrintIndentedVisit("COND", node->cond());
830 }
831 
832 
VisitWhileStatement(WhileStatement * node)833 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
834   IndentedScope indent(this, "WHILE");
835   PrintLabelsIndented(NULL, node->labels());
836   PrintIndentedVisit("COND", node->cond());
837   PrintIndentedVisit("BODY", node->body());
838 }
839 
840 
VisitForStatement(ForStatement * node)841 void AstPrinter::VisitForStatement(ForStatement* node) {
842   IndentedScope indent(this, "FOR");
843   PrintLabelsIndented(NULL, node->labels());
844   if (node->init()) PrintIndentedVisit("INIT", node->init());
845   if (node->cond()) PrintIndentedVisit("COND", node->cond());
846   PrintIndentedVisit("BODY", node->body());
847   if (node->next()) PrintIndentedVisit("NEXT", node->next());
848 }
849 
850 
VisitForInStatement(ForInStatement * node)851 void AstPrinter::VisitForInStatement(ForInStatement* node) {
852   IndentedScope indent(this, "FOR IN");
853   PrintIndentedVisit("FOR", node->each());
854   PrintIndentedVisit("IN", node->enumerable());
855   PrintIndentedVisit("BODY", node->body());
856 }
857 
858 
VisitTryCatchStatement(TryCatchStatement * node)859 void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
860   IndentedScope indent(this, "TRY CATCH");
861   PrintIndentedVisit("TRY", node->try_block());
862   PrintIndentedVisit("CATCHVAR", node->catch_var());
863   PrintIndentedVisit("CATCH", node->catch_block());
864 }
865 
866 
VisitTryFinallyStatement(TryFinallyStatement * node)867 void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
868   IndentedScope indent(this, "TRY FINALLY");
869   PrintIndentedVisit("TRY", node->try_block());
870   PrintIndentedVisit("FINALLY", node->finally_block());
871 }
872 
873 
VisitDebuggerStatement(DebuggerStatement * node)874 void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
875   IndentedScope indent(this, "DEBUGGER");
876 }
877 
878 
VisitFunctionLiteral(FunctionLiteral * node)879 void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
880   IndentedScope indent(this, "FUNC LITERAL");
881   PrintLiteralIndented("NAME", node->name(), false);
882   PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
883   PrintParameters(node->scope());
884   // We don't want to see the function literal in this case: it
885   // will be printed via PrintProgram when the code for it is
886   // generated.
887   // PrintStatements(node->body());
888 }
889 
890 
VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral * node)891 void AstPrinter::VisitSharedFunctionInfoLiteral(
892     SharedFunctionInfoLiteral* node) {
893   IndentedScope indent(this, "FUNC LITERAL");
894   PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true);
895 }
896 
897 
VisitConditional(Conditional * node)898 void AstPrinter::VisitConditional(Conditional* node) {
899   IndentedScope indent(this, "CONDITIONAL");
900   PrintIndentedVisit("?", node->condition());
901   PrintIndentedVisit("THEN", node->then_expression());
902   PrintIndentedVisit("ELSE", node->else_expression());
903 }
904 
905 
VisitLiteral(Literal * node)906 void AstPrinter::VisitLiteral(Literal* node) {
907   PrintLiteralIndented("LITERAL", node->handle(), true);
908 }
909 
910 
VisitRegExpLiteral(RegExpLiteral * node)911 void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
912   IndentedScope indent(this, "REGEXP LITERAL");
913   PrintLiteralIndented("PATTERN", node->pattern(), false);
914   PrintLiteralIndented("FLAGS", node->flags(), false);
915 }
916 
917 
VisitObjectLiteral(ObjectLiteral * node)918 void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
919   IndentedScope indent(this, "OBJ LITERAL");
920   for (int i = 0; i < node->properties()->length(); i++) {
921     const char* prop_kind = NULL;
922     switch (node->properties()->at(i)->kind()) {
923       case ObjectLiteral::Property::CONSTANT:
924         prop_kind = "PROPERTY - CONSTANT";
925         break;
926       case ObjectLiteral::Property::COMPUTED:
927         prop_kind = "PROPERTY - COMPUTED";
928         break;
929       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
930         prop_kind = "PROPERTY - MATERIALIZED_LITERAL";
931         break;
932       case ObjectLiteral::Property::PROTOTYPE:
933         prop_kind = "PROPERTY - PROTOTYPE";
934         break;
935       case ObjectLiteral::Property::GETTER:
936         prop_kind = "PROPERTY - GETTER";
937         break;
938       case ObjectLiteral::Property::SETTER:
939         prop_kind = "PROPERTY - SETTER";
940         break;
941       default:
942         UNREACHABLE();
943     }
944     IndentedScope prop(this, prop_kind);
945     PrintIndentedVisit("KEY", node->properties()->at(i)->key());
946     PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
947   }
948 }
949 
950 
VisitArrayLiteral(ArrayLiteral * node)951 void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
952   IndentedScope indent(this, "ARRAY LITERAL");
953   if (node->values()->length() > 0) {
954     IndentedScope indent(this, "VALUES");
955     for (int i = 0; i < node->values()->length(); i++) {
956       Visit(node->values()->at(i));
957     }
958   }
959 }
960 
961 
VisitCatchExtensionObject(CatchExtensionObject * node)962 void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) {
963   IndentedScope indent(this, "CatchExtensionObject");
964   PrintIndentedVisit("KEY", node->key());
965   PrintIndentedVisit("VALUE", node->value());
966 }
967 
968 
VisitSlot(Slot * node)969 void AstPrinter::VisitSlot(Slot* node) {
970   PrintIndented("SLOT ");
971   PrettyPrinter::VisitSlot(node);
972   Print("\n");
973 }
974 
975 
VisitVariableProxy(VariableProxy * node)976 void AstPrinter::VisitVariableProxy(VariableProxy* node) {
977   PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name());
978   Variable* var = node->var();
979   if (var != NULL && var->rewrite() != NULL) {
980     IndentedScope indent(this);
981     Visit(var->rewrite());
982   }
983 }
984 
985 
VisitAssignment(Assignment * node)986 void AstPrinter::VisitAssignment(Assignment* node) {
987   IndentedScope indent(this, Token::Name(node->op()), node);
988   Visit(node->target());
989   Visit(node->value());
990 }
991 
992 
VisitThrow(Throw * node)993 void AstPrinter::VisitThrow(Throw* node) {
994   PrintIndentedVisit("THROW", node->exception());
995 }
996 
997 
VisitProperty(Property * node)998 void AstPrinter::VisitProperty(Property* node) {
999   IndentedScope indent(this, "PROPERTY", node);
1000   Visit(node->obj());
1001   Literal* literal = node->key()->AsLiteral();
1002   if (literal != NULL && literal->handle()->IsSymbol()) {
1003     PrintLiteralIndented("NAME", literal->handle(), false);
1004   } else {
1005     PrintIndentedVisit("KEY", node->key());
1006   }
1007 }
1008 
1009 
VisitCall(Call * node)1010 void AstPrinter::VisitCall(Call* node) {
1011   IndentedScope indent(this, "CALL");
1012   Visit(node->expression());
1013   PrintArguments(node->arguments());
1014 }
1015 
1016 
VisitCallNew(CallNew * node)1017 void AstPrinter::VisitCallNew(CallNew* node) {
1018   IndentedScope indent(this, "CALL NEW");
1019   Visit(node->expression());
1020   PrintArguments(node->arguments());
1021 }
1022 
1023 
VisitCallRuntime(CallRuntime * node)1024 void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1025   PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
1026   IndentedScope indent(this);
1027   PrintArguments(node->arguments());
1028 }
1029 
1030 
VisitUnaryOperation(UnaryOperation * node)1031 void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1032   PrintIndentedVisit(Token::Name(node->op()), node->expression());
1033 }
1034 
1035 
VisitCountOperation(CountOperation * node)1036 void AstPrinter::VisitCountOperation(CountOperation* node) {
1037   EmbeddedVector<char, 128> buf;
1038   OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1039                Token::Name(node->op()));
1040   PrintIndentedVisit(buf.start(), node->expression());
1041 }
1042 
1043 
VisitBinaryOperation(BinaryOperation * node)1044 void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
1045   IndentedScope indent(this, Token::Name(node->op()), node);
1046   Visit(node->left());
1047   Visit(node->right());
1048 }
1049 
1050 
VisitCompareOperation(CompareOperation * node)1051 void AstPrinter::VisitCompareOperation(CompareOperation* node) {
1052   IndentedScope indent(this, Token::Name(node->op()), node);
1053   Visit(node->left());
1054   Visit(node->right());
1055 }
1056 
1057 
VisitCompareToNull(CompareToNull * node)1058 void AstPrinter::VisitCompareToNull(CompareToNull* node) {
1059   const char* name = node->is_strict()
1060       ? "COMPARE-TO-NULL-STRICT"
1061       : "COMPARE-TO-NULL";
1062   IndentedScope indent(this, name, node);
1063   Visit(node->expression());
1064 }
1065 
1066 
VisitThisFunction(ThisFunction * node)1067 void AstPrinter::VisitThisFunction(ThisFunction* node) {
1068   IndentedScope indent(this, "THIS-FUNCTION");
1069 }
1070 
1071 
TagScope(JsonAstBuilder * builder,const char * name)1072 TagScope::TagScope(JsonAstBuilder* builder, const char* name)
1073     : builder_(builder), next_(builder->tag()), has_body_(false) {
1074   if (next_ != NULL) {
1075     next_->use();
1076     builder->Print(",\n");
1077   }
1078   builder->set_tag(this);
1079   builder->PrintIndented("[");
1080   builder->Print("\"%s\"", name);
1081   builder->increase_indent(JsonAstBuilder::kTagIndentSize);
1082 }
1083 
1084 
~TagScope()1085 TagScope::~TagScope() {
1086   builder_->decrease_indent(JsonAstBuilder::kTagIndentSize);
1087   if (has_body_) {
1088     builder_->Print("\n");
1089     builder_->PrintIndented("]");
1090   } else {
1091     builder_->Print("]");
1092   }
1093   builder_->set_tag(next_);
1094 }
1095 
1096 
AttributesScope(JsonAstBuilder * builder)1097 AttributesScope::AttributesScope(JsonAstBuilder* builder)
1098     : builder_(builder), attribute_count_(0) {
1099   builder->set_attributes(this);
1100   builder->tag()->use();
1101   builder->Print(",\n");
1102   builder->PrintIndented("{");
1103   builder->increase_indent(JsonAstBuilder::kAttributesIndentSize);
1104 }
1105 
1106 
~AttributesScope()1107 AttributesScope::~AttributesScope() {
1108   builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize);
1109   if (attribute_count_ > 1) {
1110     builder_->Print("\n");
1111     builder_->PrintIndented("}");
1112   } else {
1113     builder_->Print("}");
1114   }
1115   builder_->set_attributes(NULL);
1116 }
1117 
1118 
BuildProgram(FunctionLiteral * program)1119 const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) {
1120   Init();
1121   Visit(program);
1122   Print("\n");
1123   return Output();
1124 }
1125 
1126 
AddAttributePrefix(const char * name)1127 void JsonAstBuilder::AddAttributePrefix(const char* name) {
1128   if (attributes()->is_used()) {
1129     Print(",\n");
1130     PrintIndented("\"");
1131   } else {
1132     Print("\"");
1133   }
1134   Print("%s\":", name);
1135   attributes()->use();
1136 }
1137 
1138 
AddAttribute(const char * name,Handle<String> value)1139 void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) {
1140   SmartPointer<char> value_string = value->ToCString();
1141   AddAttributePrefix(name);
1142   Print("\"%s\"", *value_string);
1143 }
1144 
1145 
AddAttribute(const char * name,const char * value)1146 void JsonAstBuilder::AddAttribute(const char* name, const char* value) {
1147   AddAttributePrefix(name);
1148   Print("\"%s\"", value);
1149 }
1150 
1151 
AddAttribute(const char * name,int value)1152 void JsonAstBuilder::AddAttribute(const char* name, int value) {
1153   AddAttributePrefix(name);
1154   Print("%d", value);
1155 }
1156 
1157 
AddAttribute(const char * name,bool value)1158 void JsonAstBuilder::AddAttribute(const char* name, bool value) {
1159   AddAttributePrefix(name);
1160   Print(value ? "true" : "false");
1161 }
1162 
1163 
VisitBlock(Block * stmt)1164 void JsonAstBuilder::VisitBlock(Block* stmt) {
1165   TagScope tag(this, "Block");
1166   VisitStatements(stmt->statements());
1167 }
1168 
1169 
VisitExpressionStatement(ExpressionStatement * stmt)1170 void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1171   TagScope tag(this, "ExpressionStatement");
1172   Visit(stmt->expression());
1173 }
1174 
1175 
VisitEmptyStatement(EmptyStatement * stmt)1176 void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1177   TagScope tag(this, "EmptyStatement");
1178 }
1179 
1180 
VisitIfStatement(IfStatement * stmt)1181 void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) {
1182   TagScope tag(this, "IfStatement");
1183   Visit(stmt->condition());
1184   Visit(stmt->then_statement());
1185   Visit(stmt->else_statement());
1186 }
1187 
1188 
VisitContinueStatement(ContinueStatement * stmt)1189 void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) {
1190   TagScope tag(this, "ContinueStatement");
1191 }
1192 
1193 
VisitBreakStatement(BreakStatement * stmt)1194 void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) {
1195   TagScope tag(this, "BreakStatement");
1196 }
1197 
1198 
VisitReturnStatement(ReturnStatement * stmt)1199 void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1200   TagScope tag(this, "ReturnStatement");
1201   Visit(stmt->expression());
1202 }
1203 
1204 
VisitWithEnterStatement(WithEnterStatement * stmt)1205 void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
1206   TagScope tag(this, "WithEnterStatement");
1207   Visit(stmt->expression());
1208 }
1209 
1210 
VisitWithExitStatement(WithExitStatement * stmt)1211 void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
1212   TagScope tag(this, "WithExitStatement");
1213 }
1214 
1215 
VisitSwitchStatement(SwitchStatement * stmt)1216 void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1217   TagScope tag(this, "SwitchStatement");
1218 }
1219 
1220 
VisitDoWhileStatement(DoWhileStatement * stmt)1221 void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1222   TagScope tag(this, "DoWhileStatement");
1223   Visit(stmt->body());
1224   Visit(stmt->cond());
1225 }
1226 
1227 
VisitWhileStatement(WhileStatement * stmt)1228 void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) {
1229   TagScope tag(this, "WhileStatement");
1230   Visit(stmt->cond());
1231   Visit(stmt->body());
1232 }
1233 
1234 
VisitForStatement(ForStatement * stmt)1235 void JsonAstBuilder::VisitForStatement(ForStatement* stmt) {
1236   TagScope tag(this, "ForStatement");
1237   if (stmt->init() != NULL) Visit(stmt->init());
1238   if (stmt->cond() != NULL) Visit(stmt->cond());
1239   Visit(stmt->body());
1240   if (stmt->next() != NULL) Visit(stmt->next());
1241 }
1242 
1243 
VisitForInStatement(ForInStatement * stmt)1244 void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) {
1245   TagScope tag(this, "ForInStatement");
1246   Visit(stmt->each());
1247   Visit(stmt->enumerable());
1248   Visit(stmt->body());
1249 }
1250 
1251 
VisitTryCatchStatement(TryCatchStatement * stmt)1252 void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1253   TagScope tag(this, "TryCatchStatement");
1254   Visit(stmt->try_block());
1255   Visit(stmt->catch_var());
1256   Visit(stmt->catch_block());
1257 }
1258 
1259 
VisitTryFinallyStatement(TryFinallyStatement * stmt)1260 void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1261   TagScope tag(this, "TryFinallyStatement");
1262   Visit(stmt->try_block());
1263   Visit(stmt->finally_block());
1264 }
1265 
1266 
VisitDebuggerStatement(DebuggerStatement * stmt)1267 void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1268   TagScope tag(this, "DebuggerStatement");
1269 }
1270 
1271 
VisitFunctionLiteral(FunctionLiteral * expr)1272 void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
1273   TagScope tag(this, "FunctionLiteral");
1274   {
1275     AttributesScope attributes(this);
1276     AddAttribute("name", expr->name());
1277   }
1278   VisitDeclarations(expr->scope()->declarations());
1279   VisitStatements(expr->body());
1280 }
1281 
1282 
VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral * expr)1283 void JsonAstBuilder::VisitSharedFunctionInfoLiteral(
1284     SharedFunctionInfoLiteral* expr) {
1285   TagScope tag(this, "SharedFunctionInfoLiteral");
1286 }
1287 
1288 
VisitConditional(Conditional * expr)1289 void JsonAstBuilder::VisitConditional(Conditional* expr) {
1290   TagScope tag(this, "Conditional");
1291 }
1292 
1293 
VisitSlot(Slot * expr)1294 void JsonAstBuilder::VisitSlot(Slot* expr) {
1295   TagScope tag(this, "Slot");
1296   {
1297     AttributesScope attributes(this);
1298     switch (expr->type()) {
1299       case Slot::PARAMETER:
1300         AddAttribute("type", "PARAMETER");
1301         break;
1302       case Slot::LOCAL:
1303         AddAttribute("type", "LOCAL");
1304         break;
1305       case Slot::CONTEXT:
1306         AddAttribute("type", "CONTEXT");
1307         break;
1308       case Slot::LOOKUP:
1309         AddAttribute("type", "LOOKUP");
1310         break;
1311     }
1312     AddAttribute("index", expr->index());
1313   }
1314 }
1315 
1316 
VisitVariableProxy(VariableProxy * expr)1317 void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
1318   if (expr->var()->rewrite() == NULL) {
1319     TagScope tag(this, "VariableProxy");
1320     {
1321       AttributesScope attributes(this);
1322       AddAttribute("name", expr->name());
1323       AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
1324     }
1325   } else {
1326     Visit(expr->var()->rewrite());
1327   }
1328 }
1329 
1330 
VisitLiteral(Literal * expr)1331 void JsonAstBuilder::VisitLiteral(Literal* expr) {
1332   TagScope tag(this, "Literal");
1333   {
1334     AttributesScope attributes(this);
1335     Handle<Object> handle = expr->handle();
1336     if (handle->IsString()) {
1337       AddAttribute("handle", Handle<String>(String::cast(*handle)));
1338     } else if (handle->IsSmi()) {
1339       AddAttribute("handle", Smi::cast(*handle)->value());
1340     }
1341   }
1342 }
1343 
1344 
VisitRegExpLiteral(RegExpLiteral * expr)1345 void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1346   TagScope tag(this, "RegExpLiteral");
1347 }
1348 
1349 
VisitObjectLiteral(ObjectLiteral * expr)1350 void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1351   TagScope tag(this, "ObjectLiteral");
1352 }
1353 
1354 
VisitArrayLiteral(ArrayLiteral * expr)1355 void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1356   TagScope tag(this, "ArrayLiteral");
1357 }
1358 
1359 
VisitCatchExtensionObject(CatchExtensionObject * expr)1360 void JsonAstBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
1361   TagScope tag(this, "CatchExtensionObject");
1362   Visit(expr->key());
1363   Visit(expr->value());
1364 }
1365 
1366 
VisitAssignment(Assignment * expr)1367 void JsonAstBuilder::VisitAssignment(Assignment* expr) {
1368   TagScope tag(this, "Assignment");
1369   {
1370     AttributesScope attributes(this);
1371     AddAttribute("op", Token::Name(expr->op()));
1372   }
1373   Visit(expr->target());
1374   Visit(expr->value());
1375 }
1376 
1377 
VisitThrow(Throw * expr)1378 void JsonAstBuilder::VisitThrow(Throw* expr) {
1379   TagScope tag(this, "Throw");
1380   Visit(expr->exception());
1381 }
1382 
1383 
VisitProperty(Property * expr)1384 void JsonAstBuilder::VisitProperty(Property* expr) {
1385   TagScope tag(this, "Property");
1386   {
1387     AttributesScope attributes(this);
1388     AddAttribute("type", expr->is_synthetic() ? "SYNTHETIC" : "NORMAL");
1389   }
1390   Visit(expr->obj());
1391   Visit(expr->key());
1392 }
1393 
1394 
VisitCall(Call * expr)1395 void JsonAstBuilder::VisitCall(Call* expr) {
1396   TagScope tag(this, "Call");
1397   Visit(expr->expression());
1398   VisitExpressions(expr->arguments());
1399 }
1400 
1401 
VisitCallNew(CallNew * expr)1402 void JsonAstBuilder::VisitCallNew(CallNew* expr) {
1403   TagScope tag(this, "CallNew");
1404   Visit(expr->expression());
1405   VisitExpressions(expr->arguments());
1406 }
1407 
1408 
VisitCallRuntime(CallRuntime * expr)1409 void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) {
1410   TagScope tag(this, "CallRuntime");
1411   {
1412     AttributesScope attributes(this);
1413     AddAttribute("name", expr->name());
1414   }
1415   VisitExpressions(expr->arguments());
1416 }
1417 
1418 
VisitUnaryOperation(UnaryOperation * expr)1419 void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) {
1420   TagScope tag(this, "UnaryOperation");
1421   {
1422     AttributesScope attributes(this);
1423     AddAttribute("op", Token::Name(expr->op()));
1424   }
1425   Visit(expr->expression());
1426 }
1427 
1428 
VisitCountOperation(CountOperation * expr)1429 void JsonAstBuilder::VisitCountOperation(CountOperation* expr) {
1430   TagScope tag(this, "CountOperation");
1431   {
1432     AttributesScope attributes(this);
1433     AddAttribute("is_prefix", expr->is_prefix());
1434     AddAttribute("op", Token::Name(expr->op()));
1435   }
1436   Visit(expr->expression());
1437 }
1438 
1439 
VisitBinaryOperation(BinaryOperation * expr)1440 void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) {
1441   TagScope tag(this, "BinaryOperation");
1442   {
1443     AttributesScope attributes(this);
1444     AddAttribute("op", Token::Name(expr->op()));
1445   }
1446   Visit(expr->left());
1447   Visit(expr->right());
1448 }
1449 
1450 
VisitCompareOperation(CompareOperation * expr)1451 void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) {
1452   TagScope tag(this, "CompareOperation");
1453   {
1454     AttributesScope attributes(this);
1455     AddAttribute("op", Token::Name(expr->op()));
1456   }
1457   Visit(expr->left());
1458   Visit(expr->right());
1459 }
1460 
1461 
VisitCompareToNull(CompareToNull * expr)1462 void JsonAstBuilder::VisitCompareToNull(CompareToNull* expr) {
1463   TagScope tag(this, "CompareToNull");
1464   {
1465     AttributesScope attributes(this);
1466     AddAttribute("is_strict", expr->is_strict());
1467   }
1468   Visit(expr->expression());
1469 }
1470 
1471 
VisitThisFunction(ThisFunction * expr)1472 void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) {
1473   TagScope tag(this, "ThisFunction");
1474 }
1475 
1476 
VisitDeclaration(Declaration * decl)1477 void JsonAstBuilder::VisitDeclaration(Declaration* decl) {
1478   TagScope tag(this, "Declaration");
1479   {
1480     AttributesScope attributes(this);
1481     AddAttribute("mode", Variable::Mode2String(decl->mode()));
1482   }
1483   Visit(decl->proxy());
1484   if (decl->fun() != NULL) Visit(decl->fun());
1485 }
1486 
1487 
1488 #endif  // DEBUG
1489 
1490 } }  // namespace v8::internal
1491