On Wed, Feb 15, 2017 at 5:39 AM, Richard Braun via cfe-dev < cfe-...@lists.llvm.org> wrote:
> On Wed, Feb 15, 2017 at 10:00:25AM +0000, Manuel Klimek wrote: > > Both of these projects duplicate a lot of code from clang-tidy and the > AST > > matcher infrastructure in clang. > > > > I'd be curious what the reasons are to not use those, so we can try to > > address them :) > > I tried using matchers at some point, but couldn't understand the > processing flow and felt a lot more comfortable with the current result > despite writing more code. > The thing that made it click for me is that the way it works is basically a classic "tree interpreter" type pattern. I wrote up some ideas for improving the documentation a long time ago when I was staring at it, though I don't think it ever made it to the mailing list (oops!). https://docs.google.com/document/d/1foYulTnUXumiuGzzgoAbGQLFJerk4 X1WjR2cKBUUMJI/edit?usp=sharing I think this started out as a reply in an email and then I saved it into a document as it morphed into ideas for implementing the dynamic AST matches in a way that doesn't require stamping out huge amounts of text (as in machine code; essentially it instantiates each matcher separately resulting in huge .o files instead of using a "data-driven" approach based on the node type enums). Don't really clearly remember though. In a more traditional OO implementation of the tree interpreter pattern it would look something like (pseudocode): class MatcherBase { std::vector<std::unique_ptr<MatcherBase>> Children; virtual bool matches(ASTNode &Node) = 0; ... } class AllOfMatcher : public MatcherBase { bool matches(ASTNode &Node) override { for (auto &Matcher : Children) if (!Matcher->matches(Node)) return false; return true; } ... } std::unique_ptr<MatcherBase> allOf(std::vector<std::unique_ptr<MatcherBase>> Children) { return make_unique<AllOfMatcher>(Children); } class CallExprMatcher : public AllOfMatcher { bool matches(ASTNode &Node) override { if (!AllOfMatcher::matches(Node)) return false; return isa<CallExpr(Node); } ... } std::unique_ptr<MatcherBase> callExpr(std::vector<std::unique_ptr<MatcherBase>> Children) { return make_unique<CallExprMatcher>(Children); } The implementation actually looks essentially like this, except that it is static instead of dynamic and so the body of the `matches` virtual method essentially ends up inside templates and macros somewhere and isn't actually a virtual function) For example, if you look at the implementation of the `callExpr` matcher, you see: ``` const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; ``` "dyn_cast AllOfMatcher" does pretty much what you expect based on looking at the toy OO pseudocode above. (the need to pass the Stmt template argument is not that relevant; it could probably be inferred by following the inheritance chain from CallExpr up to the top of the inheritance hierarchy) (I've been totally out of the loop for quite a while for all the stuff that Manuel et al. have been doing with Clang tooling; so all of this is subject to being out of date or just remembered incorrectly) -- Sean Silva > > -- > Richard Braun > _______________________________________________ > cfe-dev mailing list > cfe-...@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev >
_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest