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