• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_PRETTYPRINTER_H_
29 #define V8_PRETTYPRINTER_H_
30 
31 #include "ast.h"
32 
33 namespace v8 {
34 namespace internal {
35 
36 #ifdef DEBUG
37 
38 class PrettyPrinter: public AstVisitor {
39  public:
40   PrettyPrinter();
41   virtual ~PrettyPrinter();
42 
43   // The following routines print a node into a string.
44   // The result string is alive as long as the PrettyPrinter is alive.
45   const char* Print(AstNode* node);
46   const char* PrintExpression(FunctionLiteral* program);
47   const char* PrintProgram(FunctionLiteral* program);
48 
49   void Print(const char* format, ...);
50 
51   // Print a node to stdout.
52   static void PrintOut(AstNode* node);
53 
54   virtual void VisitSlot(Slot* node);
55   // Individual nodes
56 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
57   AST_NODE_LIST(DECLARE_VISIT)
58 #undef DECLARE_VISIT
59 
60  private:
61   char* output_;  // output string buffer
62   int size_;  // output_ size
63   int pos_;  // current printing position
64 
65  protected:
66   void Init();
Output()67   const char* Output() const { return output_; }
68 
69   virtual void PrintStatements(ZoneList<Statement*>* statements);
70   void PrintLabels(ZoneStringList* labels);
71   virtual void PrintArguments(ZoneList<Expression*>* arguments);
72   void PrintLiteral(Handle<Object> value, bool quote);
73   void PrintParameters(Scope* scope);
74   void PrintDeclarations(ZoneList<Declaration*>* declarations);
75   void PrintFunctionLiteral(FunctionLiteral* function);
76   void PrintCaseClause(CaseClause* clause);
77 };
78 
79 
80 // Prints the AST structure
81 class AstPrinter: public PrettyPrinter {
82  public:
83   AstPrinter();
84   virtual ~AstPrinter();
85 
86   const char* PrintProgram(FunctionLiteral* program);
87 
88   // Individual nodes
89   virtual void VisitSlot(Slot* node);
90 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
91   AST_NODE_LIST(DECLARE_VISIT)
92 #undef DECLARE_VISIT
93 
94  private:
95   friend class IndentedScope;
96   void PrintIndented(const char* txt);
97   void PrintIndentedVisit(const char* s, AstNode* node);
98 
99   void PrintStatements(ZoneList<Statement*>* statements);
100   void PrintDeclarations(ZoneList<Declaration*>* declarations);
101   void PrintParameters(Scope* scope);
102   void PrintArguments(ZoneList<Expression*>* arguments);
103   void PrintCaseClause(CaseClause* clause);
104   void PrintLiteralIndented(const char* info, Handle<Object> value, bool quote);
105   void PrintLiteralWithModeIndented(const char* info,
106                                     Variable* var,
107                                     Handle<Object> value);
108   void PrintLabelsIndented(const char* info, ZoneStringList* labels);
109 
inc_indent()110   void inc_indent() { indent_++; }
dec_indent()111   void dec_indent() { indent_--; }
112 
113   int indent_;
114 };
115 
116 
117 // Forward declaration of helper classes.
118 class TagScope;
119 class AttributesScope;
120 
121 // Build a C string containing a JSON representation of a function's
122 // AST. The representation is based on JsonML (www.jsonml.org).
123 class JsonAstBuilder: public PrettyPrinter {
124  public:
JsonAstBuilder()125   JsonAstBuilder()
126       : indent_(0), top_tag_scope_(NULL), attributes_scope_(NULL) {
127   }
~JsonAstBuilder()128   virtual ~JsonAstBuilder() {}
129 
130   // Controls the indentation of subsequent lines of a tag body after
131   // the first line.
132   static const int kTagIndentSize = 2;
133 
134   // Controls the indentation of subsequent lines of an attributes
135   // blocks's body after the first line.
136   static const int kAttributesIndentSize = 1;
137 
138   // Construct a JSON representation of a function literal.
139   const char* BuildProgram(FunctionLiteral* program);
140 
141   // Print text indented by the current indentation level.
PrintIndented(const char * text)142   void PrintIndented(const char* text) { Print("%*s%s", indent_, "", text); }
143 
144   // Change the indentation level.
increase_indent(int amount)145   void increase_indent(int amount) { indent_ += amount; }
decrease_indent(int amount)146   void decrease_indent(int amount) { indent_ -= amount; }
147 
148   // The builder maintains a stack of opened AST node constructors.
149   // Each node constructor corresponds to a JsonML tag.
tag()150   TagScope* tag() { return top_tag_scope_; }
set_tag(TagScope * scope)151   void set_tag(TagScope* scope) { top_tag_scope_ = scope; }
152 
153   // The builder maintains a pointer to the currently opened attributes
154   // of current AST node or NULL if the attributes are not opened.
attributes()155   AttributesScope* attributes() { return attributes_scope_; }
set_attributes(AttributesScope * scope)156   void set_attributes(AttributesScope* scope) { attributes_scope_ = scope; }
157 
158   // Add an attribute to the currently opened attributes.
159   void AddAttribute(const char* name, Handle<String> value);
160   void AddAttribute(const char* name, const char* value);
161   void AddAttribute(const char* name, int value);
162   void AddAttribute(const char* name, bool value);
163 
164   // AST node visit functions.
165   virtual void VisitSlot(Slot* node);
166 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
167   AST_NODE_LIST(DECLARE_VISIT)
168 #undef DECLARE_VISIT
169 
170  private:
171   int indent_;
172   TagScope* top_tag_scope_;
173   AttributesScope* attributes_scope_;
174 
175   // Utility function used by AddAttribute implementations.
176   void AddAttributePrefix(const char* name);
177 };
178 
179 
180 // The JSON AST builder keeps a stack of open element tags (AST node
181 // constructors from the current iteration point to the root of the
182 // AST).  TagScope is a helper class to manage the opening and closing
183 // of tags, the indentation of their bodies, and comma separating their
184 // contents.
185 class TagScope BASE_EMBEDDED {
186  public:
187   TagScope(JsonAstBuilder* builder, const char* name);
188   ~TagScope();
189 
use()190   void use() { has_body_ = true; }
191 
192  private:
193   JsonAstBuilder* builder_;
194   TagScope* next_;
195   bool has_body_;
196 };
197 
198 
199 // AttributesScope is a helper class to manage the opening and closing
200 // of attribute blocks, the indentation of their bodies, and comma
201 // separating their contents. JsonAstBuilder::AddAttribute adds an
202 // attribute to the currently open AttributesScope. They cannot be
203 // nested so the builder keeps an optional single scope rather than a
204 // stack.
205 class AttributesScope BASE_EMBEDDED {
206  public:
207   explicit AttributesScope(JsonAstBuilder* builder);
208   ~AttributesScope();
209 
is_used()210   bool is_used() { return attribute_count_ > 0; }
use()211   void use() { ++attribute_count_; }
212 
213  private:
214   JsonAstBuilder* builder_;
215   int attribute_count_;
216 };
217 
218 #endif  // DEBUG
219 
220 } }  // namespace v8::internal
221 
222 #endif  // V8_PRETTYPRINTER_H_
223