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

Christian Schafmeister chris.schaf at verizon.net
Tue Jan 7 10:50:00 PST 2014


On Jan 7, 2014, at 12:59 PM, Manuel Klimek <klimek at google.com> wrote:

> On Tue, Jan 7, 2014 at 6:52 PM, Christian Schafmeister <chris.schaf at verizon.net> wrote:
> 
> On Jan 7, 2014, at 12:12 PM, Manuel Klimek <klimek at google.com> wrote:
> 
>> On Tue, Jan 7, 2014 at 5:16 PM, Christian Schafmeister <chris.schaf at verizon.net> wrote:
>> Hey folks,
>> 
>> 
>> I’ve written a new Common Lisp environment/compiler over the past two years.  
>> It uses LLVM as the back-end (by exposing the LLVM C++ library to Common Lisp) and interoperates with C++ in that it has a template library like boost::python for exposing arbitrary C++ classes/functions to Common Lisp.  
>> 
>> I want to do some automated refactoring to improve my C++ code so I’m exposing the Clang ASTMatcher and Refactoring libraries.
>> 
>> I also think it would be really cool to write refactoring tools in a dynamic language like Lisp - without all the exhausting boilerplate required by the C++ approach.
>> 
>> C++ refactoring tools actually don't require that much boilerplate… 
> 
> Sorry, my statement sounded like a criticism - I never mean to criticize - these languages are what they are. 
> 
> No worries, I have no problems with criticism - and I didn't take it that way. My remark was really just meant as that - I think writing a refactoring tool has suprisingly little overhead. The main problem is actually compilation, which is why I'd be very interested in seeing more interpreted integrations.
>  
> I was just speaking about my feelings from writing a few simple refactoring tools in C++ and my motivations for implementing a Common Lisp compiler and writing refactoring tools in Common Lisp.  I’m a new convert to Common Lisp - I just discovered it two years ago and most of my experience with it is writing a self-hosting compiler.
> 
> 
>>  
>> So I’m exposing the Clang AST library to this Common Lisp environment with the goal of writing a general tool for writing C++ refactoring tools in Common Lisp.
>> 
>> My goal is to mimic C++ ASTMatchers like:
>> 
>> recordDecl(hasDescendant(
>>     ifStmt(hasTrueExpression(
>>         expr(hasDescendant(
>>             ifStmt()))))))
>> 
>> Using S-expressions: (record-decl (has-descendent (if-stmt (has-true-expression (expr (has-descendant( if-stmt)))))))    
>> 
>> And the source-to-source translation code will be small lambda functions that use the resulting MatchResults.
>> 
>> That way I don’t have to write a lot of documentation :-).
>> 
>> Currently I’m looking at calling the ASTMatcher/Dynamic/VariantValue interface to build ASTMatchers from S-expressions - does that sound like a good idea - or is there a better approach I should be exploring?
>> 
>> Well, if your boost shim can already match "arbitrary C++ classes / functions", then it should in principle be able to expose the AST matchers as is (without the need to go through the dynamic parsing).
>> After all, the matchers are mostly just template functions :)
> 
> I was trying to figure out how to do that at first but the ASTMatchers looked more exotic than just simple functions.
> 
> For instance “namedDecl” has the type internal::VariadicDynCastAllOfMatcher<Decl,NamedDecl>
> VariadicDynCastAllOfMatcher is defined as:
> 
> template <typename SourceT, typename TargetT>
> class VariadicDynCastAllOfMatcher
>     : public llvm::VariadicFunction<
>         BindableMatcher<SourceT>, Matcher<TargetT>,
>         makeDynCastAllOfComposite<SourceT, TargetT> > {
> public:
>   VariadicDynCastAllOfMatcher() {}
> };
> 
> llvm::VariadicFunction has many templated overloads of "operator()"
> I haven’t written template code to automatically wrap variadic functions (as in functions that take … ellipses).
> 
> I can wrap functions that take ArrayRef’s though - is there a function like namedDecl(ArrayRef<ASTMatcher>) for ASTMatchers?
> 
> I’ve only been getting deep into C++ template programming for about two months so I’m still struggling with reading complex template code.
> 
> Yes, I'd actually be suprised if this was possible without major jump-through-hooping - the problem is that the compiler generates the template code only when they get instantiated - so unless you have a backend that takes the lisp code and generates C++ code from that that integrates with the template code, I wouldn't know how to do it (and that round-trip would seem like it kills a lot of the benefits of having lisp in the first place - after all, you'd still get crappy C++ error messages :P)

Agreed.   

Maybe the best way to do this is to write a Registry class like the one in Dynamic/Registry.h and define “constructMatcher” and “constructBoundMatcher” that take Lisp symbols and assemble VariantMatchers that way.




> 
> 
> 
> 
> 
>> 
>> Otherwise I think going the dynamic matcher route is a good approach.
>> 
>> Cheers,
>> /Manuel
> 
> 

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


More information about the cfe-dev mailing list