diff options
Diffstat (limited to 'src/3rdparty/v8/src/prettyprinter.cc')
-rw-r--r-- | src/3rdparty/v8/src/prettyprinter.cc | 1530 |
1 files changed, 1530 insertions, 0 deletions
diff --git a/src/3rdparty/v8/src/prettyprinter.cc b/src/3rdparty/v8/src/prettyprinter.cc new file mode 100644 index 0000000..043ad1c --- /dev/null +++ b/src/3rdparty/v8/src/prettyprinter.cc @@ -0,0 +1,1530 @@ +// 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 DEBUG + +PrettyPrinter::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::VisitDoWhileStatement(DoWhileStatement* node) { + PrintLabels(node->labels()); + Print("do "); + Visit(node->body()); + Print(" while ("); + Visit(node->cond()); + Print(");"); +} + + +void PrettyPrinter::VisitWhileStatement(WhileStatement* node) { + PrintLabels(node->labels()); + Print("while ("); + Visit(node->cond()); + Print(") "); + Visit(node->body()); +} + + +void PrettyPrinter::VisitForStatement(ForStatement* node) { + PrintLabels(node->labels()); + 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()); +} + + +void PrettyPrinter::VisitForInStatement(ForInStatement* node) { + PrintLabels(node->labels()); + Print("for ("); + Visit(node->each()); + Print(" in "); + Visit(node->enumerable()); + Print(") "); + Visit(node->body()); +} + + +void PrettyPrinter::VisitTryCatchStatement(TryCatchStatement* node) { + Print("try "); + Visit(node->try_block()); + Print(" catch ("); + Visit(node->catch_var()); + Print(") "); + Visit(node->catch_block()); +} + + +void PrettyPrinter::VisitTryFinallyStatement(TryFinallyStatement* 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::VisitSharedFunctionInfoLiteral( + SharedFunctionInfoLiteral* node) { + Print("("); + PrintLiteral(node->shared_function_info(), 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::VisitCatchExtensionObject(CatchExtensionObject* node) { + Print("{ "); + Visit(node->key()); + Print(": "); + Visit(node->value()); + Print(" }"); +} + + +void PrettyPrinter::VisitSlot(Slot* node) { + switch (node->type()) { + case Slot::PARAMETER: + Print("parameter[%d]", node->index()); + break; + case Slot::LOCAL: + Print("local[%d]", node->index()); + break; + case Slot::CONTEXT: + Print("context[%d]", node->index()); + break; + case Slot::LOOKUP: + Print("lookup["); + 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::VisitIncrementOperation(IncrementOperation* node) { + UNREACHABLE(); +} + + +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::VisitCompareToNull(CompareToNull* node) { + Print("("); + Visit(node->expression()); + Print("%s null)", Token::String(node->op())); +} + + +void PrettyPrinter::VisitThisFunction(ThisFunction* node) { + Print("<this-function>"); +} + + +const char* PrettyPrinter::Print(AstNode* 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(AstNode* 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->IsNull()) { + Print("null"); + } else if (object->IsTrue()) { + Print("true"); + } else if (object->IsFalse()) { + Print("false"); + } else if (object->IsUndefined()) { + 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()) { + Print("JS-Object"); + } else { + Print("?UNKNOWN?"); + } + } else if (object->IsFixedArray()) { + Print("FixedArray"); + } else { + Print("<unknown literal %p>", object); + } +} + + +void PrettyPrinter::PrintParameters(Scope* scope) { + Print("("); + for (int i = 0; i < scope->num_parameters(); i++) { + if (i > 0) Print(", "); + PrintLiteral(scope->parameter(i)->name(), false); + } + Print(")"); +} + + +void PrettyPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { + for (int i = 0; i < declarations->length(); i++) { + if (i > 0) Print(" "); + Visit(declarations->at(i)); + } +} + + +void PrettyPrinter::PrintFunctionLiteral(FunctionLiteral* function) { + Print("function "); + PrintLiteral(function->name(), false); + PrintParameters(function->scope()); + Print(" { "); + PrintDeclarations(function->scope()->declarations()); + PrintStatements(function->body()); + Print(" }"); +} + + +void PrettyPrinter::PrintCaseClause(CaseClause* clause) { + if (clause->is_default()) { + Print("default"); + } else { + Print("case "); + Visit(clause->label()); + } + Print(": "); + PrintStatements(clause->statements()); + if (clause->statements()->length() > 0) + Print(" "); +} + + +//----------------------------------------------------------------------------- + +class IndentedScope BASE_EMBEDDED { + public: + explicit IndentedScope(AstPrinter* printer) : ast_printer_(printer) { + ast_printer_->inc_indent(); + } + + IndentedScope(AstPrinter* printer, const char* txt, AstNode* node = NULL) + : ast_printer_(printer) { + ast_printer_->PrintIndented(txt); + if (node != NULL && node->AsExpression() != NULL) { + Expression* expr = node->AsExpression(); + bool printed_first = false; + if ((expr->type() != NULL) && (expr->type()->IsKnown())) { + ast_printer_->Print(" (type = "); + ast_printer_->Print(StaticType::Type2String(expr->type())); + printed_first = true; + } + if (printed_first) ast_printer_->Print(")"); + } + ast_printer_->Print("\n"); + ast_printer_->inc_indent(); + } + + virtual ~IndentedScope() { + ast_printer_->dec_indent(); + } + + private: + AstPrinter* ast_printer_; +}; + + +//----------------------------------------------------------------------------- + + +AstPrinter::AstPrinter() : indent_(0) { +} + + +AstPrinter::~AstPrinter() { + ASSERT(indent_ == 0); +} + + +void AstPrinter::PrintIndented(const char* txt) { + for (int i = 0; i < indent_; i++) { + Print(". "); + } + Print(txt); +} + + +void AstPrinter::PrintLiteralIndented(const char* info, + Handle<Object> value, + bool quote) { + PrintIndented(info); + Print(" "); + PrintLiteral(value, quote); + Print("\n"); +} + + +void AstPrinter::PrintLiteralWithModeIndented(const char* info, + Variable* var, + Handle<Object> value, + StaticType* type) { + if (var == NULL) { + PrintLiteralIndented(info, value, true); + } else { + EmbeddedVector<char, 256> buf; + int pos = OS::SNPrintF(buf, "%s (mode = %s", info, + Variable::Mode2String(var->mode())); + if (type->IsKnown()) { + pos += OS::SNPrintF(buf + pos, ", type = %s", + StaticType::Type2String(type)); + } + OS::SNPrintF(buf + pos, ")"); + PrintLiteralIndented(buf.start(), value, true); + } +} + + +void AstPrinter::PrintLabelsIndented(const char* info, ZoneStringList* labels) { + if (labels != NULL && labels->length() > 0) { + if (info == NULL) { + PrintIndented("LABELS "); + } else { + PrintIndented(info); + Print(" "); + } + PrintLabels(labels); + } else if (info != NULL) { + PrintIndented(info); + } + Print("\n"); +} + + +void AstPrinter::PrintIndentedVisit(const char* s, AstNode* node) { + IndentedScope indent(this, s, node); + Visit(node); +} + + +const char* AstPrinter::PrintProgram(FunctionLiteral* program) { + Init(); + { IndentedScope indent(this, "FUNC"); + PrintLiteralIndented("NAME", program->name(), true); + PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true); + PrintParameters(program->scope()); + PrintDeclarations(program->scope()->declarations()); + PrintStatements(program->body()); + } + return Output(); +} + + +void AstPrinter::PrintDeclarations(ZoneList<Declaration*>* declarations) { + if (declarations->length() > 0) { + IndentedScope indent(this, "DECLS"); + for (int i = 0; i < declarations->length(); i++) { + Visit(declarations->at(i)); + } + } +} + + +void AstPrinter::PrintParameters(Scope* scope) { + if (scope->num_parameters() > 0) { + IndentedScope indent(this, "PARAMS"); + for (int i = 0; i < scope->num_parameters(); i++) { + PrintLiteralWithModeIndented("VAR", scope->parameter(i), + scope->parameter(i)->name(), + scope->parameter(i)->type()); + } + } +} + + +void AstPrinter::PrintStatements(ZoneList<Statement*>* statements) { + for (int i = 0; i < statements->length(); i++) { + Visit(statements->at(i)); + } +} + + +void AstPrinter::PrintArguments(ZoneList<Expression*>* arguments) { + for (int i = 0; i < arguments->length(); i++) { + Visit(arguments->at(i)); + } +} + + +void AstPrinter::PrintCaseClause(CaseClause* clause) { + if (clause->is_default()) { + IndentedScope indent(this, "DEFAULT"); + PrintStatements(clause->statements()); + } else { + IndentedScope indent(this, "CASE"); + Visit(clause->label()); + PrintStatements(clause->statements()); + } +} + + +void AstPrinter::VisitBlock(Block* node) { + const char* block_txt = node->is_initializer_block() ? "BLOCK INIT" : "BLOCK"; + IndentedScope indent(this, block_txt); + PrintStatements(node->statements()); +} + + +void AstPrinter::VisitDeclaration(Declaration* node) { + if (node->fun() == NULL) { + // var or const declarations + PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()), + node->proxy()->AsVariable(), + node->proxy()->name(), + node->proxy()->AsVariable()->type()); + } else { + // function declarations + PrintIndented("FUNCTION "); + PrintLiteral(node->proxy()->name(), true); + Print(" = function "); + PrintLiteral(node->fun()->name(), false); + Print("\n"); + } +} + + +void AstPrinter::VisitExpressionStatement(ExpressionStatement* node) { + Visit(node->expression()); +} + + +void AstPrinter::VisitEmptyStatement(EmptyStatement* node) { + PrintIndented("EMPTY\n"); +} + + +void AstPrinter::VisitIfStatement(IfStatement* node) { + PrintIndentedVisit("IF", node->condition()); + PrintIndentedVisit("THEN", node->then_statement()); + if (node->HasElseStatement()) { + PrintIndentedVisit("ELSE", node->else_statement()); + } +} + + +void AstPrinter::VisitContinueStatement(ContinueStatement* node) { + PrintLabelsIndented("CONTINUE", node->target()->labels()); +} + + +void AstPrinter::VisitBreakStatement(BreakStatement* node) { + PrintLabelsIndented("BREAK", node->target()->labels()); +} + + +void AstPrinter::VisitReturnStatement(ReturnStatement* node) { + PrintIndentedVisit("RETURN", node->expression()); +} + + +void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) { + PrintIndentedVisit("WITH ENTER", node->expression()); +} + + +void AstPrinter::VisitWithExitStatement(WithExitStatement* node) { + PrintIndented("WITH EXIT\n"); +} + + +void AstPrinter::VisitSwitchStatement(SwitchStatement* node) { + IndentedScope indent(this, "SWITCH"); + PrintLabelsIndented(NULL, node->labels()); + PrintIndentedVisit("TAG", node->tag()); + for (int i = 0; i < node->cases()->length(); i++) { + PrintCaseClause(node->cases()->at(i)); + } +} + + +void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) { + IndentedScope indent(this, "DO"); + PrintLabelsIndented(NULL, node->labels()); + PrintIndentedVisit("BODY", node->body()); + PrintIndentedVisit("COND", node->cond()); +} + + +void AstPrinter::VisitWhileStatement(WhileStatement* node) { + IndentedScope indent(this, "WHILE"); + PrintLabelsIndented(NULL, node->labels()); + PrintIndentedVisit("COND", node->cond()); + PrintIndentedVisit("BODY", node->body()); +} + + +void AstPrinter::VisitForStatement(ForStatement* node) { + IndentedScope indent(this, "FOR"); + PrintLabelsIndented(NULL, node->labels()); + if (node->init()) PrintIndentedVisit("INIT", node->init()); + if (node->cond()) PrintIndentedVisit("COND", node->cond()); + PrintIndentedVisit("BODY", node->body()); + if (node->next()) PrintIndentedVisit("NEXT", node->next()); +} + + +void AstPrinter::VisitForInStatement(ForInStatement* node) { + IndentedScope indent(this, "FOR IN"); + PrintIndentedVisit("FOR", node->each()); + PrintIndentedVisit("IN", node->enumerable()); + PrintIndentedVisit("BODY", node->body()); +} + + +void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) { + IndentedScope indent(this, "TRY CATCH"); + PrintIndentedVisit("TRY", node->try_block()); + PrintIndentedVisit("CATCHVAR", node->catch_var()); + PrintIndentedVisit("CATCH", node->catch_block()); +} + + +void AstPrinter::VisitTryFinallyStatement(TryFinallyStatement* node) { + IndentedScope indent(this, "TRY FINALLY"); + PrintIndentedVisit("TRY", node->try_block()); + PrintIndentedVisit("FINALLY", node->finally_block()); +} + + +void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { + IndentedScope indent(this, "DEBUGGER"); +} + + +void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { + IndentedScope indent(this, "FUNC LITERAL"); + PrintLiteralIndented("NAME", node->name(), false); + PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false); + PrintParameters(node->scope()); + // We don't want to see the function literal in this case: it + // will be printed via PrintProgram when the code for it is + // generated. + // PrintStatements(node->body()); +} + + +void AstPrinter::VisitSharedFunctionInfoLiteral( + SharedFunctionInfoLiteral* node) { + IndentedScope indent(this, "FUNC LITERAL"); + PrintLiteralIndented("SHARED INFO", node->shared_function_info(), true); +} + + +void AstPrinter::VisitConditional(Conditional* node) { + IndentedScope indent(this, "CONDITIONAL"); + PrintIndentedVisit("?", node->condition()); + PrintIndentedVisit("THEN", node->then_expression()); + PrintIndentedVisit("ELSE", node->else_expression()); +} + + +void AstPrinter::VisitLiteral(Literal* node) { + PrintLiteralIndented("LITERAL", node->handle(), true); +} + + +void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { + IndentedScope indent(this, "REGEXP LITERAL"); + PrintLiteralIndented("PATTERN", node->pattern(), false); + PrintLiteralIndented("FLAGS", node->flags(), false); +} + + +void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) { + IndentedScope indent(this, "OBJ LITERAL"); + for (int i = 0; i < node->properties()->length(); i++) { + const char* prop_kind = NULL; + switch (node->properties()->at(i)->kind()) { + case ObjectLiteral::Property::CONSTANT: + prop_kind = "PROPERTY - CONSTANT"; + break; + case ObjectLiteral::Property::COMPUTED: + prop_kind = "PROPERTY - COMPUTED"; + break; + case ObjectLiteral::Property::MATERIALIZED_LITERAL: + prop_kind = "PROPERTY - MATERIALIZED_LITERAL"; + break; + case ObjectLiteral::Property::PROTOTYPE: + prop_kind = "PROPERTY - PROTOTYPE"; + break; + case ObjectLiteral::Property::GETTER: + prop_kind = "PROPERTY - GETTER"; + break; + case ObjectLiteral::Property::SETTER: + prop_kind = "PROPERTY - SETTER"; + break; + default: + UNREACHABLE(); + } + IndentedScope prop(this, prop_kind); + PrintIndentedVisit("KEY", node->properties()->at(i)->key()); + PrintIndentedVisit("VALUE", node->properties()->at(i)->value()); + } +} + + +void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) { + IndentedScope indent(this, "ARRAY LITERAL"); + if (node->values()->length() > 0) { + IndentedScope indent(this, "VALUES"); + for (int i = 0; i < node->values()->length(); i++) { + Visit(node->values()->at(i)); + } + } +} + + +void AstPrinter::VisitCatchExtensionObject(CatchExtensionObject* node) { + IndentedScope indent(this, "CatchExtensionObject"); + PrintIndentedVisit("KEY", node->key()); + PrintIndentedVisit("VALUE", node->value()); +} + + +void AstPrinter::VisitSlot(Slot* node) { + PrintIndented("SLOT "); + PrettyPrinter::VisitSlot(node); + Print("\n"); +} + + +void AstPrinter::VisitVariableProxy(VariableProxy* node) { + PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name(), + node->type()); + Variable* var = node->var(); + if (var != NULL && var->rewrite() != NULL) { + IndentedScope indent(this); + Visit(var->rewrite()); + } +} + + +void AstPrinter::VisitAssignment(Assignment* node) { + IndentedScope indent(this, Token::Name(node->op()), node); + Visit(node->target()); + Visit(node->value()); +} + + +void AstPrinter::VisitThrow(Throw* node) { + PrintIndentedVisit("THROW", node->exception()); +} + + +void AstPrinter::VisitProperty(Property* node) { + IndentedScope indent(this, "PROPERTY", node); + Visit(node->obj()); + Literal* literal = node->key()->AsLiteral(); + if (literal != NULL && literal->handle()->IsSymbol()) { + PrintLiteralIndented("NAME", literal->handle(), false); + } else { + PrintIndentedVisit("KEY", node->key()); + } +} + + +void AstPrinter::VisitCall(Call* node) { + IndentedScope indent(this, "CALL"); + Visit(node->expression()); + PrintArguments(node->arguments()); +} + + +void AstPrinter::VisitCallNew(CallNew* node) { + IndentedScope indent(this, "CALL NEW"); + Visit(node->expression()); + PrintArguments(node->arguments()); +} + + +void AstPrinter::VisitCallRuntime(CallRuntime* node) { + PrintLiteralIndented("CALL RUNTIME ", node->name(), false); + IndentedScope indent(this); + PrintArguments(node->arguments()); +} + + +void AstPrinter::VisitUnaryOperation(UnaryOperation* node) { + PrintIndentedVisit(Token::Name(node->op()), node->expression()); +} + + +void AstPrinter::VisitIncrementOperation(IncrementOperation* node) { + UNREACHABLE(); +} + + +void AstPrinter::VisitCountOperation(CountOperation* node) { + EmbeddedVector<char, 128> buf; + if (node->type()->IsKnown()) { + OS::SNPrintF(buf, "%s %s (type = %s)", + (node->is_prefix() ? "PRE" : "POST"), + Token::Name(node->op()), + StaticType::Type2String(node->type())); + } else { + OS::SNPrintF(buf, "%s %s", (node->is_prefix() ? "PRE" : "POST"), + Token::Name(node->op())); + } + PrintIndentedVisit(buf.start(), node->expression()); +} + + +void AstPrinter::VisitBinaryOperation(BinaryOperation* node) { + IndentedScope indent(this, Token::Name(node->op()), node); + Visit(node->left()); + Visit(node->right()); +} + + +void AstPrinter::VisitCompareOperation(CompareOperation* node) { + IndentedScope indent(this, Token::Name(node->op()), node); + Visit(node->left()); + Visit(node->right()); +} + + +void AstPrinter::VisitCompareToNull(CompareToNull* node) { + const char* name = node->is_strict() + ? "COMPARE-TO-NULL-STRICT" + : "COMPARE-TO-NULL"; + IndentedScope indent(this, name, node); + Visit(node->expression()); +} + + +void AstPrinter::VisitThisFunction(ThisFunction* node) { + IndentedScope indent(this, "THIS-FUNCTION"); +} + + +TagScope::TagScope(JsonAstBuilder* builder, const char* name) + : builder_(builder), next_(builder->tag()), has_body_(false) { + if (next_ != NULL) { + next_->use(); + builder->Print(",\n"); + } + builder->set_tag(this); + builder->PrintIndented("["); + builder->Print("\"%s\"", name); + builder->increase_indent(JsonAstBuilder::kTagIndentSize); +} + + +TagScope::~TagScope() { + builder_->decrease_indent(JsonAstBuilder::kTagIndentSize); + if (has_body_) { + builder_->Print("\n"); + builder_->PrintIndented("]"); + } else { + builder_->Print("]"); + } + builder_->set_tag(next_); +} + + +AttributesScope::AttributesScope(JsonAstBuilder* builder) + : builder_(builder), attribute_count_(0) { + builder->set_attributes(this); + builder->tag()->use(); + builder->Print(",\n"); + builder->PrintIndented("{"); + builder->increase_indent(JsonAstBuilder::kAttributesIndentSize); +} + + +AttributesScope::~AttributesScope() { + builder_->decrease_indent(JsonAstBuilder::kAttributesIndentSize); + if (attribute_count_ > 1) { + builder_->Print("\n"); + builder_->PrintIndented("}"); + } else { + builder_->Print("}"); + } + builder_->set_attributes(NULL); +} + + +const char* JsonAstBuilder::BuildProgram(FunctionLiteral* program) { + Init(); + Visit(program); + Print("\n"); + return Output(); +} + + +void JsonAstBuilder::AddAttributePrefix(const char* name) { + if (attributes()->is_used()) { + Print(",\n"); + PrintIndented("\""); + } else { + Print("\""); + } + Print("%s\":", name); + attributes()->use(); +} + + +void JsonAstBuilder::AddAttribute(const char* name, Handle<String> value) { + SmartPointer<char> value_string = value->ToCString(); + AddAttributePrefix(name); + Print("\"%s\"", *value_string); +} + + +void JsonAstBuilder::AddAttribute(const char* name, const char* value) { + AddAttributePrefix(name); + Print("\"%s\"", value); +} + + +void JsonAstBuilder::AddAttribute(const char* name, int value) { + AddAttributePrefix(name); + Print("%d", value); +} + + +void JsonAstBuilder::AddAttribute(const char* name, bool value) { + AddAttributePrefix(name); + Print(value ? "true" : "false"); +} + + +void JsonAstBuilder::VisitBlock(Block* stmt) { + TagScope tag(this, "Block"); + VisitStatements(stmt->statements()); +} + + +void JsonAstBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { + TagScope tag(this, "ExpressionStatement"); + Visit(stmt->expression()); +} + + +void JsonAstBuilder::VisitEmptyStatement(EmptyStatement* stmt) { + TagScope tag(this, "EmptyStatement"); +} + + +void JsonAstBuilder::VisitIfStatement(IfStatement* stmt) { + TagScope tag(this, "IfStatement"); + Visit(stmt->condition()); + Visit(stmt->then_statement()); + Visit(stmt->else_statement()); +} + + +void JsonAstBuilder::VisitContinueStatement(ContinueStatement* stmt) { + TagScope tag(this, "ContinueStatement"); +} + + +void JsonAstBuilder::VisitBreakStatement(BreakStatement* stmt) { + TagScope tag(this, "BreakStatement"); +} + + +void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) { + TagScope tag(this, "ReturnStatement"); + Visit(stmt->expression()); +} + + +void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { + TagScope tag(this, "WithEnterStatement"); + Visit(stmt->expression()); +} + + +void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) { + TagScope tag(this, "WithExitStatement"); +} + + +void JsonAstBuilder::VisitSwitchStatement(SwitchStatement* stmt) { + TagScope tag(this, "SwitchStatement"); +} + + +void JsonAstBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { + TagScope tag(this, "DoWhileStatement"); + Visit(stmt->body()); + Visit(stmt->cond()); +} + + +void JsonAstBuilder::VisitWhileStatement(WhileStatement* stmt) { + TagScope tag(this, "WhileStatement"); + Visit(stmt->cond()); + Visit(stmt->body()); +} + + +void JsonAstBuilder::VisitForStatement(ForStatement* stmt) { + TagScope tag(this, "ForStatement"); + if (stmt->init() != NULL) Visit(stmt->init()); + if (stmt->cond() != NULL) Visit(stmt->cond()); + Visit(stmt->body()); + if (stmt->next() != NULL) Visit(stmt->next()); +} + + +void JsonAstBuilder::VisitForInStatement(ForInStatement* stmt) { + TagScope tag(this, "ForInStatement"); + Visit(stmt->each()); + Visit(stmt->enumerable()); + Visit(stmt->body()); +} + + +void JsonAstBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { + TagScope tag(this, "TryCatchStatement"); + Visit(stmt->try_block()); + Visit(stmt->catch_var()); + Visit(stmt->catch_block()); +} + + +void JsonAstBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { + TagScope tag(this, "TryFinallyStatement"); + Visit(stmt->try_block()); + Visit(stmt->finally_block()); +} + + +void JsonAstBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { + TagScope tag(this, "DebuggerStatement"); +} + + +void JsonAstBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { + TagScope tag(this, "FunctionLiteral"); + { + AttributesScope attributes(this); + AddAttribute("name", expr->name()); + } + VisitDeclarations(expr->scope()->declarations()); + VisitStatements(expr->body()); +} + + +void JsonAstBuilder::VisitSharedFunctionInfoLiteral( + SharedFunctionInfoLiteral* expr) { + TagScope tag(this, "SharedFunctionInfoLiteral"); +} + + +void JsonAstBuilder::VisitConditional(Conditional* expr) { + TagScope tag(this, "Conditional"); +} + + +void JsonAstBuilder::VisitSlot(Slot* expr) { + TagScope tag(this, "Slot"); + { + AttributesScope attributes(this); + switch (expr->type()) { + case Slot::PARAMETER: + AddAttribute("type", "PARAMETER"); + break; + case Slot::LOCAL: + AddAttribute("type", "LOCAL"); + break; + case Slot::CONTEXT: + AddAttribute("type", "CONTEXT"); + break; + case Slot::LOOKUP: + AddAttribute("type", "LOOKUP"); + break; + } + AddAttribute("index", expr->index()); + } +} + + +void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) { + if (expr->var()->rewrite() == NULL) { + TagScope tag(this, "VariableProxy"); + { + AttributesScope attributes(this); + AddAttribute("name", expr->name()); + AddAttribute("mode", Variable::Mode2String(expr->var()->mode())); + } + } else { + Visit(expr->var()->rewrite()); + } +} + + +void JsonAstBuilder::VisitLiteral(Literal* expr) { + TagScope tag(this, "Literal"); + { + AttributesScope attributes(this); + Handle<Object> handle = expr->handle(); + if (handle->IsString()) { + AddAttribute("handle", Handle<String>(String::cast(*handle))); + } else if (handle->IsSmi()) { + AddAttribute("handle", Smi::cast(*handle)->value()); + } + } +} + + +void JsonAstBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { + TagScope tag(this, "RegExpLiteral"); +} + + +void JsonAstBuilder::VisitObjectLiteral(ObjectLiteral* expr) { + TagScope tag(this, "ObjectLiteral"); +} + + +void JsonAstBuilder::VisitArrayLiteral(ArrayLiteral* expr) { + TagScope tag(this, "ArrayLiteral"); +} + + +void JsonAstBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { + TagScope tag(this, "CatchExtensionObject"); + Visit(expr->key()); + Visit(expr->value()); +} + + +void JsonAstBuilder::VisitAssignment(Assignment* expr) { + TagScope tag(this, "Assignment"); + { + AttributesScope attributes(this); + AddAttribute("op", Token::Name(expr->op())); + } + Visit(expr->target()); + Visit(expr->value()); +} + + +void JsonAstBuilder::VisitThrow(Throw* expr) { + TagScope tag(this, "Throw"); + Visit(expr->exception()); +} + + +void JsonAstBuilder::VisitProperty(Property* expr) { + TagScope tag(this, "Property"); + { + AttributesScope attributes(this); + AddAttribute("type", expr->is_synthetic() ? "SYNTHETIC" : "NORMAL"); + } + Visit(expr->obj()); + Visit(expr->key()); +} + + +void JsonAstBuilder::VisitCall(Call* expr) { + TagScope tag(this, "Call"); + Visit(expr->expression()); + VisitExpressions(expr->arguments()); +} + + +void JsonAstBuilder::VisitCallNew(CallNew* expr) { + TagScope tag(this, "CallNew"); + Visit(expr->expression()); + VisitExpressions(expr->arguments()); +} + + +void JsonAstBuilder::VisitCallRuntime(CallRuntime* expr) { + TagScope tag(this, "CallRuntime"); + { + AttributesScope attributes(this); + AddAttribute("name", expr->name()); + } + VisitExpressions(expr->arguments()); +} + + +void JsonAstBuilder::VisitUnaryOperation(UnaryOperation* expr) { + TagScope tag(this, "UnaryOperation"); + { + AttributesScope attributes(this); + AddAttribute("op", Token::Name(expr->op())); + } + Visit(expr->expression()); +} + + +void JsonAstBuilder::VisitIncrementOperation(IncrementOperation* expr) { + UNREACHABLE(); +} + + +void JsonAstBuilder::VisitCountOperation(CountOperation* expr) { + TagScope tag(this, "CountOperation"); + { + AttributesScope attributes(this); + AddAttribute("is_prefix", expr->is_prefix()); + AddAttribute("op", Token::Name(expr->op())); + } + Visit(expr->expression()); +} + + +void JsonAstBuilder::VisitBinaryOperation(BinaryOperation* expr) { + TagScope tag(this, "BinaryOperation"); + { + AttributesScope attributes(this); + AddAttribute("op", Token::Name(expr->op())); + } + Visit(expr->left()); + Visit(expr->right()); +} + + +void JsonAstBuilder::VisitCompareOperation(CompareOperation* expr) { + TagScope tag(this, "CompareOperation"); + { + AttributesScope attributes(this); + AddAttribute("op", Token::Name(expr->op())); + } + Visit(expr->left()); + Visit(expr->right()); +} + + +void JsonAstBuilder::VisitCompareToNull(CompareToNull* expr) { + TagScope tag(this, "CompareToNull"); + { + AttributesScope attributes(this); + AddAttribute("is_strict", expr->is_strict()); + } + Visit(expr->expression()); +} + + +void JsonAstBuilder::VisitThisFunction(ThisFunction* expr) { + TagScope tag(this, "ThisFunction"); +} + + +void JsonAstBuilder::VisitDeclaration(Declaration* decl) { + TagScope tag(this, "Declaration"); + { + AttributesScope attributes(this); + AddAttribute("mode", Variable::Mode2String(decl->mode())); + } + Visit(decl->proxy()); + if (decl->fun() != NULL) Visit(decl->fun()); +} + + +#endif // DEBUG + +} } // namespace v8::internal |