Change --print-ast output to be more regular.

The print-ast output is useful for debugging front end issues.  It is a mix
of fully-parenthesized prefix notation (i.e., Lisp S-expressions) with some
infix.

It is not valid S-expressions for various other reasons.  Most obviously, it
uses ' (single quote) instead of " (double quote) to delimit strings.

This change makes the print-ast output a valid Scheme S-expression.  It can
be pretty printed by copying it, quoting it (by preceding it with a single
quote), and evaluating it at the REPL of a Scheme implementation.

Also, the AST node pretty names are changed to predictably match the class
name.  It doesn't seem helpful to have them be arbitrary.

BUG=
R=regis@google.com

Review URL: https://codereview.chromium.org//23923005

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@27282 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
kmillikin@google.com
2013-09-09 10:20:55 +00:00
parent 72e13620a7
commit e9eec70cad
6 changed files with 170 additions and 179 deletions
+17 -14
View File
@@ -12,19 +12,21 @@
namespace dart {
#define DEFINE_VISIT_FUNCTION(type, name) \
void type::Visit(AstNodeVisitor* visitor) { \
visitor->Visit##type(this); \
}
NODE_LIST(DEFINE_VISIT_FUNCTION)
#define DEFINE_VISIT_FUNCTION(BaseName) \
void BaseName##Node::Visit(AstNodeVisitor* visitor) { \
visitor->Visit##BaseName##Node(this); \
}
FOR_EACH_NODE(DEFINE_VISIT_FUNCTION)
#undef DEFINE_VISIT_FUNCTION
#define DEFINE_NAME_FUNCTION(type, name) \
const char* type::PrettyName() const { \
return name; \
}
NODE_LIST(DEFINE_NAME_FUNCTION)
#define DEFINE_NAME_FUNCTION(BaseName) \
const char* BaseName##Node::PrettyName() const { \
return #BaseName; \
}
FOR_EACH_NODE(DEFINE_NAME_FUNCTION)
#undef DEFINE_NAME_FUNCTION
@@ -35,12 +37,13 @@ class AstNodeCollector : public AstNodeVisitor {
explicit AstNodeCollector(GrowableArray<AstNode*>* nodes)
: nodes_(nodes) { }
#define DEFINE_VISITOR_FUNCTION(type, name) \
virtual void Visit##type(type* node) { \
#define DEFINE_VISITOR_FUNCTION(BaseName) \
virtual void Visit##BaseName##Node(BaseName##Node* node) { \
nodes_->Add(node); \
node->VisitChildren(this); \
}
NODE_LIST(DEFINE_VISITOR_FUNCTION)
FOR_EACH_NODE(DEFINE_VISITOR_FUNCTION)
#undef DEFINE_VISITOR_FUNCTION
private:
@@ -151,7 +154,7 @@ bool ComparisonNode::IsKindValid() const {
const char* ComparisonNode::TokenName() const {
return Token::Str(kind_);
return (kind_ == Token::kAS) ? "as" : Token::Str(kind_);
}
+58 -56
View File
@@ -15,56 +15,56 @@
namespace dart {
#define NODE_LIST(V) \
V(ReturnNode, "return") \
V(LiteralNode, "literal") \
V(TypeNode, "type") \
V(AssignableNode, "assignable") \
V(BinaryOpNode, "binop") \
V(BinaryOpWithMask32Node, "binop with mask 32") \
V(ComparisonNode, "compare") \
V(UnaryOpNode, "unaryop") \
V(ConditionalExprNode, "?:") \
V(IfNode, "if") \
V(SwitchNode, "switch") \
V(CaseNode, "case") \
V(WhileNode, "while") \
V(DoWhileNode, "dowhile") \
V(ForNode, "for") \
V(JumpNode, "jump") \
V(ArgumentListNode, "args") \
V(ArrayNode, "array") \
V(ClosureNode, "closure") \
V(InstanceCallNode, "instance call") \
V(StaticCallNode, "static call") \
V(ClosureCallNode, "closure call") \
V(CloneContextNode, "clone context") \
V(ConstructorCallNode, "constructor call") \
V(InstanceGetterNode, "instance getter call") \
V(InstanceSetterNode, "instance setter call") \
V(StaticGetterNode, "static getter") \
V(StaticSetterNode, "static setter") \
V(NativeBodyNode, "native body") \
V(PrimaryNode, "primary") \
V(LoadLocalNode, "load local") \
V(StoreLocalNode, "store local") \
V(LoadInstanceFieldNode, "load field") \
V(StoreInstanceFieldNode, "store field") \
V(LoadStaticFieldNode, "load static field") \
V(StoreStaticFieldNode, "store static field") \
V(LoadIndexedNode, "load indexed") \
V(StoreIndexedNode, "store indexed") \
V(SequenceNode, "seq") \
V(LetNode, "let") \
V(CatchClauseNode, "catch clause block") \
V(TryCatchNode, "try catch block") \
V(ThrowNode, "throw") \
V(InlinedFinallyNode, "inlined finally") \
#define FOR_EACH_NODE(V) \
V(Return) \
V(Literal) \
V(Type) \
V(Assignable) \
V(BinaryOp) \
V(BinaryOpWithMask32) \
V(Comparison) \
V(UnaryOp) \
V(ConditionalExpr) \
V(If) \
V(Switch) \
V(Case) \
V(While) \
V(DoWhile) \
V(For) \
V(Jump) \
V(ArgumentList) \
V(Array) \
V(Closure) \
V(InstanceCall) \
V(StaticCall) \
V(ClosureCall) \
V(CloneContext) \
V(ConstructorCall) \
V(InstanceGetter) \
V(InstanceSetter) \
V(StaticGetter) \
V(StaticSetter) \
V(NativeBody) \
V(Primary) \
V(LoadLocal) \
V(StoreLocal) \
V(LoadInstanceField) \
V(StoreInstanceField) \
V(LoadStaticField) \
V(StoreStaticField) \
V(LoadIndexed) \
V(StoreIndexed) \
V(Sequence) \
V(Let) \
V(CatchClause) \
V(TryCatch) \
V(Throw) \
V(InlinedFinally) \
#define DEFINE_FORWARD_DECLARATION(type, name) class type;
NODE_LIST(DEFINE_FORWARD_DECLARATION)
#undef DEFINE_FORWARD_DECLARATION
#define FORWARD_DECLARATION(BaseName) class BaseName##Node;
FOR_EACH_NODE(FORWARD_DECLARATION)
#undef FORWARD_DECLARATION
// Abstract class to implement an AST node visitor. An example is AstPrinter.
@@ -73,9 +73,10 @@ class AstNodeVisitor : public ValueObject {
AstNodeVisitor() {}
virtual ~AstNodeVisitor() {}
#define DEFINE_VISITOR_FUNCTION(type, name) \
virtual void Visit##type(type* node) { }
NODE_LIST(DEFINE_VISITOR_FUNCTION)
#define DEFINE_VISITOR_FUNCTION(BaseName) \
virtual void Visit##BaseName##Node(BaseName##Node* node) { }
FOR_EACH_NODE(DEFINE_VISITOR_FUNCTION)
#undef DEFINE_VISITOR_FUNCTION
private:
@@ -99,10 +100,11 @@ class AstNode : public ZoneAllocated {
intptr_t token_pos() const { return token_pos_; }
#define AST_TYPE_CHECK(type, name) \
virtual bool Is##type() const { return false; } \
virtual type* As##type() { return NULL; }
NODE_LIST(AST_TYPE_CHECK)
#define AST_TYPE_CHECK(BaseName) \
virtual bool Is##BaseName##Node() const { return false; } \
virtual BaseName##Node* As##BaseName##Node() { return NULL; }
FOR_EACH_NODE(AST_TYPE_CHECK)
#undef AST_TYPE_CHECK
virtual void Visit(AstNodeVisitor* visitor) = 0;
@@ -893,7 +895,7 @@ class DoWhileNode : public AstNode {
};
// initializer, condition, increment expressions can be NULL.
// The condition can be NULL.
class ForNode : public AstNode {
public:
ForNode(intptr_t token_pos,
+79 -99
View File
@@ -24,17 +24,16 @@ void AstPrinter::VisitGenericAstNode(AstNode* node) {
}
void AstPrinter::VisitSequenceNode(SequenceNode* node_sequence) {
void AstPrinter::VisitSequenceNode(SequenceNode* node) {
// TODO(regis): Make the output more readable by indenting the nested
// sequences. This could be achieved using a AstPrinterContext similar to the
// CodeGeneratorContext.
ASSERT(node_sequence != NULL);
for (int i = 0; i < node_sequence->length(); i++) {
OS::Print("scope %p: ",
node_sequence->scope());
node_sequence->NodeAt(i)->Visit(this);
OS::Print("(%s (scope \"%p\")", node->PrettyName(), node->scope());
for (int i = 0; i < node->length(); ++i) {
OS::Print("\n");
node->NodeAt(i)->Visit(this);
}
OS::Print(")");
}
@@ -55,17 +54,19 @@ void AstPrinter::VisitReturnNode(ReturnNode* node) {
void AstPrinter::VisitGenericLocalNode(AstNode* node,
const LocalVariable& var) {
OS::Print("(%s %s%s '%s'",
OS::Print("(%s %s%s \"%s\"",
node->PrettyName(),
var.is_final() ? "final " : "",
String::Handle(var.type().Name()).ToCString(),
var.name().ToCString());
if (var.HasIndex()) {
OS::Print(" @%d", var.index());
if (var.is_captured()) {
OS::Print(" ctx %d", var.owner()->context_level());
OS::Print(" (context %d %d)", var.owner()->context_level(), var.index());
} else {
OS::Print(" (stack %d)", var.index());
}
}
OS::Print(" ");
node->VisitChildren(this);
OS::Print(")");
}
@@ -82,7 +83,7 @@ void AstPrinter::VisitStoreLocalNode(StoreLocalNode* node) {
void AstPrinter::VisitGenericFieldNode(AstNode* node, const Field& field) {
OS::Print("(%s %s%s '%s' ",
OS::Print("(%s %s%s \"%s\" ",
node->PrettyName(),
field.is_final() ? "final " : "",
String::Handle(AbstractType::Handle(field.type()).Name()).
@@ -125,59 +126,63 @@ void AstPrinter::VisitArrayNode(ArrayNode* node) {
void AstPrinter::VisitLiteralNode(LiteralNode* node) {
const Instance& literal = node->literal();
OS::Print("'%s'", literal.ToCString());
OS::Print("(%s \"%s\")", node->PrettyName(), literal.ToCString());
}
void AstPrinter::VisitTypeNode(TypeNode* node) {
const AbstractType& type = node->type();
OS::Print("'%s'", String::Handle(type.Name()).ToCString());
OS::Print("(%s \"%s\")",
node->PrettyName(),
String::Handle(type.Name()).ToCString());
}
void AstPrinter::VisitAssignableNode(AssignableNode* node) {
OS::Print("(assignable ");
node->expr()->Visit(this);
const AbstractType& type = node->type();
const String& dst_name = node->dst_name();
OS::Print(" to type '%s' of '%s')",
OS::Print("(%s (type \"%s\") (of \"%s\") ",
node->PrettyName(),
String::Handle(type.Name()).ToCString(),
dst_name.ToCString());
node->VisitChildren(this);
OS::Print(")");
}
void AstPrinter::VisitPrimaryNode(PrimaryNode* node) {
OS::Print("***** PRIMARY NODE IN AST ***** (primary '%s')",
OS::Print("*****%s***** \"%s\")",
node->PrettyName(),
node->primary().ToCString());
}
void AstPrinter::VisitComparisonNode(ComparisonNode* node) {
if (node->kind() == Token::kAS) {
OS::Print("(as ");
node->VisitChildren(this);
OS::Print(")");
} else {
VisitGenericAstNode(node);
}
}
void AstPrinter::VisitBinaryOpNode(BinaryOpNode* node) {
VisitGenericAstNode(node);
}
void AstPrinter::VisitBinaryOpWithMask32Node(BinaryOpWithMask32Node* node) {
OS::Print("(%s %s", node->PrettyName(), node->TokenName());
OS::Print("(%s %s ", node->PrettyName(), node->TokenName());
node->VisitChildren(this);
OS::Print(" & 0x%" Px64 "", node->mask32());
OS::Print(")");
}
void AstPrinter::VisitBinaryOpNode(BinaryOpNode* node) {
OS::Print("(%s %s ", node->PrettyName(), node->TokenName());
node->VisitChildren(this);
OS::Print(")");
}
void AstPrinter::VisitBinaryOpWithMask32Node(BinaryOpWithMask32Node* node) {
OS::Print("(%s %s ", node->PrettyName(), node->TokenName());
node->VisitChildren(this);
OS::Print(" & \"0x%" Px64 "", node->mask32());
OS::Print("\")");
}
void AstPrinter::VisitUnaryOpNode(UnaryOpNode* node) {
VisitGenericAstNode(node);
OS::Print("(%s %s ", node->PrettyName(), node->TokenName());
node->VisitChildren(this);
OS::Print(")");
}
@@ -187,25 +192,17 @@ void AstPrinter::VisitConditionalExprNode(ConditionalExprNode* node) {
void AstPrinter::VisitIfNode(IfNode* node) {
OS::Print("(if ");
node->condition()->Visit(this);
OS::Print(" then ");
node->true_branch()->Visit(this);
OS::Print(" else ");
if (node->false_branch() != NULL) {
node->false_branch()->Visit(this);
}
OS::Print(")");
VisitGenericAstNode(node);
}
void AstPrinter::VisitCaseNode(CaseNode* node) {
OS::Print("(case (");
OS::Print("(%s (", node->PrettyName());
for (int i = 0; i < node->case_expressions()->length(); i++) {
node->case_expressions()->NodeAt(i)->Visit(this);
}
if (node->contains_default()) {
OS::Print(" default ");
OS::Print(" default");
}
OS::Print(")");
node->statements()->Visit(this);
@@ -214,47 +211,39 @@ void AstPrinter::VisitCaseNode(CaseNode* node) {
void AstPrinter::VisitSwitchNode(SwitchNode* node) {
OS::Print("(switch ");
node->body()->Visit(this);
OS::Print(")");
VisitGenericAstNode(node);
}
void AstPrinter::VisitWhileNode(WhileNode* node) {
OS::Print("(while ");
node->condition()->Visit(this);
OS::Print(" do ");
node->body()->Visit(this);
OS::Print(")");
VisitGenericAstNode(node);
}
void AstPrinter::VisitForNode(ForNode* node) {
OS::Print("(for (init: ");
// Complicated because the condition is optional and so we clearly want to
// indicate the subparts.
OS::Print("(%s (init ", node->PrettyName());
node->initializer()->Visit(this);
OS::Print("; cond:");
if (node->condition() != NULL) {
OS::Print(") (cond ");
node->condition()->Visit(this);
}
OS::Print("; incr:");
OS::Print(") (update ");
node->increment()->Visit(this);
OS::Print(") body:");
OS::Print(") ");
node->body()->Visit(this);
OS::Print("endfor)");
}
void AstPrinter::VisitDoWhileNode(DoWhileNode* node) {
OS::Print("(do ");
node->body()->Visit(this);
OS::Print(" while ");
node->condition()->Visit(this);
OS::Print(")");
}
void AstPrinter::VisitDoWhileNode(DoWhileNode* node) {
VisitGenericAstNode(node);
}
void AstPrinter::VisitJumpNode(JumpNode* node) {
OS::Print("(%s %s %s in scope %p)",
OS::Print("(%s %s %s (scope \"%p\"))",
node->PrettyName(),
node->TokenName(),
node->label()->name().ToCString(),
@@ -263,23 +252,25 @@ void AstPrinter::VisitJumpNode(JumpNode* node) {
void AstPrinter::VisitInstanceCallNode(InstanceCallNode* node) {
OS::Print("(%s '%s'(", node->PrettyName(), node->function_name().ToCString());
OS::Print("(%s \"%s\" ",
node->PrettyName(),
node->function_name().ToCString());
node->VisitChildren(this);
OS::Print("))");
OS::Print(")");
}
void AstPrinter::VisitStaticCallNode(StaticCallNode* node) {
const char* function_fullname = node->function().ToFullyQualifiedCString();
OS::Print("(%s '%s'(", node->PrettyName(), function_fullname);
OS::Print("(%s \"%s\" ", node->PrettyName(), function_fullname);
node->VisitChildren(this);
OS::Print("))");
OS::Print(")");
}
void AstPrinter::VisitClosureNode(ClosureNode* node) {
const char* function_fullname = node->function().ToFullyQualifiedCString();
OS::Print("(%s '%s')", node->PrettyName(), function_fullname);
OS::Print("(%s \"%s\")", node->PrettyName(), function_fullname);
}
@@ -291,48 +282,47 @@ void AstPrinter::VisitClosureCallNode(ClosureCallNode* node) {
void AstPrinter::VisitConstructorCallNode(ConstructorCallNode* node) {
const char* kind = node->constructor().IsFactory() ? "factory " : "";
const char* constructor_name = node->constructor().ToFullyQualifiedCString();
OS::Print("(%s %s'%s' ((this)", node->PrettyName(), kind, constructor_name);
OS::Print("(%s %s \"%s\" ", node->PrettyName(), kind, constructor_name);
node->VisitChildren(this);
OS::Print("))");
OS::Print(")");
}
void AstPrinter::VisitInstanceGetterNode(InstanceGetterNode* node) {
OS::Print("(%s 'get %s'(",
OS::Print("(%s \"%s\" ",
node->PrettyName(),
node->field_name().ToCString());
node->VisitChildren(this);
OS::Print("))");
OS::Print(")");
}
void AstPrinter::VisitInstanceSetterNode(InstanceSetterNode* node) {
OS::Print("(%s 'set %s'(",
OS::Print("(%s \"%s\" ",
node->PrettyName(),
node->field_name().ToCString());
node->VisitChildren(this);
OS::Print("))");
OS::Print(")");
}
void AstPrinter::VisitStaticGetterNode(StaticGetterNode* node) {
String& class_name = String::Handle(node->cls().Name());
OS::Print("(%s '%s.%s'(",
OS::Print("(%s \"%s.%s\")",
node->PrettyName(),
class_name.ToCString(),
node->field_name().ToCString());
OS::Print("))");
}
void AstPrinter::VisitStaticSetterNode(StaticSetterNode* node) {
String& class_name = String::Handle(node->cls().Name());
OS::Print("(%s '%s.%s'(",
OS::Print("(%s \"%s.%s\" ",
node->PrettyName(),
class_name.ToCString(),
node->field_name().ToCString());
node->VisitChildren(this);
OS::Print("))");
OS::Print(")");
}
@@ -351,39 +341,29 @@ void AstPrinter::VisitStoreIndexedNode(StoreIndexedNode* node) {
void AstPrinter::VisitNativeBodyNode(NativeBodyNode* node) {
OS::Print("(native_c call '%s'(%d args))",
OS::Print("(%s \"%s\" (%d args))",
node->PrettyName(),
node->native_c_function_name().ToCString(),
NativeArguments::ParameterCountForResolution(node->function()));
}
void AstPrinter::VisitCatchClauseNode(CatchClauseNode* node) {
node->VisitChildren(this);
VisitGenericAstNode(node);
}
void AstPrinter::VisitTryCatchNode(TryCatchNode* node) {
OS::Print("(");
// First visit the try block.
OS::Print("(try block (");
OS::Print("(%s ", node->PrettyName());
node->try_block()->Visit(this);
OS::Print("))");
// Now visit the catch block if it exists.
if (node->catch_block() != NULL) {
OS::Print("(catch block () (");
node->catch_block()->Visit(this);
OS::Print("))");
}
// Now visit the finally block if it exists.
if (node->finally_block() != NULL) {
OS::Print("(finally block () (");
OS::Print("(finally ");
node->finally_block()->Visit(this);
OS::Print("))");
OS::Print(")");
}
OS::Print(")");
}
+5 -4
View File
@@ -21,10 +21,11 @@ class AstPrinter : public AstNodeVisitor {
static void PrintLocalScope(const LocalScope* scope, int variable_index);
#define DEFINE_VISITOR_FUNCTION(type, name) \
virtual void Visit##type(type* node);
NODE_LIST(DEFINE_VISITOR_FUNCTION)
#undef DEFINE_VISITOR_FUNCTION
#define DECLARE_VISITOR_FUNCTION(BaseName) \
virtual void Visit##BaseName##Node(BaseName##Node* node);
FOR_EACH_NODE(DECLARE_VISITOR_FUNCTION)
#undef DECLARE_VISITOR_FUNCTION
private:
AstPrinter();
+5 -3
View File
@@ -208,9 +208,11 @@ class EffectGraphVisitor : public AstNodeVisitor {
entry_(NULL),
exit_(NULL) { }
#define DEFINE_VISIT(type, name) virtual void Visit##type(type* node);
NODE_LIST(DEFINE_VISIT)
#undef DEFINE_VISIT
#define DECLARE_VISIT(BaseName) \
virtual void Visit##BaseName##Node(BaseName##Node* node);
FOR_EACH_NODE(DECLARE_VISIT)
#undef DECLARE_VISIT
FlowGraphBuilder* owner() const { return owner_; }
intptr_t temp_index() const { return temp_index_; }
+6 -3
View File
@@ -77,9 +77,12 @@ static bool IsCallRecursive(const Function& function, Definition* call) {
class ChildrenVisitor : public AstNodeVisitor {
public:
ChildrenVisitor() { }
#define DEFINE_VISIT(type, name) \
virtual void Visit##type(type* node) { node->VisitChildren(this); }
NODE_LIST(DEFINE_VISIT);
#define DEFINE_VISIT(BaseName) \
virtual void Visit##BaseName##Node(BaseName##Node* node) { \
node->VisitChildren(this); \
}
FOR_EACH_NODE(DEFINE_VISIT);
#undef DEFINE_VISIT
};