[cfe-dev] Writing C++ refactoring tools in Common Lisp

Christian Schafmeister chris.schaf at verizon.net
Mon Jan 13 14:50:03 PST 2014

On Jan 13, 2014, at 5:19 PM, Samuel Benzaquen <sbenza at google.com> wrote:

> On Mon, Jan 13, 2014 at 3:18 PM, Christian Schafmeister <meister at temple.edu> wrote:
> So, I managed to hack/rewrite parts of Registry.cpp, Registry.h, Marshaller.h and Diagnostics.h so that they work with Common Lisp Symbols and Conses.
> I can now assemble ASTMatchers from s-expressions.   
> I exposed the entire ASTMatcher interface in one go - so I can write any ASTMatcher using S-expressions that can be written with the C++ DSL.
> Using the C++ DSL you would use:
> fieldDecl(hasType(recordDecl(isDerivedFrom(recordDecl(hasName(“GCObject”)))))).bind(“all”)
> In Common Lisp I would use:
> (:bind :all (:field-decl (:has-type (:record-decl (:is-derived-from (:record-decl (:has-name "GCObject"))))))))
> Question:
> How do you get proficient at writing these matchers?   I still struggle with it.   
> In theory, they should read as english (with some bad grammar =P).
> In your example, it reads as:
> "A <fieldDecl> that a <hasType> that is a <recordDecl> which <isDerivedFrom> ..."
> In my experience, the hardest part is figuring out which matchers to use (which basically requires knowing about them), not how to assemble them. 

Thanks - that helps. 

> Do you have some way of looking at the AST dumps and then inverting them in your head into queries?
> I don't see what you mean by inverting.

I got that from the first talk that I saw Chandler Carruth present on the ASTMatcher library:
http://www.youtube.com/watch?v=mVbDzTM21BQ     at 14:40

It sounded fascinating and planted this idea of exposing the ASTMatcher library in the Common Lisp system/compiler that I was just starting to write.

I still have no clear idea what he was talking about “...invert the AST and turn it into a set of matchers…” but it sounded compelling - hilarious huh?

> There are two types of matchers: filters and traversal.
> The filters check properties on the nodes, like "hasName()".
> The traversal matchers help you reach other nodes in the AST, like "hasType()”.

Two types of matchers - filter & traversal - that part I get - what about Narrowing matchers?
The traversal matchers somewhat correspond to methods of the node classes that they traverse from - right?
Like Expr nodes have a Expr::getType() method and an "expr()" matcher can have a “hasType()” matcher as an argument - as in “expr(hasType(…))”?

Can you help me understand the docs on http://clang.llvm.org/docs/LibASTMatchersReference.html?
There are the rows with three columns “Return Type” “Name” “Parameters”.
I understand the type of the parameters.  What does the “Return type” tell us?  Does it mean that you can only use that matcher X as a parameter of matcher Y if matcher Y accepts matcher Xs “Return Type” (or a more derived type) as a “Parameters” type?

> There are various trees that are interconnected; expressions, declarations and types. Matchers allow you to go from one to the other.
> Eg. you can go from an expression (like &a->foo) to its type, from a type to some expression (like getting the initializer for a member field), etc.
> In each tree you can also go up and down the hierarchies. Eg. you can go from Foo[] type to Foo, or from "1+foo->bar()" to "1" and "foo->bar()”.

Ok, that is very helpful - thank you.



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140113/b7a3432a/attachment.html>

More information about the cfe-dev mailing list