blob: bc4125c7c44182e41011e7c92dead348d535014c [file] [log] [blame]
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
kasperl@chromium.org71affb52009-05-26 05:44:31 +000036namespace v8 {
37namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
39#ifdef DEBUG
40
41PrettyPrinter::PrettyPrinter() {
42 output_ = NULL;
43 size_ = 0;
44 pos_ = 0;
45}
46
47
48PrettyPrinter::~PrettyPrinter() {
49 DeleteArray(output_);
50}
51
52
53void 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
61void 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
72void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) {
73 Visit(node->expression());
74 Print(";");
75}
76
77
78void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) {
79 Print(";");
80}
81
82
83void 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
95void 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
107void 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
119void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
120 Print("return ");
121 Visit(node->expression());
122 Print(";");
123}
124
125
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000126void PrettyPrinter::VisitEnterWithContextStatement(
127 EnterWithContextStatement* node) {
128 Print("<enter with context> (");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129 Visit(node->expression());
130 Print(") ");
131}
132
133
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000134void PrettyPrinter::VisitExitContextStatement(ExitContextStatement* node) {
135 Print("<exit context>");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136}
137
138
139void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) {
140 PrintLabels(node->labels());
141 Print("switch (");
142 Visit(node->tag());
143 Print(") { ");
144 ZoneList<CaseClause*>* cases = node->cases();
145 for (int i = 0; i < cases->length(); i++)
146 PrintCaseClause(cases->at(i));
147 Print("}");
148}
149
150
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000151void PrettyPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000152 PrintLabels(node->labels());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000153 Print("do ");
154 Visit(node->body());
155 Print(" while (");
156 Visit(node->cond());
157 Print(");");
158}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000159
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000160
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000161void PrettyPrinter::VisitWhileStatement(WhileStatement* node) {
162 PrintLabels(node->labels());
163 Print("while (");
164 Visit(node->cond());
165 Print(") ");
166 Visit(node->body());
167}
168
169
170void PrettyPrinter::VisitForStatement(ForStatement* node) {
171 PrintLabels(node->labels());
172 Print("for (");
173 if (node->init() != NULL) {
174 Visit(node->init());
175 Print(" ");
176 } else {
177 Print("; ");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000179 if (node->cond() != NULL) Visit(node->cond());
180 Print("; ");
181 if (node->next() != NULL) {
182 Visit(node->next()); // prints extra ';', unfortunately
183 // to fix: should use Expression for next
184 }
185 Print(") ");
186 Visit(node->body());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187}
188
189
190void PrettyPrinter::VisitForInStatement(ForInStatement* node) {
191 PrintLabels(node->labels());
192 Print("for (");
193 Visit(node->each());
194 Print(" in ");
195 Visit(node->enumerable());
196 Print(") ");
197 Visit(node->body());
198}
199
200
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000201void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202 Print("try ");
203 Visit(node->try_block());
204 Print(" catch (");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000205 const bool quote = false;
206 PrintLiteral(node->name(), quote);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207 Print(") ");
208 Visit(node->catch_block());
209}
210
211
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000212void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000213 Print("try ");
214 Visit(node->try_block());
215 Print(" finally ");
216 Visit(node->finally_block());
217}
218
219
220void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
221 Print("debugger ");
222}
223
224
225void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
226 Print("(");
227 PrintFunctionLiteral(node);
228 Print(")");
229}
230
231
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000232void PrettyPrinter::VisitSharedFunctionInfoLiteral(
233 SharedFunctionInfoLiteral* node) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000234 Print("(");
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000235 PrintLiteral(node->shared_function_info(), true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000236 Print(")");
237}
238
239
240void PrettyPrinter::VisitConditional(Conditional* node) {
241 Visit(node->condition());
242 Print(" ? ");
243 Visit(node->then_expression());
244 Print(" : ");
245 Visit(node->else_expression());
246}
247
248
249void PrettyPrinter::VisitLiteral(Literal* node) {
250 PrintLiteral(node->handle(), true);
251}
252
253
254void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
255 Print(" RegExp(");
256 PrintLiteral(node->pattern(), false);
257 Print(",");
258 PrintLiteral(node->flags(), false);
259 Print(") ");
260}
261
262
263void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
264 Print("{ ");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265 for (int i = 0; i < node->properties()->length(); i++) {
266 if (i != 0) Print(",");
267 ObjectLiteral::Property* property = node->properties()->at(i);
268 Print(" ");
269 Visit(property->key());
270 Print(": ");
271 Visit(property->value());
272 }
273 Print(" }");
274}
275
276
277void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
278 Print("[ ");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279 for (int i = 0; i < node->values()->length(); i++) {
280 if (i != 0) Print(",");
281 Visit(node->values()->at(i));
282 }
283 Print(" ]");
284}
285
286
287void PrettyPrinter::VisitSlot(Slot* node) {
288 switch (node->type()) {
289 case Slot::PARAMETER:
290 Print("parameter[%d]", node->index());
291 break;
292 case Slot::LOCAL:
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000293 Print("local[%d]", node->index());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000294 break;
295 case Slot::CONTEXT:
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000296 Print("context[%d]", node->index());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297 break;
298 case Slot::LOOKUP:
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000299 Print("lookup[");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000300 PrintLiteral(node->var()->name(), false);
301 Print("]");
302 break;
303 default:
304 UNREACHABLE();
305 }
306}
307
308
309void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
310 PrintLiteral(node->name(), false);
311}
312
313
314void PrettyPrinter::VisitAssignment(Assignment* node) {
315 Visit(node->target());
316 Print(" %s ", Token::String(node->op()));
317 Visit(node->value());
318}
319
320
321void PrettyPrinter::VisitThrow(Throw* node) {
322 Print("throw ");
323 Visit(node->exception());
324}
325
326
327void PrettyPrinter::VisitProperty(Property* node) {
328 Expression* key = node->key();
329 Literal* literal = key->AsLiteral();
330 if (literal != NULL && literal->handle()->IsSymbol()) {
331 Print("(");
332 Visit(node->obj());
333 Print(").");
334 PrintLiteral(literal->handle(), false);
335 } else {
336 Visit(node->obj());
337 Print("[");
338 Visit(key);
339 Print("]");
340 }
341}
342
343
344void PrettyPrinter::VisitCall(Call* node) {
345 Visit(node->expression());
346 PrintArguments(node->arguments());
347}
348
349
350void PrettyPrinter::VisitCallNew(CallNew* node) {
351 Print("new (");
352 Visit(node->expression());
353 Print(")");
354 PrintArguments(node->arguments());
355}
356
357
358void PrettyPrinter::VisitCallRuntime(CallRuntime* node) {
359 Print("%%");
360 PrintLiteral(node->name(), false);
361 PrintArguments(node->arguments());
362}
363
364
365void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000366 Token::Value op = node->op();
367 bool needsSpace =
368 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
369 Print("(%s%s", Token::String(op), needsSpace ? " " : "");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370 Visit(node->expression());
371 Print(")");
372}
373
374
375void PrettyPrinter::VisitCountOperation(CountOperation* node) {
376 Print("(");
377 if (node->is_prefix()) Print("%s", Token::String(node->op()));
378 Visit(node->expression());
379 if (node->is_postfix()) Print("%s", Token::String(node->op()));
380 Print(")");
381}
382
383
384void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) {
385 Print("(");
386 Visit(node->left());
danno@chromium.org40cb8782011-05-25 07:58:50 +0000387 Print(" %s ", Token::String(node->op()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000388 Visit(node->right());
389 Print(")");
390}
391
392
393void PrettyPrinter::VisitCompareOperation(CompareOperation* node) {
394 Print("(");
395 Visit(node->left());
danno@chromium.org40cb8782011-05-25 07:58:50 +0000396 Print(" %s ", Token::String(node->op()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000397 Visit(node->right());
398 Print(")");
399}
400
401
ricow@chromium.org65fae842010-08-25 15:26:24 +0000402void PrettyPrinter::VisitCompareToNull(CompareToNull* node) {
403 Print("(");
404 Visit(node->expression());
405 Print("%s null)", Token::String(node->op()));
406}
407
408
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000409void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
410 Print("<this-function>");
411}
412
413
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000414const char* PrettyPrinter::Print(AstNode* node) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415 Init();
416 Visit(node);
417 return output_;
418}
419
420
421const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) {
422 Init();
423 ExpressionStatement* statement =
424 program->body()->at(0)->AsExpressionStatement();
425 Visit(statement->expression());
426 return output_;
427}
428
429
430const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) {
431 Init();
432 PrintStatements(program->body());
433 Print("\n");
434 return output_;
435}
436
437
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000438void PrettyPrinter::PrintOut(AstNode* node) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000439 PrettyPrinter printer;
440 PrintF("%s", printer.Print(node));
441}
442
443
444void PrettyPrinter::Init() {
445 if (size_ == 0) {
446 ASSERT(output_ == NULL);
447 const int initial_size = 256;
448 output_ = NewArray<char>(initial_size);
449 size_ = initial_size;
450 }
451 output_[0] = '\0';
452 pos_ = 0;
453}
454
455
456void PrettyPrinter::Print(const char* format, ...) {
457 for (;;) {
458 va_list arguments;
459 va_start(arguments, format);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000460 int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_,
461 format,
462 arguments);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000463 va_end(arguments);
464
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000465 if (n >= 0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000466 // there was enough space - we are done
467 pos_ += n;
468 return;
469 } else {
470 // there was not enough space - allocate more and try again
471 const int slack = 32;
472 int new_size = size_ + (size_ >> 1) + slack;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473 char* new_output = NewArray<char>(new_size);
474 memcpy(new_output, output_, pos_);
475 DeleteArray(output_);
476 output_ = new_output;
477 size_ = new_size;
478 }
479 }
480}
481
482
483void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) {
484 for (int i = 0; i < statements->length(); i++) {
485 if (i != 0) Print(" ");
486 Visit(statements->at(i));
487 }
488}
489
490
491void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
492 if (labels != NULL) {
493 for (int i = 0; i < labels->length(); i++) {
494 PrintLiteral(labels->at(i), false);
495 Print(": ");
496 }
497 }
498}
499
500
501void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
502 Print("(");
503 for (int i = 0; i < arguments->length(); i++) {
504 if (i != 0) Print(", ");
505 Visit(arguments->at(i));
506 }
507 Print(")");
508}
509
510
511void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) {
512 Object* object = *value;
513 if (object->IsString()) {
514 String* string = String::cast(object);
515 if (quote) Print("\"");
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000516 for (int i = 0; i < string->length(); i++) {
517 Print("%c", string->Get(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518 }
519 if (quote) Print("\"");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000520 } else if (object->IsNull()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521 Print("null");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000522 } else if (object->IsTrue()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000523 Print("true");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000524 } else if (object->IsFalse()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525 Print("false");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000526 } else if (object->IsUndefined()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527 Print("undefined");
528 } else if (object->IsNumber()) {
529 Print("%g", object->Number());
530 } else if (object->IsJSObject()) {
531 // regular expression
532 if (object->IsJSFunction()) {
533 Print("JS-Function");
534 } else if (object->IsJSArray()) {
535 Print("JS-array[%u]", JSArray::cast(object)->length());
536 } else if (object->IsJSObject()) {
537 Print("JS-Object");
538 } else {
539 Print("?UNKNOWN?");
540 }
541 } else if (object->IsFixedArray()) {
542 Print("FixedArray");
543 } else {
544 Print("<unknown literal %p>", object);
545 }
546}
547
548
549void PrettyPrinter::PrintParameters(Scope* scope) {
550 Print("(");
551 for (int i = 0; i < scope->num_parameters(); i++) {
552 if (i > 0) Print(", ");
553 PrintLiteral(scope->parameter(i)->name(), false);
554 }
555 Print(")");
556}
557
558
559void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
560 for (int i = 0; i < declarations->length(); i++) {
561 if (i > 0) Print(" ");
562 Visit(declarations->at(i));
563 }
564}
565
566
567void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) {
568 Print("function ");
569 PrintLiteral(function->name(), false);
570 PrintParameters(function->scope());
571 Print(" { ");
572 PrintDeclarations(function->scope()->declarations());
573 PrintStatements(function->body());
574 Print(" }");
575}
576
577
578void PrettyPrinter::PrintCaseClause(CaseClause* clause) {
579 if (clause->is_default()) {
580 Print("default");
581 } else {
582 Print("case ");
583 Visit(clause->label());
584 }
585 Print(": ");
586 PrintStatements(clause->statements());
587 if (clause->statements()->length() > 0)
588 Print(" ");
589}
590
591
592//-----------------------------------------------------------------------------
593
594class IndentedScope BASE_EMBEDDED {
595 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000596 explicit IndentedScope(AstPrinter* printer) : ast_printer_(printer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000597 ast_printer_->inc_indent();
598 }
599
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000600 IndentedScope(AstPrinter* printer, const char* txt, AstNode* node = NULL)
601 : ast_printer_(printer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000602 ast_printer_->PrintIndented(txt);
603 ast_printer_->Print("\n");
604 ast_printer_->inc_indent();
605 }
606
607 virtual ~IndentedScope() {
608 ast_printer_->dec_indent();
609 }
610
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000611 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000612 AstPrinter* ast_printer_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000613};
614
615
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616//-----------------------------------------------------------------------------
617
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000619AstPrinter::AstPrinter() : indent_(0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000620}
621
622
623AstPrinter::~AstPrinter() {
624 ASSERT(indent_ == 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000625}
626
627
628void AstPrinter::PrintIndented(const char* txt) {
629 for (int i = 0; i < indent_; i++) {
kasperl@chromium.org2d18d102009-04-15 13:27:32 +0000630 Print(". ");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631 }
632 Print(txt);
633}
634
635
636void AstPrinter::PrintLiteralIndented(const char* info,
637 Handle<Object> value,
638 bool quote) {
639 PrintIndented(info);
640 Print(" ");
641 PrintLiteral(value, quote);
642 Print("\n");
643}
644
645
646void AstPrinter::PrintLiteralWithModeIndented(const char* info,
647 Variable* var,
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000648 Handle<Object> value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000649 if (var == NULL) {
650 PrintLiteralIndented(info, value, true);
651 } else {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000652 EmbeddedVector<char, 256> buf;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000653 int pos = OS::SNPrintF(buf, "%s (mode = %s", info,
654 Variable::Mode2String(var->mode()));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000655 OS::SNPrintF(buf + pos, ")");
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000656 PrintLiteralIndented(buf.start(), value, true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000657 }
658}
659
660
661void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) {
662 if (labels != NULL && labels->length() > 0) {
663 if (info == NULL) {
664 PrintIndented("LABELS ");
665 } else {
666 PrintIndented(info);
667 Print(" ");
668 }
669 PrintLabels(labels);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000670 } else if (info != NULL) {
671 PrintIndented(info);
672 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000673 Print("\n");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674}
675
676
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000677void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000678 IndentedScope indent(this, s, node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000679 Visit(node);
680}
681
682
683const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
684 Init();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000685 { IndentedScope indent(this, "FUNC");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000686 PrintLiteralIndented("NAME", program->name(), true);
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000687 PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000688 PrintParameters(program->scope());
689 PrintDeclarations(program->scope()->declarations());
690 PrintStatements(program->body());
691 }
692 return Output();
693}
694
695
696void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) {
697 if (declarations->length() > 0) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000698 IndentedScope indent(this, "DECLS");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000699 for (int i = 0; i < declarations->length(); i++) {
700 Visit(declarations->at(i));
701 }
702 }
703}
704
705
706void AstPrinter::PrintParameters(Scope* scope) {
707 if (scope->num_parameters() > 0) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000708 IndentedScope indent(this, "PARAMS");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709 for (int i = 0; i < scope->num_parameters(); i++) {
kasperl@chromium.org2d18d102009-04-15 13:27:32 +0000710 PrintLiteralWithModeIndented("VAR", scope->parameter(i),
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000711 scope->parameter(i)->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000712 }
713 }
714}
715
716
717void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) {
718 for (int i = 0; i < statements->length(); i++) {
719 Visit(statements->at(i));
720 }
721}
722
723
724void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) {
725 for (int i = 0; i < arguments->length(); i++) {
726 Visit(arguments->at(i));
727 }
728}
729
730
731void AstPrinter::PrintCaseClause(CaseClause* clause) {
732 if (clause->is_default()) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000733 IndentedScope indent(this, "DEFAULT");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000734 PrintStatements(clause->statements());
735 } else {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000736 IndentedScope indent(this, "CASE");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737 Visit(clause->label());
738 PrintStatements(clause->statements());
739 }
740}
741
742
743void AstPrinter::VisitBlock(Block* node) {
744 const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK";
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000745 IndentedScope indent(this, block_txt);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000746 PrintStatements(node->statements());
747}
748
749
750void AstPrinter::VisitDeclaration(Declaration* node) {
751 if (node->fun() == NULL) {
752 // var or const declarations
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000753 PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
754 node->proxy()->AsVariable(),
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000755 node->proxy()->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756 } else {
757 // function declarations
758 PrintIndented("FUNCTION ");
759 PrintLiteral(node->proxy()->name(), true);
760 Print(" = function ");
761 PrintLiteral(node->fun()->name(), false);
762 Print("\n");
763 }
764}
765
766
767void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) {
768 Visit(node->expression());
769}
770
771
772void AstPrinter::VisitEmptyStatement(EmptyStatement* node) {
773 PrintIndented("EMPTY\n");
774}
775
776
777void AstPrinter::VisitIfStatement(IfStatement* node) {
778 PrintIndentedVisit("IF", node->condition());
779 PrintIndentedVisit("THEN", node->then_statement());
780 if (node->HasElseStatement()) {
781 PrintIndentedVisit("ELSE", node->else_statement());
782 }
783}
784
785
786void AstPrinter::VisitContinueStatement(ContinueStatement* node) {
787 PrintLabelsIndented("CONTINUE", node->target()->labels());
788}
789
790
791void AstPrinter::VisitBreakStatement(BreakStatement* node) {
792 PrintLabelsIndented("BREAK", node->target()->labels());
793}
794
795
796void AstPrinter::VisitReturnStatement(ReturnStatement* node) {
797 PrintIndentedVisit("RETURN", node->expression());
798}
799
800
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000801void AstPrinter::VisitEnterWithContextStatement(
802 EnterWithContextStatement* node) {
803 PrintIndentedVisit("ENTER WITH CONTEXT", node->expression());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000804}
805
806
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000807void AstPrinter::VisitExitContextStatement(ExitContextStatement* node) {
808 PrintIndented("EXIT CONTEXT\n");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000809}
810
811
812void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000813 IndentedScope indent(this, "SWITCH");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000814 PrintLabelsIndented(NULL, node->labels());
815 PrintIndentedVisit("TAG", node->tag());
816 for (int i = 0; i < node->cases()->length(); i++) {
817 PrintCaseClause(node->cases()->at(i));
818 }
819}
820
821
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000822void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000823 IndentedScope indent(this, "DO");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000824 PrintLabelsIndented(NULL, node->labels());
825 PrintIndentedVisit("BODY", node->body());
826 PrintIndentedVisit("COND", node->cond());
827}
828
829
830void AstPrinter::VisitWhileStatement(WhileStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000831 IndentedScope indent(this, "WHILE");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000832 PrintLabelsIndented(NULL, node->labels());
833 PrintIndentedVisit("COND", node->cond());
834 PrintIndentedVisit("BODY", node->body());
835}
836
837
838void AstPrinter::VisitForStatement(ForStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000839 IndentedScope indent(this, "FOR");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000840 PrintLabelsIndented(NULL, node->labels());
841 if (node->init()) PrintIndentedVisit("INIT", node->init());
842 if (node->cond()) PrintIndentedVisit("COND", node->cond());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000843 PrintIndentedVisit("BODY", node->body());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844 if (node->next()) PrintIndentedVisit("NEXT", node->next());
845}
846
847
848void AstPrinter::VisitForInStatement(ForInStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000849 IndentedScope indent(this, "FOR IN");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000850 PrintIndentedVisit("FOR", node->each());
851 PrintIndentedVisit("IN", node->enumerable());
852 PrintIndentedVisit("BODY", node->body());
853}
854
855
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000856void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000857 IndentedScope indent(this, "TRY CATCH");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000858 PrintIndentedVisit("TRY", node->try_block());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000859 const bool quote = false;
860 PrintLiteralIndented("CATCHVAR", node->name(), quote);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000861 PrintIndentedVisit("CATCH", node->catch_block());
862}
863
864
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000865void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000866 IndentedScope indent(this, "TRY FINALLY");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000867 PrintIndentedVisit("TRY", node->try_block());
868 PrintIndentedVisit("FINALLY", node->finally_block());
869}
870
871
872void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000873 IndentedScope indent(this, "DEBUGGER");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874}
875
876
877void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000878 IndentedScope indent(this, "FUNC LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000879 PrintLiteralIndented("NAME", node->name(), false);
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000880 PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000881 PrintParameters(node->scope());
882 // We don't want to see the function literal in this case: it
883 // will be printed via PrintProgram when the code for it is
884 // generated.
885 // PrintStatements(node->body());
886}
887
888
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000889void AstPrinter::VisitSharedFunctionInfoLiteral(
890 SharedFunctionInfoLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000891 IndentedScope indent(this, "FUNC LITERAL");
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000892 PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893}
894
895
896void AstPrinter::VisitConditional(Conditional* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000897 IndentedScope indent(this, "CONDITIONAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000898 PrintIndentedVisit("?", node->condition());
899 PrintIndentedVisit("THEN", node->then_expression());
900 PrintIndentedVisit("ELSE", node->else_expression());
901}
902
903
904void AstPrinter::VisitLiteral(Literal* node) {
905 PrintLiteralIndented("LITERAL", node->handle(), true);
906}
907
908
909void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000910 IndentedScope indent(this, "REGEXP LITERAL");
ager@chromium.orge2902be2009-06-08 12:21:35 +0000911 PrintLiteralIndented("PATTERN", node->pattern(), false);
912 PrintLiteralIndented("FLAGS", node->flags(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000913}
914
915
916void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000917 IndentedScope indent(this, "OBJ LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000918 for (int i = 0; i < node->properties()->length(); i++) {
919 const char* prop_kind = NULL;
920 switch (node->properties()->at(i)->kind()) {
921 case ObjectLiteral::Property::CONSTANT:
922 prop_kind = "PROPERTY - CONSTANT";
923 break;
924 case ObjectLiteral::Property::COMPUTED:
925 prop_kind = "PROPERTY - COMPUTED";
926 break;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000927 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
928 prop_kind = "PROPERTY - MATERIALIZED_LITERAL";
929 break;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000930 case ObjectLiteral::Property::PROTOTYPE:
931 prop_kind = "PROPERTY - PROTOTYPE";
932 break;
933 case ObjectLiteral::Property::GETTER:
934 prop_kind = "PROPERTY - GETTER";
935 break;
936 case ObjectLiteral::Property::SETTER:
937 prop_kind = "PROPERTY - SETTER";
938 break;
939 default:
940 UNREACHABLE();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000941 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000942 IndentedScope prop(this, prop_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000943 PrintIndentedVisit("KEY", node->properties()->at(i)->key());
944 PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
945 }
946}
947
948
949void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000950 IndentedScope indent(this, "ARRAY LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000951 if (node->values()->length() > 0) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000952 IndentedScope indent(this, "VALUES");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000953 for (int i = 0; i < node->values()->length(); i++) {
954 Visit(node->values()->at(i));
955 }
956 }
957}
958
959
960void AstPrinter::VisitSlot(Slot* node) {
961 PrintIndented("SLOT ");
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000962 PrettyPrinter::VisitSlot(node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000963 Print("\n");
964}
965
966
967void AstPrinter::VisitVariableProxy(VariableProxy* node) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000968 PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000969 Variable* var = node->var();
970 if (var != NULL && var->rewrite() != NULL) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000971 IndentedScope indent(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000972 Visit(var->rewrite());
973 }
974}
975
976
977void AstPrinter::VisitAssignment(Assignment* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000978 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000979 Visit(node->target());
980 Visit(node->value());
981}
982
983
984void AstPrinter::VisitThrow(Throw* node) {
985 PrintIndentedVisit("THROW", node->exception());
986}
987
988
989void AstPrinter::VisitProperty(Property* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000990 IndentedScope indent(this, "PROPERTY", node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000991 Visit(node->obj());
992 Literal* literal = node->key()->AsLiteral();
993 if (literal != NULL && literal->handle()->IsSymbol()) {
kasperl@chromium.org2d18d102009-04-15 13:27:32 +0000994 PrintLiteralIndented("NAME", literal->handle(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000995 } else {
996 PrintIndentedVisit("KEY", node->key());
997 }
998}
999
1000
1001void AstPrinter::VisitCall(Call* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001002 IndentedScope indent(this, "CALL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001003 Visit(node->expression());
1004 PrintArguments(node->arguments());
1005}
1006
1007
1008void AstPrinter::VisitCallNew(CallNew* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001009 IndentedScope indent(this, "CALL NEW");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001010 Visit(node->expression());
1011 PrintArguments(node->arguments());
1012}
1013
1014
1015void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1016 PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001017 IndentedScope indent(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001018 PrintArguments(node->arguments());
1019}
1020
1021
1022void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1023 PrintIndentedVisit(Token::Name(node->op()), node->expression());
1024}
1025
1026
1027void AstPrinter::VisitCountOperation(CountOperation* node) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001028 EmbeddedVector<char, 128> buf;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001029 OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1030 Token::Name(node->op()));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001031 PrintIndentedVisit(buf.start(), node->expression());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001032}
1033
1034
1035void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001036 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001037 Visit(node->left());
1038 Visit(node->right());
1039}
1040
1041
1042void AstPrinter::VisitCompareOperation(CompareOperation* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001043 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001044 Visit(node->left());
1045 Visit(node->right());
1046}
1047
1048
ricow@chromium.org65fae842010-08-25 15:26:24 +00001049void AstPrinter::VisitCompareToNull(CompareToNull* node) {
1050 const char* name = node->is_strict()
1051 ? "COMPARE-TO-NULL-STRICT"
1052 : "COMPARE-TO-NULL";
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001053 IndentedScope indent(this, name, node);
ricow@chromium.org65fae842010-08-25 15:26:24 +00001054 Visit(node->expression());
1055}
1056
1057
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001058void AstPrinter::VisitThisFunction(ThisFunction* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001059 IndentedScope indent(this, "THIS-FUNCTION");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001060}
1061
1062
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001063TagScope::TagScope(JsonAstBuilder* builder, const char* name)
1064 : builder_(builder), next_(builder->tag()), has_body_(false) {
1065 if (next_ != NULL) {
1066 next_->use();
1067 builder->Print(",\n");
1068 }
1069 builder->set_tag(this);
1070 builder->PrintIndented("[");
1071 builder->Print("\"%s\"", name);
1072 builder->increase_indent(JsonAstBuilder::kTagIndentSize);
1073}
1074
1075
1076TagScope::~TagScope() {
1077 builder_->decrease_indent(JsonAstBuilder::kTagIndentSize);
1078 if (has_body_) {
1079 builder_->Print("\n");
1080 builder_->PrintIndented("]");
1081 } else {
1082 builder_->Print("]");
1083 }
1084 builder_->set_tag(next_);
1085}
1086
1087
1088AttributesScope::AttributesScope(JsonAstBuilder* builder)
1089 : builder_(builder), attribute_count_(0) {
1090 builder->set_attributes(this);
1091 builder->tag()->use();
1092 builder->Print(",\n");
1093 builder->PrintIndented("{");
1094 builder->increase_indent(JsonAstBuilder::kAttributesIndentSize);
1095}
1096
1097
1098AttributesScope::~AttributesScope() {
1099 builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize);
1100 if (attribute_count_ > 1) {
1101 builder_->Print("\n");
1102 builder_->PrintIndented("}");
1103 } else {
1104 builder_->Print("}");
1105 }
1106 builder_->set_attributes(NULL);
1107}
1108
1109
1110const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) {
1111 Init();
1112 Visit(program);
1113 Print("\n");
1114 return Output();
1115}
1116
1117
1118void JsonAstBuilder::AddAttributePrefix(const char* name) {
1119 if (attributes()->is_used()) {
1120 Print(",\n");
1121 PrintIndented("\"");
1122 } else {
1123 Print("\"");
1124 }
1125 Print("%s\":", name);
1126 attributes()->use();
1127}
1128
1129
1130void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) {
1131 SmartPointer<char> value_string = value->ToCString();
1132 AddAttributePrefix(name);
1133 Print("\"%s\"", *value_string);
1134}
1135
1136
1137void JsonAstBuilder::AddAttribute(const char* name, const char* value) {
1138 AddAttributePrefix(name);
1139 Print("\"%s\"", value);
1140}
1141
1142
1143void JsonAstBuilder::AddAttribute(const char* name, int value) {
1144 AddAttributePrefix(name);
1145 Print("%d", value);
1146}
1147
1148
1149void JsonAstBuilder::AddAttribute(const char* name, bool value) {
1150 AddAttributePrefix(name);
1151 Print(value ? "true" : "false");
1152}
1153
1154
1155void JsonAstBuilder::VisitBlock(Block* stmt) {
1156 TagScope tag(this, "Block");
1157 VisitStatements(stmt->statements());
1158}
1159
1160
1161void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1162 TagScope tag(this, "ExpressionStatement");
1163 Visit(stmt->expression());
1164}
1165
1166
1167void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1168 TagScope tag(this, "EmptyStatement");
1169}
1170
1171
1172void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) {
1173 TagScope tag(this, "IfStatement");
1174 Visit(stmt->condition());
1175 Visit(stmt->then_statement());
1176 Visit(stmt->else_statement());
1177}
1178
1179
1180void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) {
1181 TagScope tag(this, "ContinueStatement");
1182}
1183
1184
1185void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) {
1186 TagScope tag(this, "BreakStatement");
1187}
1188
1189
1190void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1191 TagScope tag(this, "ReturnStatement");
1192 Visit(stmt->expression());
1193}
1194
1195
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001196void JsonAstBuilder::VisitEnterWithContextStatement(
1197 EnterWithContextStatement* stmt) {
1198 TagScope tag(this, "EnterWithContextStatement");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001199 Visit(stmt->expression());
1200}
1201
1202
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001203void JsonAstBuilder::VisitExitContextStatement(ExitContextStatement* stmt) {
1204 TagScope tag(this, "ExitContextStatement");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001205}
1206
1207
1208void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1209 TagScope tag(this, "SwitchStatement");
1210}
1211
1212
1213void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1214 TagScope tag(this, "DoWhileStatement");
1215 Visit(stmt->body());
1216 Visit(stmt->cond());
1217}
1218
1219
1220void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) {
1221 TagScope tag(this, "WhileStatement");
1222 Visit(stmt->cond());
1223 Visit(stmt->body());
1224}
1225
1226
1227void JsonAstBuilder::VisitForStatement(ForStatement* stmt) {
1228 TagScope tag(this, "ForStatement");
1229 if (stmt->init() != NULL) Visit(stmt->init());
1230 if (stmt->cond() != NULL) Visit(stmt->cond());
1231 Visit(stmt->body());
1232 if (stmt->next() != NULL) Visit(stmt->next());
1233}
1234
1235
1236void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) {
1237 TagScope tag(this, "ForInStatement");
1238 Visit(stmt->each());
1239 Visit(stmt->enumerable());
1240 Visit(stmt->body());
1241}
1242
1243
1244void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1245 TagScope tag(this, "TryCatchStatement");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001246 { AttributesScope attributes(this);
1247 AddAttribute("variable", stmt->name());
1248 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001249 Visit(stmt->try_block());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001250 Visit(stmt->catch_block());
1251}
1252
1253
1254void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1255 TagScope tag(this, "TryFinallyStatement");
1256 Visit(stmt->try_block());
1257 Visit(stmt->finally_block());
1258}
1259
1260
1261void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1262 TagScope tag(this, "DebuggerStatement");
1263}
1264
1265
1266void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
1267 TagScope tag(this, "FunctionLiteral");
1268 {
1269 AttributesScope attributes(this);
1270 AddAttribute("name", expr->name());
1271 }
1272 VisitDeclarations(expr->scope()->declarations());
1273 VisitStatements(expr->body());
1274}
1275
1276
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001277void JsonAstBuilder::VisitSharedFunctionInfoLiteral(
1278 SharedFunctionInfoLiteral* expr) {
1279 TagScope tag(this, "SharedFunctionInfoLiteral");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001280}
1281
1282
1283void JsonAstBuilder::VisitConditional(Conditional* expr) {
1284 TagScope tag(this, "Conditional");
1285}
1286
1287
1288void JsonAstBuilder::VisitSlot(Slot* expr) {
1289 TagScope tag(this, "Slot");
1290 {
1291 AttributesScope attributes(this);
1292 switch (expr->type()) {
1293 case Slot::PARAMETER:
1294 AddAttribute("type", "PARAMETER");
1295 break;
1296 case Slot::LOCAL:
1297 AddAttribute("type", "LOCAL");
1298 break;
1299 case Slot::CONTEXT:
1300 AddAttribute("type", "CONTEXT");
1301 break;
1302 case Slot::LOOKUP:
1303 AddAttribute("type", "LOOKUP");
1304 break;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001305 }
1306 AddAttribute("index", expr->index());
1307 }
1308}
1309
1310
1311void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
1312 if (expr->var()->rewrite() == NULL) {
1313 TagScope tag(this, "VariableProxy");
1314 {
1315 AttributesScope attributes(this);
1316 AddAttribute("name", expr->name());
1317 AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
1318 }
1319 } else {
1320 Visit(expr->var()->rewrite());
1321 }
1322}
1323
1324
1325void JsonAstBuilder::VisitLiteral(Literal* expr) {
1326 TagScope tag(this, "Literal");
1327 {
1328 AttributesScope attributes(this);
1329 Handle<Object> handle = expr->handle();
1330 if (handle->IsString()) {
1331 AddAttribute("handle", Handle<String>(String::cast(*handle)));
1332 } else if (handle->IsSmi()) {
1333 AddAttribute("handle", Smi::cast(*handle)->value());
1334 }
1335 }
1336}
1337
1338
1339void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1340 TagScope tag(this, "RegExpLiteral");
1341}
1342
1343
1344void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1345 TagScope tag(this, "ObjectLiteral");
1346}
1347
1348
1349void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1350 TagScope tag(this, "ArrayLiteral");
1351}
1352
1353
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001354void JsonAstBuilder::VisitAssignment(Assignment* expr) {
1355 TagScope tag(this, "Assignment");
1356 {
1357 AttributesScope attributes(this);
1358 AddAttribute("op", Token::Name(expr->op()));
1359 }
1360 Visit(expr->target());
1361 Visit(expr->value());
1362}
1363
1364
1365void JsonAstBuilder::VisitThrow(Throw* expr) {
1366 TagScope tag(this, "Throw");
1367 Visit(expr->exception());
1368}
1369
1370
1371void JsonAstBuilder::VisitProperty(Property* expr) {
1372 TagScope tag(this, "Property");
1373 {
1374 AttributesScope attributes(this);
1375 AddAttribute("type", expr->is_synthetic() ? "SYNTHETIC" : "NORMAL");
1376 }
1377 Visit(expr->obj());
1378 Visit(expr->key());
1379}
1380
1381
1382void JsonAstBuilder::VisitCall(Call* expr) {
1383 TagScope tag(this, "Call");
1384 Visit(expr->expression());
1385 VisitExpressions(expr->arguments());
1386}
1387
1388
1389void JsonAstBuilder::VisitCallNew(CallNew* expr) {
1390 TagScope tag(this, "CallNew");
1391 Visit(expr->expression());
1392 VisitExpressions(expr->arguments());
1393}
1394
1395
1396void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) {
1397 TagScope tag(this, "CallRuntime");
1398 {
1399 AttributesScope attributes(this);
1400 AddAttribute("name", expr->name());
1401 }
1402 VisitExpressions(expr->arguments());
1403}
1404
1405
1406void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) {
1407 TagScope tag(this, "UnaryOperation");
1408 {
1409 AttributesScope attributes(this);
1410 AddAttribute("op", Token::Name(expr->op()));
1411 }
1412 Visit(expr->expression());
1413}
1414
1415
1416void JsonAstBuilder::VisitCountOperation(CountOperation* expr) {
1417 TagScope tag(this, "CountOperation");
1418 {
1419 AttributesScope attributes(this);
1420 AddAttribute("is_prefix", expr->is_prefix());
1421 AddAttribute("op", Token::Name(expr->op()));
1422 }
1423 Visit(expr->expression());
1424}
1425
1426
1427void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) {
1428 TagScope tag(this, "BinaryOperation");
1429 {
1430 AttributesScope attributes(this);
1431 AddAttribute("op", Token::Name(expr->op()));
1432 }
1433 Visit(expr->left());
1434 Visit(expr->right());
1435}
1436
1437
1438void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) {
1439 TagScope tag(this, "CompareOperation");
1440 {
1441 AttributesScope attributes(this);
1442 AddAttribute("op", Token::Name(expr->op()));
1443 }
1444 Visit(expr->left());
1445 Visit(expr->right());
1446}
1447
1448
ricow@chromium.org65fae842010-08-25 15:26:24 +00001449void JsonAstBuilder::VisitCompareToNull(CompareToNull* expr) {
1450 TagScope tag(this, "CompareToNull");
1451 {
1452 AttributesScope attributes(this);
1453 AddAttribute("is_strict", expr->is_strict());
1454 }
1455 Visit(expr->expression());
1456}
1457
1458
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001459void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) {
1460 TagScope tag(this, "ThisFunction");
1461}
1462
1463
1464void JsonAstBuilder::VisitDeclaration(Declaration* decl) {
1465 TagScope tag(this, "Declaration");
1466 {
1467 AttributesScope attributes(this);
1468 AddAttribute("mode", Variable::Mode2String(decl->mode()));
1469 }
1470 Visit(decl->proxy());
1471 if (decl->fun() != NULL) Visit(decl->fun());
1472}
1473
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001474
1475#endif // DEBUG
1476
1477} } // namespace v8::internal