blob: b03429341e3817ed0a4c85af813b858b07ef7836 [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
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000126void PrettyPrinter::VisitWithStatement(WithStatement* node) {
127 Print("with (");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128 Visit(node->expression());
129 Print(") ");
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000130 Visit(node->statement());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131}
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;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000206 PrintLiteral(node->variable()->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
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000801void AstPrinter::VisitWithStatement(WithStatement* node) {
802 IndentedScope indent(this, "WITH");
803 PrintIndentedVisit("OBJECT", node->expression());
804 PrintIndentedVisit("BODY", node->statement());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805}
806
807
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000808void AstPrinter::VisitExitContextStatement(ExitContextStatement* node) {
809 PrintIndented("EXIT CONTEXT\n");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000810}
811
812
813void AstPrinter::VisitSwitchStatement(SwitchStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000814 IndentedScope indent(this, "SWITCH");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815 PrintLabelsIndented(NULL, node->labels());
816 PrintIndentedVisit("TAG", node->tag());
817 for (int i = 0; i < node->cases()->length(); i++) {
818 PrintCaseClause(node->cases()->at(i));
819 }
820}
821
822
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000823void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000824 IndentedScope indent(this, "DO");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000825 PrintLabelsIndented(NULL, node->labels());
826 PrintIndentedVisit("BODY", node->body());
827 PrintIndentedVisit("COND", node->cond());
828}
829
830
831void AstPrinter::VisitWhileStatement(WhileStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000832 IndentedScope indent(this, "WHILE");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000833 PrintLabelsIndented(NULL, node->labels());
834 PrintIndentedVisit("COND", node->cond());
835 PrintIndentedVisit("BODY", node->body());
836}
837
838
839void AstPrinter::VisitForStatement(ForStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000840 IndentedScope indent(this, "FOR");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000841 PrintLabelsIndented(NULL, node->labels());
842 if (node->init()) PrintIndentedVisit("INIT", node->init());
843 if (node->cond()) PrintIndentedVisit("COND", node->cond());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000844 PrintIndentedVisit("BODY", node->body());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000845 if (node->next()) PrintIndentedVisit("NEXT", node->next());
846}
847
848
849void AstPrinter::VisitForInStatement(ForInStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000850 IndentedScope indent(this, "FOR IN");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000851 PrintIndentedVisit("FOR", node->each());
852 PrintIndentedVisit("IN", node->enumerable());
853 PrintIndentedVisit("BODY", node->body());
854}
855
856
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000857void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000858 IndentedScope indent(this, "TRY CATCH");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000859 PrintIndentedVisit("TRY", node->try_block());
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000860 PrintLiteralWithModeIndented("CATCHVAR",
861 node->variable(),
862 node->variable()->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000863 PrintIndentedVisit("CATCH", node->catch_block());
864}
865
866
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000867void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000868 IndentedScope indent(this, "TRY FINALLY");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000869 PrintIndentedVisit("TRY", node->try_block());
870 PrintIndentedVisit("FINALLY", node->finally_block());
871}
872
873
874void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000875 IndentedScope indent(this, "DEBUGGER");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000876}
877
878
879void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000880 IndentedScope indent(this, "FUNC LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000881 PrintLiteralIndented("NAME", node->name(), false);
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000882 PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000883 PrintParameters(node->scope());
884 // We don't want to see the function literal in this case: it
885 // will be printed via PrintProgram when the code for it is
886 // generated.
887 // PrintStatements(node->body());
888}
889
890
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000891void AstPrinter::VisitSharedFunctionInfoLiteral(
892 SharedFunctionInfoLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000893 IndentedScope indent(this, "FUNC LITERAL");
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000894 PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000895}
896
897
898void AstPrinter::VisitConditional(Conditional* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000899 IndentedScope indent(this, "CONDITIONAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000900 PrintIndentedVisit("?", node->condition());
901 PrintIndentedVisit("THEN", node->then_expression());
902 PrintIndentedVisit("ELSE", node->else_expression());
903}
904
905
906void AstPrinter::VisitLiteral(Literal* node) {
907 PrintLiteralIndented("LITERAL", node->handle(), true);
908}
909
910
911void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000912 IndentedScope indent(this, "REGEXP LITERAL");
ager@chromium.orge2902be2009-06-08 12:21:35 +0000913 PrintLiteralIndented("PATTERN", node->pattern(), false);
914 PrintLiteralIndented("FLAGS", node->flags(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000915}
916
917
918void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000919 IndentedScope indent(this, "OBJ LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000920 for (int i = 0; i < node->properties()->length(); i++) {
921 const char* prop_kind = NULL;
922 switch (node->properties()->at(i)->kind()) {
923 case ObjectLiteral::Property::CONSTANT:
924 prop_kind = "PROPERTY - CONSTANT";
925 break;
926 case ObjectLiteral::Property::COMPUTED:
927 prop_kind = "PROPERTY - COMPUTED";
928 break;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000929 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
930 prop_kind = "PROPERTY - MATERIALIZED_LITERAL";
931 break;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000932 case ObjectLiteral::Property::PROTOTYPE:
933 prop_kind = "PROPERTY - PROTOTYPE";
934 break;
935 case ObjectLiteral::Property::GETTER:
936 prop_kind = "PROPERTY - GETTER";
937 break;
938 case ObjectLiteral::Property::SETTER:
939 prop_kind = "PROPERTY - SETTER";
940 break;
941 default:
942 UNREACHABLE();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000943 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000944 IndentedScope prop(this, prop_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000945 PrintIndentedVisit("KEY", node->properties()->at(i)->key());
946 PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
947 }
948}
949
950
951void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000952 IndentedScope indent(this, "ARRAY LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000953 if (node->values()->length() > 0) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000954 IndentedScope indent(this, "VALUES");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000955 for (int i = 0; i < node->values()->length(); i++) {
956 Visit(node->values()->at(i));
957 }
958 }
959}
960
961
962void AstPrinter::VisitSlot(Slot* node) {
963 PrintIndented("SLOT ");
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000964 PrettyPrinter::VisitSlot(node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000965 Print("\n");
966}
967
968
969void AstPrinter::VisitVariableProxy(VariableProxy* node) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000970 PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000971 Variable* var = node->var();
972 if (var != NULL && var->rewrite() != NULL) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000973 IndentedScope indent(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000974 Visit(var->rewrite());
975 }
976}
977
978
979void AstPrinter::VisitAssignment(Assignment* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000980 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000981 Visit(node->target());
982 Visit(node->value());
983}
984
985
986void AstPrinter::VisitThrow(Throw* node) {
987 PrintIndentedVisit("THROW", node->exception());
988}
989
990
991void AstPrinter::VisitProperty(Property* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000992 IndentedScope indent(this, "PROPERTY", node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000993 Visit(node->obj());
994 Literal* literal = node->key()->AsLiteral();
995 if (literal != NULL && literal->handle()->IsSymbol()) {
kasperl@chromium.org2d18d102009-04-15 13:27:32 +0000996 PrintLiteralIndented("NAME", literal->handle(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000997 } else {
998 PrintIndentedVisit("KEY", node->key());
999 }
1000}
1001
1002
1003void AstPrinter::VisitCall(Call* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001004 IndentedScope indent(this, "CALL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001005 Visit(node->expression());
1006 PrintArguments(node->arguments());
1007}
1008
1009
1010void AstPrinter::VisitCallNew(CallNew* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001011 IndentedScope indent(this, "CALL NEW");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001012 Visit(node->expression());
1013 PrintArguments(node->arguments());
1014}
1015
1016
1017void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1018 PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001019 IndentedScope indent(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001020 PrintArguments(node->arguments());
1021}
1022
1023
1024void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1025 PrintIndentedVisit(Token::Name(node->op()), node->expression());
1026}
1027
1028
1029void AstPrinter::VisitCountOperation(CountOperation* node) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001030 EmbeddedVector<char, 128> buf;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001031 OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1032 Token::Name(node->op()));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001033 PrintIndentedVisit(buf.start(), node->expression());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034}
1035
1036
1037void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001038 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001039 Visit(node->left());
1040 Visit(node->right());
1041}
1042
1043
1044void AstPrinter::VisitCompareOperation(CompareOperation* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001045 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001046 Visit(node->left());
1047 Visit(node->right());
1048}
1049
1050
ricow@chromium.org65fae842010-08-25 15:26:24 +00001051void AstPrinter::VisitCompareToNull(CompareToNull* node) {
1052 const char* name = node->is_strict()
1053 ? "COMPARE-TO-NULL-STRICT"
1054 : "COMPARE-TO-NULL";
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001055 IndentedScope indent(this, name, node);
ricow@chromium.org65fae842010-08-25 15:26:24 +00001056 Visit(node->expression());
1057}
1058
1059
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001060void AstPrinter::VisitThisFunction(ThisFunction* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001061 IndentedScope indent(this, "THIS-FUNCTION");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001062}
1063
1064
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001065TagScope::TagScope(JsonAstBuilder* builder, const char* name)
1066 : builder_(builder), next_(builder->tag()), has_body_(false) {
1067 if (next_ != NULL) {
1068 next_->use();
1069 builder->Print(",\n");
1070 }
1071 builder->set_tag(this);
1072 builder->PrintIndented("[");
1073 builder->Print("\"%s\"", name);
1074 builder->increase_indent(JsonAstBuilder::kTagIndentSize);
1075}
1076
1077
1078TagScope::~TagScope() {
1079 builder_->decrease_indent(JsonAstBuilder::kTagIndentSize);
1080 if (has_body_) {
1081 builder_->Print("\n");
1082 builder_->PrintIndented("]");
1083 } else {
1084 builder_->Print("]");
1085 }
1086 builder_->set_tag(next_);
1087}
1088
1089
1090AttributesScope::AttributesScope(JsonAstBuilder* builder)
1091 : builder_(builder), attribute_count_(0) {
1092 builder->set_attributes(this);
1093 builder->tag()->use();
1094 builder->Print(",\n");
1095 builder->PrintIndented("{");
1096 builder->increase_indent(JsonAstBuilder::kAttributesIndentSize);
1097}
1098
1099
1100AttributesScope::~AttributesScope() {
1101 builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize);
1102 if (attribute_count_ > 1) {
1103 builder_->Print("\n");
1104 builder_->PrintIndented("}");
1105 } else {
1106 builder_->Print("}");
1107 }
1108 builder_->set_attributes(NULL);
1109}
1110
1111
1112const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) {
1113 Init();
1114 Visit(program);
1115 Print("\n");
1116 return Output();
1117}
1118
1119
1120void JsonAstBuilder::AddAttributePrefix(const char* name) {
1121 if (attributes()->is_used()) {
1122 Print(",\n");
1123 PrintIndented("\"");
1124 } else {
1125 Print("\"");
1126 }
1127 Print("%s\":", name);
1128 attributes()->use();
1129}
1130
1131
1132void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) {
1133 SmartPointer<char> value_string = value->ToCString();
1134 AddAttributePrefix(name);
1135 Print("\"%s\"", *value_string);
1136}
1137
1138
1139void JsonAstBuilder::AddAttribute(const char* name, const char* value) {
1140 AddAttributePrefix(name);
1141 Print("\"%s\"", value);
1142}
1143
1144
1145void JsonAstBuilder::AddAttribute(const char* name, int value) {
1146 AddAttributePrefix(name);
1147 Print("%d", value);
1148}
1149
1150
1151void JsonAstBuilder::AddAttribute(const char* name, bool value) {
1152 AddAttributePrefix(name);
1153 Print(value ? "true" : "false");
1154}
1155
1156
1157void JsonAstBuilder::VisitBlock(Block* stmt) {
1158 TagScope tag(this, "Block");
1159 VisitStatements(stmt->statements());
1160}
1161
1162
1163void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1164 TagScope tag(this, "ExpressionStatement");
1165 Visit(stmt->expression());
1166}
1167
1168
1169void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1170 TagScope tag(this, "EmptyStatement");
1171}
1172
1173
1174void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) {
1175 TagScope tag(this, "IfStatement");
1176 Visit(stmt->condition());
1177 Visit(stmt->then_statement());
1178 Visit(stmt->else_statement());
1179}
1180
1181
1182void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) {
1183 TagScope tag(this, "ContinueStatement");
1184}
1185
1186
1187void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) {
1188 TagScope tag(this, "BreakStatement");
1189}
1190
1191
1192void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1193 TagScope tag(this, "ReturnStatement");
1194 Visit(stmt->expression());
1195}
1196
1197
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001198void JsonAstBuilder::VisitWithStatement(WithStatement* stmt) {
1199 TagScope tag(this, "WithStatement");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001200 Visit(stmt->expression());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001201 Visit(stmt->statement());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001202}
1203
1204
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001205void JsonAstBuilder::VisitExitContextStatement(ExitContextStatement* stmt) {
1206 TagScope tag(this, "ExitContextStatement");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001207}
1208
1209
1210void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1211 TagScope tag(this, "SwitchStatement");
1212}
1213
1214
1215void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1216 TagScope tag(this, "DoWhileStatement");
1217 Visit(stmt->body());
1218 Visit(stmt->cond());
1219}
1220
1221
1222void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) {
1223 TagScope tag(this, "WhileStatement");
1224 Visit(stmt->cond());
1225 Visit(stmt->body());
1226}
1227
1228
1229void JsonAstBuilder::VisitForStatement(ForStatement* stmt) {
1230 TagScope tag(this, "ForStatement");
1231 if (stmt->init() != NULL) Visit(stmt->init());
1232 if (stmt->cond() != NULL) Visit(stmt->cond());
1233 Visit(stmt->body());
1234 if (stmt->next() != NULL) Visit(stmt->next());
1235}
1236
1237
1238void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) {
1239 TagScope tag(this, "ForInStatement");
1240 Visit(stmt->each());
1241 Visit(stmt->enumerable());
1242 Visit(stmt->body());
1243}
1244
1245
1246void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1247 TagScope tag(this, "TryCatchStatement");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001248 { AttributesScope attributes(this);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001249 AddAttribute("variable", stmt->variable()->name());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001250 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001251 Visit(stmt->try_block());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001252 Visit(stmt->catch_block());
1253}
1254
1255
1256void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1257 TagScope tag(this, "TryFinallyStatement");
1258 Visit(stmt->try_block());
1259 Visit(stmt->finally_block());
1260}
1261
1262
1263void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1264 TagScope tag(this, "DebuggerStatement");
1265}
1266
1267
1268void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
1269 TagScope tag(this, "FunctionLiteral");
1270 {
1271 AttributesScope attributes(this);
1272 AddAttribute("name", expr->name());
1273 }
1274 VisitDeclarations(expr->scope()->declarations());
1275 VisitStatements(expr->body());
1276}
1277
1278
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001279void JsonAstBuilder::VisitSharedFunctionInfoLiteral(
1280 SharedFunctionInfoLiteral* expr) {
1281 TagScope tag(this, "SharedFunctionInfoLiteral");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001282}
1283
1284
1285void JsonAstBuilder::VisitConditional(Conditional* expr) {
1286 TagScope tag(this, "Conditional");
1287}
1288
1289
1290void JsonAstBuilder::VisitSlot(Slot* expr) {
1291 TagScope tag(this, "Slot");
1292 {
1293 AttributesScope attributes(this);
1294 switch (expr->type()) {
1295 case Slot::PARAMETER:
1296 AddAttribute("type", "PARAMETER");
1297 break;
1298 case Slot::LOCAL:
1299 AddAttribute("type", "LOCAL");
1300 break;
1301 case Slot::CONTEXT:
1302 AddAttribute("type", "CONTEXT");
1303 break;
1304 case Slot::LOOKUP:
1305 AddAttribute("type", "LOOKUP");
1306 break;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001307 }
1308 AddAttribute("index", expr->index());
1309 }
1310}
1311
1312
1313void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
1314 if (expr->var()->rewrite() == NULL) {
1315 TagScope tag(this, "VariableProxy");
1316 {
1317 AttributesScope attributes(this);
1318 AddAttribute("name", expr->name());
1319 AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
1320 }
1321 } else {
1322 Visit(expr->var()->rewrite());
1323 }
1324}
1325
1326
1327void JsonAstBuilder::VisitLiteral(Literal* expr) {
1328 TagScope tag(this, "Literal");
1329 {
1330 AttributesScope attributes(this);
1331 Handle<Object> handle = expr->handle();
1332 if (handle->IsString()) {
1333 AddAttribute("handle", Handle<String>(String::cast(*handle)));
1334 } else if (handle->IsSmi()) {
1335 AddAttribute("handle", Smi::cast(*handle)->value());
1336 }
1337 }
1338}
1339
1340
1341void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1342 TagScope tag(this, "RegExpLiteral");
1343}
1344
1345
1346void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1347 TagScope tag(this, "ObjectLiteral");
1348}
1349
1350
1351void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1352 TagScope tag(this, "ArrayLiteral");
1353}
1354
1355
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001356void JsonAstBuilder::VisitAssignment(Assignment* expr) {
1357 TagScope tag(this, "Assignment");
1358 {
1359 AttributesScope attributes(this);
1360 AddAttribute("op", Token::Name(expr->op()));
1361 }
1362 Visit(expr->target());
1363 Visit(expr->value());
1364}
1365
1366
1367void JsonAstBuilder::VisitThrow(Throw* expr) {
1368 TagScope tag(this, "Throw");
1369 Visit(expr->exception());
1370}
1371
1372
1373void JsonAstBuilder::VisitProperty(Property* expr) {
1374 TagScope tag(this, "Property");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001375 Visit(expr->obj());
1376 Visit(expr->key());
1377}
1378
1379
1380void JsonAstBuilder::VisitCall(Call* expr) {
1381 TagScope tag(this, "Call");
1382 Visit(expr->expression());
1383 VisitExpressions(expr->arguments());
1384}
1385
1386
1387void JsonAstBuilder::VisitCallNew(CallNew* expr) {
1388 TagScope tag(this, "CallNew");
1389 Visit(expr->expression());
1390 VisitExpressions(expr->arguments());
1391}
1392
1393
1394void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) {
1395 TagScope tag(this, "CallRuntime");
1396 {
1397 AttributesScope attributes(this);
1398 AddAttribute("name", expr->name());
1399 }
1400 VisitExpressions(expr->arguments());
1401}
1402
1403
1404void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) {
1405 TagScope tag(this, "UnaryOperation");
1406 {
1407 AttributesScope attributes(this);
1408 AddAttribute("op", Token::Name(expr->op()));
1409 }
1410 Visit(expr->expression());
1411}
1412
1413
1414void JsonAstBuilder::VisitCountOperation(CountOperation* expr) {
1415 TagScope tag(this, "CountOperation");
1416 {
1417 AttributesScope attributes(this);
1418 AddAttribute("is_prefix", expr->is_prefix());
1419 AddAttribute("op", Token::Name(expr->op()));
1420 }
1421 Visit(expr->expression());
1422}
1423
1424
1425void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) {
1426 TagScope tag(this, "BinaryOperation");
1427 {
1428 AttributesScope attributes(this);
1429 AddAttribute("op", Token::Name(expr->op()));
1430 }
1431 Visit(expr->left());
1432 Visit(expr->right());
1433}
1434
1435
1436void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) {
1437 TagScope tag(this, "CompareOperation");
1438 {
1439 AttributesScope attributes(this);
1440 AddAttribute("op", Token::Name(expr->op()));
1441 }
1442 Visit(expr->left());
1443 Visit(expr->right());
1444}
1445
1446
ricow@chromium.org65fae842010-08-25 15:26:24 +00001447void JsonAstBuilder::VisitCompareToNull(CompareToNull* expr) {
1448 TagScope tag(this, "CompareToNull");
1449 {
1450 AttributesScope attributes(this);
1451 AddAttribute("is_strict", expr->is_strict());
1452 }
1453 Visit(expr->expression());
1454}
1455
1456
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001457void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) {
1458 TagScope tag(this, "ThisFunction");
1459}
1460
1461
1462void JsonAstBuilder::VisitDeclaration(Declaration* decl) {
1463 TagScope tag(this, "Declaration");
1464 {
1465 AttributesScope attributes(this);
1466 AddAttribute("mode", Variable::Mode2String(decl->mode()));
1467 }
1468 Visit(decl->proxy());
1469 if (decl->fun() != NULL) Visit(decl->fun());
1470}
1471
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001472
1473#endif // DEBUG
1474
1475} } // namespace v8::internal