blob: f18b3203edc098ba4630c47006511ebb39e43d81 [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;
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
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());
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000859 PrintLiteralWithModeIndented("CATCHVAR",
860 node->variable(),
861 node->variable()->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000862 PrintIndentedVisit("CATCH", node->catch_block());
863}
864
865
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000866void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000867 IndentedScope indent(this, "TRY FINALLY");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000868 PrintIndentedVisit("TRY", node->try_block());
869 PrintIndentedVisit("FINALLY", node->finally_block());
870}
871
872
873void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000874 IndentedScope indent(this, "DEBUGGER");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875}
876
877
878void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000879 IndentedScope indent(this, "FUNC LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000880 PrintLiteralIndented("NAME", node->name(), false);
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000881 PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000882 PrintParameters(node->scope());
883 // We don't want to see the function literal in this case: it
884 // will be printed via PrintProgram when the code for it is
885 // generated.
886 // PrintStatements(node->body());
887}
888
889
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000890void AstPrinter::VisitSharedFunctionInfoLiteral(
891 SharedFunctionInfoLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000892 IndentedScope indent(this, "FUNC LITERAL");
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000893 PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000894}
895
896
897void AstPrinter::VisitConditional(Conditional* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000898 IndentedScope indent(this, "CONDITIONAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000899 PrintIndentedVisit("?", node->condition());
900 PrintIndentedVisit("THEN", node->then_expression());
901 PrintIndentedVisit("ELSE", node->else_expression());
902}
903
904
905void AstPrinter::VisitLiteral(Literal* node) {
906 PrintLiteralIndented("LITERAL", node->handle(), true);
907}
908
909
910void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000911 IndentedScope indent(this, "REGEXP LITERAL");
ager@chromium.orge2902be2009-06-08 12:21:35 +0000912 PrintLiteralIndented("PATTERN", node->pattern(), false);
913 PrintLiteralIndented("FLAGS", node->flags(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000914}
915
916
917void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000918 IndentedScope indent(this, "OBJ LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000919 for (int i = 0; i < node->properties()->length(); i++) {
920 const char* prop_kind = NULL;
921 switch (node->properties()->at(i)->kind()) {
922 case ObjectLiteral::Property::CONSTANT:
923 prop_kind = "PROPERTY - CONSTANT";
924 break;
925 case ObjectLiteral::Property::COMPUTED:
926 prop_kind = "PROPERTY - COMPUTED";
927 break;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000928 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
929 prop_kind = "PROPERTY - MATERIALIZED_LITERAL";
930 break;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000931 case ObjectLiteral::Property::PROTOTYPE:
932 prop_kind = "PROPERTY - PROTOTYPE";
933 break;
934 case ObjectLiteral::Property::GETTER:
935 prop_kind = "PROPERTY - GETTER";
936 break;
937 case ObjectLiteral::Property::SETTER:
938 prop_kind = "PROPERTY - SETTER";
939 break;
940 default:
941 UNREACHABLE();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000942 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000943 IndentedScope prop(this, prop_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000944 PrintIndentedVisit("KEY", node->properties()->at(i)->key());
945 PrintIndentedVisit("VALUE", node->properties()->at(i)->value());
946 }
947}
948
949
950void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000951 IndentedScope indent(this, "ARRAY LITERAL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000952 if (node->values()->length() > 0) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000953 IndentedScope indent(this, "VALUES");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000954 for (int i = 0; i < node->values()->length(); i++) {
955 Visit(node->values()->at(i));
956 }
957 }
958}
959
960
961void AstPrinter::VisitSlot(Slot* node) {
962 PrintIndented("SLOT ");
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000963 PrettyPrinter::VisitSlot(node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000964 Print("\n");
965}
966
967
968void AstPrinter::VisitVariableProxy(VariableProxy* node) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000969 PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000970 Variable* var = node->var();
971 if (var != NULL && var->rewrite() != NULL) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000972 IndentedScope indent(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000973 Visit(var->rewrite());
974 }
975}
976
977
978void AstPrinter::VisitAssignment(Assignment* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000979 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000980 Visit(node->target());
981 Visit(node->value());
982}
983
984
985void AstPrinter::VisitThrow(Throw* node) {
986 PrintIndentedVisit("THROW", node->exception());
987}
988
989
990void AstPrinter::VisitProperty(Property* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000991 IndentedScope indent(this, "PROPERTY", node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000992 Visit(node->obj());
993 Literal* literal = node->key()->AsLiteral();
994 if (literal != NULL && literal->handle()->IsSymbol()) {
kasperl@chromium.org2d18d102009-04-15 13:27:32 +0000995 PrintLiteralIndented("NAME", literal->handle(), false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000996 } else {
997 PrintIndentedVisit("KEY", node->key());
998 }
999}
1000
1001
1002void AstPrinter::VisitCall(Call* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001003 IndentedScope indent(this, "CALL");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001004 Visit(node->expression());
1005 PrintArguments(node->arguments());
1006}
1007
1008
1009void AstPrinter::VisitCallNew(CallNew* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001010 IndentedScope indent(this, "CALL NEW");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001011 Visit(node->expression());
1012 PrintArguments(node->arguments());
1013}
1014
1015
1016void AstPrinter::VisitCallRuntime(CallRuntime* node) {
1017 PrintLiteralIndented("CALL RUNTIME ", node->name(), false);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001018 IndentedScope indent(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001019 PrintArguments(node->arguments());
1020}
1021
1022
1023void AstPrinter::VisitUnaryOperation(UnaryOperation* node) {
1024 PrintIndentedVisit(Token::Name(node->op()), node->expression());
1025}
1026
1027
1028void AstPrinter::VisitCountOperation(CountOperation* node) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001029 EmbeddedVector<char, 128> buf;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001030 OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"),
1031 Token::Name(node->op()));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001032 PrintIndentedVisit(buf.start(), node->expression());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001033}
1034
1035
1036void AstPrinter::VisitBinaryOperation(BinaryOperation* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001037 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001038 Visit(node->left());
1039 Visit(node->right());
1040}
1041
1042
1043void AstPrinter::VisitCompareOperation(CompareOperation* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001044 IndentedScope indent(this, Token::Name(node->op()), node);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001045 Visit(node->left());
1046 Visit(node->right());
1047}
1048
1049
ricow@chromium.org65fae842010-08-25 15:26:24 +00001050void AstPrinter::VisitCompareToNull(CompareToNull* node) {
1051 const char* name = node->is_strict()
1052 ? "COMPARE-TO-NULL-STRICT"
1053 : "COMPARE-TO-NULL";
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001054 IndentedScope indent(this, name, node);
ricow@chromium.org65fae842010-08-25 15:26:24 +00001055 Visit(node->expression());
1056}
1057
1058
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001059void AstPrinter::VisitThisFunction(ThisFunction* node) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001060 IndentedScope indent(this, "THIS-FUNCTION");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001061}
1062
1063
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001064TagScope::TagScope(JsonAstBuilder* builder, const char* name)
1065 : builder_(builder), next_(builder->tag()), has_body_(false) {
1066 if (next_ != NULL) {
1067 next_->use();
1068 builder->Print(",\n");
1069 }
1070 builder->set_tag(this);
1071 builder->PrintIndented("[");
1072 builder->Print("\"%s\"", name);
1073 builder->increase_indent(JsonAstBuilder::kTagIndentSize);
1074}
1075
1076
1077TagScope::~TagScope() {
1078 builder_->decrease_indent(JsonAstBuilder::kTagIndentSize);
1079 if (has_body_) {
1080 builder_->Print("\n");
1081 builder_->PrintIndented("]");
1082 } else {
1083 builder_->Print("]");
1084 }
1085 builder_->set_tag(next_);
1086}
1087
1088
1089AttributesScope::AttributesScope(JsonAstBuilder* builder)
1090 : builder_(builder), attribute_count_(0) {
1091 builder->set_attributes(this);
1092 builder->tag()->use();
1093 builder->Print(",\n");
1094 builder->PrintIndented("{");
1095 builder->increase_indent(JsonAstBuilder::kAttributesIndentSize);
1096}
1097
1098
1099AttributesScope::~AttributesScope() {
1100 builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize);
1101 if (attribute_count_ > 1) {
1102 builder_->Print("\n");
1103 builder_->PrintIndented("}");
1104 } else {
1105 builder_->Print("}");
1106 }
1107 builder_->set_attributes(NULL);
1108}
1109
1110
1111const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) {
1112 Init();
1113 Visit(program);
1114 Print("\n");
1115 return Output();
1116}
1117
1118
1119void JsonAstBuilder::AddAttributePrefix(const char* name) {
1120 if (attributes()->is_used()) {
1121 Print(",\n");
1122 PrintIndented("\"");
1123 } else {
1124 Print("\"");
1125 }
1126 Print("%s\":", name);
1127 attributes()->use();
1128}
1129
1130
1131void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) {
1132 SmartPointer<char> value_string = value->ToCString();
1133 AddAttributePrefix(name);
1134 Print("\"%s\"", *value_string);
1135}
1136
1137
1138void JsonAstBuilder::AddAttribute(const char* name, const char* value) {
1139 AddAttributePrefix(name);
1140 Print("\"%s\"", value);
1141}
1142
1143
1144void JsonAstBuilder::AddAttribute(const char* name, int value) {
1145 AddAttributePrefix(name);
1146 Print("%d", value);
1147}
1148
1149
1150void JsonAstBuilder::AddAttribute(const char* name, bool value) {
1151 AddAttributePrefix(name);
1152 Print(value ? "true" : "false");
1153}
1154
1155
1156void JsonAstBuilder::VisitBlock(Block* stmt) {
1157 TagScope tag(this, "Block");
1158 VisitStatements(stmt->statements());
1159}
1160
1161
1162void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1163 TagScope tag(this, "ExpressionStatement");
1164 Visit(stmt->expression());
1165}
1166
1167
1168void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1169 TagScope tag(this, "EmptyStatement");
1170}
1171
1172
1173void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) {
1174 TagScope tag(this, "IfStatement");
1175 Visit(stmt->condition());
1176 Visit(stmt->then_statement());
1177 Visit(stmt->else_statement());
1178}
1179
1180
1181void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) {
1182 TagScope tag(this, "ContinueStatement");
1183}
1184
1185
1186void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) {
1187 TagScope tag(this, "BreakStatement");
1188}
1189
1190
1191void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1192 TagScope tag(this, "ReturnStatement");
1193 Visit(stmt->expression());
1194}
1195
1196
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001197void JsonAstBuilder::VisitEnterWithContextStatement(
1198 EnterWithContextStatement* stmt) {
1199 TagScope tag(this, "EnterWithContextStatement");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001200 Visit(stmt->expression());
1201}
1202
1203
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001204void JsonAstBuilder::VisitExitContextStatement(ExitContextStatement* stmt) {
1205 TagScope tag(this, "ExitContextStatement");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001206}
1207
1208
1209void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1210 TagScope tag(this, "SwitchStatement");
1211}
1212
1213
1214void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1215 TagScope tag(this, "DoWhileStatement");
1216 Visit(stmt->body());
1217 Visit(stmt->cond());
1218}
1219
1220
1221void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) {
1222 TagScope tag(this, "WhileStatement");
1223 Visit(stmt->cond());
1224 Visit(stmt->body());
1225}
1226
1227
1228void JsonAstBuilder::VisitForStatement(ForStatement* stmt) {
1229 TagScope tag(this, "ForStatement");
1230 if (stmt->init() != NULL) Visit(stmt->init());
1231 if (stmt->cond() != NULL) Visit(stmt->cond());
1232 Visit(stmt->body());
1233 if (stmt->next() != NULL) Visit(stmt->next());
1234}
1235
1236
1237void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) {
1238 TagScope tag(this, "ForInStatement");
1239 Visit(stmt->each());
1240 Visit(stmt->enumerable());
1241 Visit(stmt->body());
1242}
1243
1244
1245void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1246 TagScope tag(this, "TryCatchStatement");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001247 { AttributesScope attributes(this);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001248 AddAttribute("variable", stmt->variable()->name());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001249 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001250 Visit(stmt->try_block());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001251 Visit(stmt->catch_block());
1252}
1253
1254
1255void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1256 TagScope tag(this, "TryFinallyStatement");
1257 Visit(stmt->try_block());
1258 Visit(stmt->finally_block());
1259}
1260
1261
1262void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1263 TagScope tag(this, "DebuggerStatement");
1264}
1265
1266
1267void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
1268 TagScope tag(this, "FunctionLiteral");
1269 {
1270 AttributesScope attributes(this);
1271 AddAttribute("name", expr->name());
1272 }
1273 VisitDeclarations(expr->scope()->declarations());
1274 VisitStatements(expr->body());
1275}
1276
1277
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001278void JsonAstBuilder::VisitSharedFunctionInfoLiteral(
1279 SharedFunctionInfoLiteral* expr) {
1280 TagScope tag(this, "SharedFunctionInfoLiteral");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001281}
1282
1283
1284void JsonAstBuilder::VisitConditional(Conditional* expr) {
1285 TagScope tag(this, "Conditional");
1286}
1287
1288
1289void JsonAstBuilder::VisitSlot(Slot* expr) {
1290 TagScope tag(this, "Slot");
1291 {
1292 AttributesScope attributes(this);
1293 switch (expr->type()) {
1294 case Slot::PARAMETER:
1295 AddAttribute("type", "PARAMETER");
1296 break;
1297 case Slot::LOCAL:
1298 AddAttribute("type", "LOCAL");
1299 break;
1300 case Slot::CONTEXT:
1301 AddAttribute("type", "CONTEXT");
1302 break;
1303 case Slot::LOOKUP:
1304 AddAttribute("type", "LOOKUP");
1305 break;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001306 }
1307 AddAttribute("index", expr->index());
1308 }
1309}
1310
1311
1312void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
1313 if (expr->var()->rewrite() == NULL) {
1314 TagScope tag(this, "VariableProxy");
1315 {
1316 AttributesScope attributes(this);
1317 AddAttribute("name", expr->name());
1318 AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
1319 }
1320 } else {
1321 Visit(expr->var()->rewrite());
1322 }
1323}
1324
1325
1326void JsonAstBuilder::VisitLiteral(Literal* expr) {
1327 TagScope tag(this, "Literal");
1328 {
1329 AttributesScope attributes(this);
1330 Handle<Object> handle = expr->handle();
1331 if (handle->IsString()) {
1332 AddAttribute("handle", Handle<String>(String::cast(*handle)));
1333 } else if (handle->IsSmi()) {
1334 AddAttribute("handle", Smi::cast(*handle)->value());
1335 }
1336 }
1337}
1338
1339
1340void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1341 TagScope tag(this, "RegExpLiteral");
1342}
1343
1344
1345void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1346 TagScope tag(this, "ObjectLiteral");
1347}
1348
1349
1350void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1351 TagScope tag(this, "ArrayLiteral");
1352}
1353
1354
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001355void JsonAstBuilder::VisitAssignment(Assignment* expr) {
1356 TagScope tag(this, "Assignment");
1357 {
1358 AttributesScope attributes(this);
1359 AddAttribute("op", Token::Name(expr->op()));
1360 }
1361 Visit(expr->target());
1362 Visit(expr->value());
1363}
1364
1365
1366void JsonAstBuilder::VisitThrow(Throw* expr) {
1367 TagScope tag(this, "Throw");
1368 Visit(expr->exception());
1369}
1370
1371
1372void JsonAstBuilder::VisitProperty(Property* expr) {
1373 TagScope tag(this, "Property");
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001374 Visit(expr->obj());
1375 Visit(expr->key());
1376}
1377
1378
1379void JsonAstBuilder::VisitCall(Call* expr) {
1380 TagScope tag(this, "Call");
1381 Visit(expr->expression());
1382 VisitExpressions(expr->arguments());
1383}
1384
1385
1386void JsonAstBuilder::VisitCallNew(CallNew* expr) {
1387 TagScope tag(this, "CallNew");
1388 Visit(expr->expression());
1389 VisitExpressions(expr->arguments());
1390}
1391
1392
1393void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) {
1394 TagScope tag(this, "CallRuntime");
1395 {
1396 AttributesScope attributes(this);
1397 AddAttribute("name", expr->name());
1398 }
1399 VisitExpressions(expr->arguments());
1400}
1401
1402
1403void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) {
1404 TagScope tag(this, "UnaryOperation");
1405 {
1406 AttributesScope attributes(this);
1407 AddAttribute("op", Token::Name(expr->op()));
1408 }
1409 Visit(expr->expression());
1410}
1411
1412
1413void JsonAstBuilder::VisitCountOperation(CountOperation* expr) {
1414 TagScope tag(this, "CountOperation");
1415 {
1416 AttributesScope attributes(this);
1417 AddAttribute("is_prefix", expr->is_prefix());
1418 AddAttribute("op", Token::Name(expr->op()));
1419 }
1420 Visit(expr->expression());
1421}
1422
1423
1424void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) {
1425 TagScope tag(this, "BinaryOperation");
1426 {
1427 AttributesScope attributes(this);
1428 AddAttribute("op", Token::Name(expr->op()));
1429 }
1430 Visit(expr->left());
1431 Visit(expr->right());
1432}
1433
1434
1435void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) {
1436 TagScope tag(this, "CompareOperation");
1437 {
1438 AttributesScope attributes(this);
1439 AddAttribute("op", Token::Name(expr->op()));
1440 }
1441 Visit(expr->left());
1442 Visit(expr->right());
1443}
1444
1445
ricow@chromium.org65fae842010-08-25 15:26:24 +00001446void JsonAstBuilder::VisitCompareToNull(CompareToNull* expr) {
1447 TagScope tag(this, "CompareToNull");
1448 {
1449 AttributesScope attributes(this);
1450 AddAttribute("is_strict", expr->is_strict());
1451 }
1452 Visit(expr->expression());
1453}
1454
1455
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001456void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) {
1457 TagScope tag(this, "ThisFunction");
1458}
1459
1460
1461void JsonAstBuilder::VisitDeclaration(Declaration* decl) {
1462 TagScope tag(this, "Declaration");
1463 {
1464 AttributesScope attributes(this);
1465 AddAttribute("mode", Variable::Mode2String(decl->mode()));
1466 }
1467 Visit(decl->proxy());
1468 if (decl->fun() != NULL) Visit(decl->fun());
1469}
1470
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001471
1472#endif // DEBUG
1473
1474} } // namespace v8::internal