OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdarg.h> | 5 #include <stdarg.h> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/ast-value-factory.h" | 9 #include "src/ast-value-factory.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
11 #include "src/prettyprinter.h" | 11 #include "src/prettyprinter.h" |
12 #include "src/scopes.h" | 12 #include "src/scopes.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 CallPrinter::CallPrinter(Zone* zone) { | |
18 output_ = NULL; | |
19 size_ = 0; | |
20 pos_ = 0; | |
21 position_ = 0; | |
22 found_ = false; | |
23 done_ = false; | |
24 InitializeAstVisitor(zone); | |
25 } | |
26 | |
27 | |
28 CallPrinter::~CallPrinter() { DeleteArray(output_); } | |
29 | |
30 | |
31 const char* CallPrinter::Print(FunctionLiteral* program, int position) { | |
32 Init(); | |
33 position_ = position; | |
34 Find(program); | |
35 return output_; | |
36 } | |
37 | |
38 | |
39 void CallPrinter::Find(AstNode* node, bool print) { | |
40 if (done_) return; | |
41 if (found_) { | |
42 if (print) { | |
43 int start = pos_; | |
44 Visit(node); | |
45 if (start != pos_) return; | |
46 } | |
47 Print("(intermediate value)"); | |
Yang
2015/01/20 08:19:07
I'd use square brackets like we do when we print s
| |
48 } else { | |
49 Visit(node); | |
50 } | |
51 } | |
52 | |
53 | |
54 void CallPrinter::Init() { | |
55 if (size_ == 0) { | |
56 DCHECK(output_ == NULL); | |
57 const int initial_size = 256; | |
58 output_ = NewArray<char>(initial_size); | |
59 size_ = initial_size; | |
60 } | |
61 output_[0] = '\0'; | |
62 pos_ = 0; | |
63 } | |
64 | |
65 | |
66 void CallPrinter::Print(const char* format, ...) { | |
67 if (!found_ || done_) return; | |
68 for (;;) { | |
69 va_list arguments; | |
70 va_start(arguments, format); | |
71 int n = VSNPrintF(Vector<char>(output_, size_) + pos_, format, arguments); | |
72 va_end(arguments); | |
73 | |
74 if (n >= 0) { | |
75 // there was enough space - we are done | |
76 pos_ += n; | |
77 return; | |
78 } else { | |
79 // there was not enough space - allocate more and try again | |
80 const int slack = 32; | |
81 int new_size = size_ + (size_ >> 1) + slack; | |
82 char* new_output = NewArray<char>(new_size); | |
83 MemCopy(new_output, output_, pos_); | |
84 DeleteArray(output_); | |
85 output_ = new_output; | |
86 size_ = new_size; | |
87 } | |
88 } | |
89 } | |
90 | |
91 | |
92 void CallPrinter::VisitBlock(Block* node) { | |
93 FindStatements(node->statements()); | |
94 } | |
95 | |
96 | |
97 void CallPrinter::VisitVariableDeclaration(VariableDeclaration* node) {} | |
98 | |
99 | |
100 void CallPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { | |
101 Find(node->fun()); | |
102 } | |
103 | |
104 | |
105 void CallPrinter::VisitModuleDeclaration(ModuleDeclaration* node) { | |
106 Find(node->module()); | |
107 } | |
108 | |
109 | |
110 void CallPrinter::VisitImportDeclaration(ImportDeclaration* node) { | |
111 Find(node->module()); | |
112 } | |
113 | |
114 | |
115 void CallPrinter::VisitExportDeclaration(ExportDeclaration* node) {} | |
116 | |
117 | |
118 void CallPrinter::VisitModuleLiteral(ModuleLiteral* node) { | |
119 VisitBlock(node->body()); | |
120 } | |
121 | |
122 | |
123 void CallPrinter::VisitModuleVariable(ModuleVariable* node) { | |
124 Find(node->proxy()); | |
125 } | |
126 | |
127 | |
128 void CallPrinter::VisitModulePath(ModulePath* node) { Find(node->module()); } | |
129 | |
130 | |
131 void CallPrinter::VisitModuleUrl(ModuleUrl* node) {} | |
132 | |
133 | |
134 void CallPrinter::VisitModuleStatement(ModuleStatement* node) { | |
135 Find(node->body()); | |
136 } | |
137 | |
138 | |
139 void CallPrinter::VisitExpressionStatement(ExpressionStatement* node) { | |
140 Find(node->expression()); | |
141 } | |
142 | |
143 | |
144 void CallPrinter::VisitEmptyStatement(EmptyStatement* node) {} | |
145 | |
146 | |
147 void CallPrinter::VisitIfStatement(IfStatement* node) { | |
148 Find(node->condition()); | |
149 Find(node->then_statement()); | |
150 if (node->HasElseStatement()) { | |
151 Find(node->else_statement()); | |
152 } | |
153 } | |
154 | |
155 | |
156 void CallPrinter::VisitContinueStatement(ContinueStatement* node) {} | |
157 | |
158 | |
159 void CallPrinter::VisitBreakStatement(BreakStatement* node) {} | |
160 | |
161 | |
162 void CallPrinter::VisitReturnStatement(ReturnStatement* node) { | |
163 Find(node->expression()); | |
164 } | |
165 | |
166 | |
167 void CallPrinter::VisitWithStatement(WithStatement* node) { | |
168 Find(node->expression()); | |
169 Find(node->statement()); | |
170 } | |
171 | |
172 | |
173 void CallPrinter::VisitSwitchStatement(SwitchStatement* node) { | |
174 Find(node->tag()); | |
175 ZoneList<CaseClause*>* cases = node->cases(); | |
176 for (int i = 0; i < cases->length(); i++) Find(cases->at(i)); | |
177 } | |
178 | |
179 | |
180 void CallPrinter::VisitCaseClause(CaseClause* clause) { | |
181 if (!clause->is_default()) { | |
182 Find(clause->label()); | |
183 } | |
184 FindStatements(clause->statements()); | |
185 } | |
186 | |
187 | |
188 void CallPrinter::VisitDoWhileStatement(DoWhileStatement* node) { | |
189 Find(node->body()); | |
190 Find(node->cond()); | |
191 } | |
192 | |
193 | |
194 void CallPrinter::VisitWhileStatement(WhileStatement* node) { | |
195 Find(node->cond()); | |
196 Find(node->body()); | |
197 } | |
198 | |
199 | |
200 void CallPrinter::VisitForStatement(ForStatement* node) { | |
201 if (node->init() != NULL) { | |
Yang
2015/01/20 08:19:06
omitting curly brackets would look nicer :)
| |
202 Find(node->init()); | |
203 } | |
204 if (node->cond() != NULL) Find(node->cond()); | |
205 if (node->next() != NULL) Find(node->next()); | |
206 Find(node->body()); | |
207 } | |
208 | |
209 | |
210 void CallPrinter::VisitForInStatement(ForInStatement* node) { | |
211 Find(node->each()); | |
212 Find(node->enumerable()); | |
213 Find(node->body()); | |
214 } | |
215 | |
216 | |
217 void CallPrinter::VisitForOfStatement(ForOfStatement* node) { | |
218 Find(node->each()); | |
219 Find(node->iterable()); | |
220 Find(node->body()); | |
221 } | |
222 | |
223 | |
224 void CallPrinter::VisitTryCatchStatement(TryCatchStatement* node) { | |
225 Find(node->try_block()); | |
226 Find(node->catch_block()); | |
227 } | |
228 | |
229 | |
230 void CallPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { | |
231 Find(node->try_block()); | |
232 Find(node->finally_block()); | |
233 } | |
234 | |
235 | |
236 void CallPrinter::VisitDebuggerStatement(DebuggerStatement* node) {} | |
237 | |
238 | |
239 void CallPrinter::VisitFunctionLiteral(FunctionLiteral* node) { | |
240 FindStatements(node->body()); | |
241 } | |
242 | |
243 | |
244 void CallPrinter::VisitClassLiteral(ClassLiteral* node) { | |
245 if (node->extends()) Find(node->extends()); | |
246 for (int i = 0; i < node->properties()->length(); i++) { | |
247 Find(node->properties()->at(i)->value()); | |
248 } | |
249 } | |
250 | |
251 | |
252 void CallPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {} | |
253 | |
254 | |
255 void CallPrinter::VisitConditional(Conditional* node) { | |
256 Find(node->condition()); | |
257 Find(node->then_expression()); | |
258 Find(node->else_expression()); | |
259 } | |
260 | |
261 | |
262 void CallPrinter::VisitLiteral(Literal* node) { | |
263 PrintLiteral(node->value(), true); | |
264 } | |
265 | |
266 | |
267 void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {} | |
268 | |
269 | |
270 void CallPrinter::VisitObjectLiteral(ObjectLiteral* node) { | |
271 for (int i = 0; i < node->properties()->length(); i++) { | |
272 Find(node->properties()->at(i)->value()); | |
273 } | |
274 } | |
275 | |
276 | |
277 void CallPrinter::VisitArrayLiteral(ArrayLiteral* node) { | |
278 for (int i = 0; i < node->values()->length(); i++) { | |
279 Find(node->values()->at(i)); | |
280 } | |
281 } | |
282 | |
283 | |
284 void CallPrinter::VisitVariableProxy(VariableProxy* node) { | |
285 PrintLiteral(node->name(), false); | |
286 } | |
287 | |
288 | |
289 void CallPrinter::VisitAssignment(Assignment* node) { | |
290 Find(node->target()); | |
291 Find(node->value()); | |
292 } | |
293 | |
294 | |
295 void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); } | |
296 | |
297 | |
298 void CallPrinter::VisitThrow(Throw* node) { Find(node->exception()); } | |
299 | |
300 | |
301 void CallPrinter::VisitProperty(Property* node) { | |
302 Expression* key = node->key(); | |
303 Literal* literal = key->AsLiteral(); | |
304 if (literal != NULL && literal->value()->IsInternalizedString()) { | |
305 Find(node->obj(), true); | |
306 Print("."); | |
307 PrintLiteral(literal->value(), false); | |
308 } else { | |
309 Find(node->obj(), true); | |
310 Print("["); | |
311 Find(key, true); | |
312 Print("]"); | |
313 } | |
314 } | |
315 | |
316 | |
317 void CallPrinter::VisitCall(Call* node) { | |
318 bool was_found = !found_ && node->position() == position_; | |
319 if (was_found) found_ = true; | |
320 Find(node->expression(), true); | |
321 if (!was_found) Print("(...)"); | |
322 FindArguments(node->arguments()); | |
323 if (was_found) done_ = true; | |
324 } | |
325 | |
326 | |
327 void CallPrinter::VisitCallNew(CallNew* node) { | |
328 bool was_found = !found_ && node->expression()->position() == position_; | |
329 if (was_found) found_ = true; | |
330 Find(node->expression(), was_found); | |
331 FindArguments(node->arguments()); | |
332 if (was_found) done_ = true; | |
333 } | |
334 | |
335 | |
336 void CallPrinter::VisitCallRuntime(CallRuntime* node) { | |
337 FindArguments(node->arguments()); | |
338 } | |
339 | |
340 | |
341 void CallPrinter::VisitUnaryOperation(UnaryOperation* node) { | |
342 Token::Value op = node->op(); | |
343 bool needsSpace = | |
344 op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; | |
345 Print("(%s%s", Token::String(op), needsSpace ? " " : ""); | |
346 Find(node->expression(), true); | |
347 Print(")"); | |
348 } | |
349 | |
350 | |
351 void CallPrinter::VisitCountOperation(CountOperation* node) { | |
352 Print("("); | |
353 if (node->is_prefix()) Print("%s", Token::String(node->op())); | |
354 Find(node->expression(), true); | |
355 if (node->is_postfix()) Print("%s", Token::String(node->op())); | |
356 Print(")"); | |
357 } | |
358 | |
359 | |
360 void CallPrinter::VisitBinaryOperation(BinaryOperation* node) { | |
361 Print("("); | |
362 Find(node->left(), true); | |
363 Print(" %s ", Token::String(node->op())); | |
364 Find(node->right(), true); | |
365 Print(")"); | |
366 } | |
367 | |
368 | |
369 void CallPrinter::VisitCompareOperation(CompareOperation* node) { | |
370 Print("("); | |
371 Find(node->left(), true); | |
372 Print(" %s ", Token::String(node->op())); | |
373 Find(node->right(), true); | |
374 Print(")"); | |
375 } | |
376 | |
377 | |
378 void CallPrinter::VisitThisFunction(ThisFunction* node) {} | |
379 | |
380 | |
381 void CallPrinter::VisitSuperReference(SuperReference* node) {} | |
382 | |
383 | |
384 void CallPrinter::FindStatements(ZoneList<Statement*>* statements) { | |
385 if (statements == NULL) return; | |
386 for (int i = 0; i < statements->length(); i++) { | |
387 Find(statements->at(i)); | |
388 } | |
389 } | |
390 | |
391 | |
392 void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) { | |
393 if (found_) return; | |
394 for (int i = 0; i < arguments->length(); i++) { | |
395 Find(arguments->at(i)); | |
396 } | |
397 } | |
398 | |
399 | |
400 void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) { | |
401 Object* object = *value; | |
402 if (object->IsString()) { | |
403 String* string = String::cast(object); | |
404 if (quote) Print("\""); | |
405 for (int i = 0; i < string->length(); i++) { | |
406 Print("%c", string->Get(i)); | |
407 } | |
408 if (quote) Print("\""); | |
409 } else if (object->IsNull()) { | |
410 Print("null"); | |
411 } else if (object->IsTrue()) { | |
412 Print("true"); | |
413 } else if (object->IsFalse()) { | |
414 Print("false"); | |
415 } else if (object->IsUndefined()) { | |
416 Print("undefined"); | |
417 } else if (object->IsNumber()) { | |
418 Print("%g", object->Number()); | |
419 } | |
420 } | |
421 | |
422 | |
423 void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) { | |
424 PrintLiteral(value->string(), quote); | |
425 } | |
426 | |
427 | |
428 //----------------------------------------------------------------------------- | |
429 | |
430 | |
17 #ifdef DEBUG | 431 #ifdef DEBUG |
18 | 432 |
19 PrettyPrinter::PrettyPrinter(Zone* zone) { | 433 PrettyPrinter::PrettyPrinter(Zone* zone) { |
20 output_ = NULL; | 434 output_ = NULL; |
21 size_ = 0; | 435 size_ = 0; |
22 pos_ = 0; | 436 pos_ = 0; |
23 InitializeAstVisitor(zone); | 437 InitializeAstVisitor(zone); |
24 } | 438 } |
25 | 439 |
26 | 440 |
(...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1178 } | 1592 } |
1179 | 1593 |
1180 | 1594 |
1181 void AstPrinter::VisitSuperReference(SuperReference* node) { | 1595 void AstPrinter::VisitSuperReference(SuperReference* node) { |
1182 IndentedScope indent(this, "SUPER-REFERENCE"); | 1596 IndentedScope indent(this, "SUPER-REFERENCE"); |
1183 } | 1597 } |
1184 | 1598 |
1185 #endif // DEBUG | 1599 #endif // DEBUG |
1186 | 1600 |
1187 } } // namespace v8::internal | 1601 } } // namespace v8::internal |
OLD | NEW |