📄 prettyprinter.cc.svn-base
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following// disclaimer in the documentation and/or other materials provided// with the distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived// from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include <stdarg.h>#include "v8.h"#include "prettyprinter.h"#include "scopes.h"#include "platform.h"namespace v8 { namespace internal {#ifdef DEBUGPrettyPrinter::PrettyPrinter() { output_ = NULL; size_ = 0; pos_ = 0;}PrettyPrinter::~PrettyPrinter() { DeleteArray(output_);}void PrettyPrinter::VisitBlock(Block* node) { if (!node->is_initializer_block()) Print("{ "); PrintStatements(node->statements()); if (node->statements()->length() > 0) Print(" "); if (!node->is_initializer_block()) Print("}");}void PrettyPrinter::VisitDeclaration(Declaration* node) { Print("var "); PrintLiteral(node->proxy()->name(), false); if (node->fun() != NULL) { Print(" = "); PrintFunctionLiteral(node->fun()); } Print(";");}void PrettyPrinter::VisitExpressionStatement(ExpressionStatement* node) { Visit(node->expression()); Print(";");}void PrettyPrinter::VisitEmptyStatement(EmptyStatement* node) { Print(";");}void PrettyPrinter::VisitIfStatement(IfStatement* node) { Print("if ("); Visit(node->condition()); Print(") "); Visit(node->then_statement()); if (node->HasElseStatement()) { Print(" else "); Visit(node->else_statement()); }}void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) { Print("continue"); ZoneStringList* labels = node->target()->labels(); if (labels != NULL) { Print(" "); ASSERT(labels->length() > 0); // guaranteed to have at least one entry PrintLiteral(labels->at(0), false); // any label from the list is fine } Print(";");}void PrettyPrinter::VisitBreakStatement(BreakStatement* node) { Print("break"); ZoneStringList* labels = node->target()->labels(); if (labels != NULL) { Print(" "); ASSERT(labels->length() > 0); // guaranteed to have at least one entry PrintLiteral(labels->at(0), false); // any label from the list is fine } Print(";");}void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { Print("return "); Visit(node->expression()); Print(";");}void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) { Print("<enter with> ("); Visit(node->expression()); Print(") ");}void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) { Print("<exit with>");}void PrettyPrinter::VisitSwitchStatement(SwitchStatement* node) { PrintLabels(node->labels()); Print("switch ("); Visit(node->tag()); Print(") { "); ZoneList<CaseClause*>* cases = node->cases(); for (int i = 0; i < cases->length(); i++) PrintCaseClause(cases->at(i)); Print("}");}void PrettyPrinter::VisitLoopStatement(LoopStatement* node) { PrintLabels(node->labels()); switch (node->type()) { case LoopStatement::DO_LOOP: ASSERT(node->init() == NULL); ASSERT(node->next() == NULL); Print("do "); Visit(node->body()); Print(" while ("); Visit(node->cond()); Print(");"); break; case LoopStatement::FOR_LOOP: Print("for ("); if (node->init() != NULL) { Visit(node->init()); Print(" "); } else { Print("; "); } if (node->cond() != NULL) Visit(node->cond()); Print("; "); if (node->next() != NULL) Visit(node->next()); // prints extra ';', unfortunately // to fix: should use Expression for next Print(") "); Visit(node->body()); break; case LoopStatement::WHILE_LOOP: ASSERT(node->init() == NULL); ASSERT(node->next() == NULL); Print("while ("); Visit(node->cond()); Print(") "); Visit(node->body()); break; }}void PrettyPrinter::VisitForInStatement(ForInStatement* node) { PrintLabels(node->labels()); Print("for ("); Visit(node->each()); Print(" in "); Visit(node->enumerable()); Print(") "); Visit(node->body());}void PrettyPrinter::VisitTryCatch(TryCatch* node) { Print("try "); Visit(node->try_block()); Print(" catch ("); Visit(node->catch_var()); Print(") "); Visit(node->catch_block());}void PrettyPrinter::VisitTryFinally(TryFinally* node) { Print("try "); Visit(node->try_block()); Print(" finally "); Visit(node->finally_block());}void PrettyPrinter::VisitDebuggerStatement(DebuggerStatement* node) { Print("debugger ");}void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { Print("("); PrintFunctionLiteral(node); Print(")");}void PrettyPrinter::VisitFunctionBoilerplateLiteral( FunctionBoilerplateLiteral* node) { Print("("); PrintLiteral(node->boilerplate(), true); Print(")");}void PrettyPrinter::VisitConditional(Conditional* node) { Visit(node->condition()); Print(" ? "); Visit(node->then_expression()); Print(" : "); Visit(node->else_expression());}void PrettyPrinter::VisitLiteral(Literal* node) { PrintLiteral(node->handle(), true);}void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) { Print(" RegExp("); PrintLiteral(node->pattern(), false); Print(","); PrintLiteral(node->flags(), false); Print(") ");}void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) { Print("{ "); for (int i = 0; i < node->properties()->length(); i++) { if (i != 0) Print(","); ObjectLiteral::Property* property = node->properties()->at(i); Print(" "); Visit(property->key()); Print(": "); Visit(property->value()); } Print(" }");}void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) { Print("[ "); for (int i = 0; i < node->values()->length(); i++) { if (i != 0) Print(","); Visit(node->values()->at(i)); } Print(" ]");}void PrettyPrinter::VisitSlot(Slot* node) { switch (node->type()) { case Slot::PARAMETER: Print("parameter[%d]", node->index()); break; case Slot::LOCAL: Print("frame[%d]", node->index()); break; case Slot::CONTEXT: Print(".context[%d]", node->index()); break; case Slot::LOOKUP: Print(".context["); PrintLiteral(node->var()->name(), false); Print("]"); break; default: UNREACHABLE(); }}void PrettyPrinter::VisitVariableProxy(VariableProxy* node) { PrintLiteral(node->name(), false);}void PrettyPrinter::VisitAssignment(Assignment* node) { Visit(node->target()); Print(" %s ", Token::String(node->op())); Visit(node->value());}void PrettyPrinter::VisitThrow(Throw* node) { Print("throw "); Visit(node->exception());}void PrettyPrinter::VisitProperty(Property* node) { Expression* key = node->key(); Literal* literal = key->AsLiteral(); if (literal != NULL && literal->handle()->IsSymbol()) { Print("("); Visit(node->obj()); Print(")."); PrintLiteral(literal->handle(), false); } else { Visit(node->obj()); Print("["); Visit(key); Print("]"); }}void PrettyPrinter::VisitCall(Call* node) { Visit(node->expression()); PrintArguments(node->arguments());}void PrettyPrinter::VisitCallNew(CallNew* node) { Print("new ("); Visit(node->expression()); Print(")"); PrintArguments(node->arguments());}void PrettyPrinter::VisitCallRuntime(CallRuntime* node) { Print("%%"); PrintLiteral(node->name(), false); PrintArguments(node->arguments());}void PrettyPrinter::VisitUnaryOperation(UnaryOperation* node) { Print("(%s", Token::String(node->op())); Visit(node->expression()); Print(")");}void PrettyPrinter::VisitCountOperation(CountOperation* node) { Print("("); if (node->is_prefix()) Print("%s", Token::String(node->op())); Visit(node->expression()); if (node->is_postfix()) Print("%s", Token::String(node->op())); Print(")");}void PrettyPrinter::VisitBinaryOperation(BinaryOperation* node) { Print("("); Visit(node->left()); Print("%s", Token::String(node->op())); Visit(node->right()); Print(")");}void PrettyPrinter::VisitCompareOperation(CompareOperation* node) { Print("("); Visit(node->left()); Print("%s", Token::String(node->op())); Visit(node->right()); Print(")");}void PrettyPrinter::VisitThisFunction(ThisFunction* node) { Print("<this-function>");}const char* PrettyPrinter::Print(Node* node) { Init(); Visit(node); return output_;}const char* PrettyPrinter::PrintExpression(FunctionLiteral* program) { Init(); ExpressionStatement* statement = program->body()->at(0)->AsExpressionStatement(); Visit(statement->expression()); return output_;}const char* PrettyPrinter::PrintProgram(FunctionLiteral* program) { Init(); PrintStatements(program->body()); Print("\n"); return output_;}void PrettyPrinter::PrintOut(Node* node) { PrettyPrinter printer; PrintF("%s", printer.Print(node));}void PrettyPrinter::Init() { if (size_ == 0) { ASSERT(output_ == NULL); const int initial_size = 256; output_ = NewArray<char>(initial_size); size_ = initial_size; } output_[0] = '\0'; pos_ = 0;}void PrettyPrinter::Print(const char* format, ...) { for (;;) { va_list arguments; va_start(arguments, format); int n = OS::VSNPrintF(Vector<char>(output_, size_) + pos_, format, arguments); va_end(arguments); if (n >= 0) { // there was enough space - we are done pos_ += n; return; } else { // there was not enough space - allocate more and try again const int slack = 32; int new_size = size_ + (size_ >> 1) + slack; char* new_output = NewArray<char>(new_size); memcpy(new_output, output_, pos_); DeleteArray(output_); output_ = new_output; size_ = new_size; } }}void PrettyPrinter::PrintStatements(ZoneList<Statement*>* statements) { for (int i = 0; i < statements->length(); i++) { if (i != 0) Print(" "); Visit(statements->at(i)); }}void PrettyPrinter::PrintLabels(ZoneStringList* labels) { if (labels != NULL) { for (int i = 0; i < labels->length(); i++) { PrintLiteral(labels->at(i), false); Print(": "); } }}void PrettyPrinter::PrintArguments(ZoneList<Expression*>* arguments) { Print("("); for (int i = 0; i < arguments->length(); i++) { if (i != 0) Print(", "); Visit(arguments->at(i)); } Print(")");}void PrettyPrinter::PrintLiteral(Handle<Object> value, bool quote) { Object* object = *value; if (object->IsString()) { String* string = String::cast(object); if (quote) Print("\""); for (int i = 0; i < string->length(); i++) { Print("%c", string->Get(i)); } if (quote) Print("\""); } else if (object == Heap::null_value()) { Print("null"); } else if (object == Heap::true_value()) { Print("true"); } else if (object == Heap::false_value()) { Print("false"); } else if (object == Heap::undefined_value()) { Print("undefined"); } else if (object->IsNumber()) { Print("%g", object->Number()); } else if (object->IsJSObject()) { // regular expression if (object->IsJSFunction()) { Print("JS-Function"); } else if (object->IsJSArray()) { Print("JS-array[%u]", JSArray::cast(object)->length()); } else if (object->IsJSObject()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -