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