<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 15, 2017 at 5:39 AM, Richard Braun via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-m_-6269180875227927887gmail-">On Wed, Feb 15, 2017 at 10:00:25AM +0000, Manuel Klimek wrote:<br>
> Both of these projects duplicate a lot of code from clang-tidy and the AST<br>
> matcher infrastructure in clang.<br>
><br>
> I'd be curious what the reasons are to not use those, so we can try to<br>
> address them :)<br>
<br>
</span>I tried using matchers at some point, but couldn't understand the<br>
processing flow and felt a lot more comfortable with the current result<br>
despite writing more code.<br></blockquote><div><br></div><div><br></div><div>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!).</div><div><br></div><div><a href="https://docs.google.com/document/d/1foYulTnUXumiuGzzgoAbGQLFJerk4X1WjR2cKBUUMJI/edit?usp=sharing" target="_blank">https://docs.google.com/<wbr>document/d/<wbr>1foYulTnUXumiuGzzgoAbGQLFJerk4<wbr>X1WjR2cKBUUMJI/edit?usp=<wbr>sharing</a><br></div><div><br></div><div>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.</div><div><br></div><div>In a more traditional OO implementation of the tree interpreter pattern it would look something like (pseudocode):</div><div><br></div><div><br></div><div>class MatcherBase {</div><div>  std::vector<std::unique_ptr<<wbr>MatcherBase>> Children;</div><div><br></div><div>  virtual bool matches(ASTNode &Node) = 0;</div><div><br></div><div>...</div><div><br></div><div>}</div><div><br></div><div><div>class AllOfMatcher : public MatcherBase {</div><div>  bool matches(ASTNode &Node) override {</div><div>    for (auto &Matcher : Children)</div><div>      if (!Matcher->matches(Node))</div><div>        return false;<br>    return true;<br>  }</div><div><br></div><div>...</div><div><br></div><div>}</div></div><div><br></div><div>std::unique_ptr<MatcherBase> allOf(std::vector<std::unique_<wbr>ptr<MatcherBase>> Children) {</div><div>  return make_unique<AllOfMatcher>(<wbr>Children);</div><div>}</div><div><br></div><div><div>class CallExprMatcher : public AllOfMatcher {</div><div>  bool matches(ASTNode &Node) override {</div><div>    if (!AllOfMatcher::matches(Node))</div><div>      return false;</div><div>    return isa<CallExpr(Node);</div><div>  }</div><div><br></div><div>...</div><div><br></div><div>}</div></div><div><br></div><div><div><br class="gmail-Apple-interchange-newline">std::unique_ptr<MatcherBase> callExpr(std::vector<std::unique_<wbr>ptr<MatcherBase>> Children) {</div><div>  return make_unique<CallExprMatcher>(<wbr>Children);</div><div>}</div></div><div><br></div><div><br></div><div><div>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)</div></div><div><br></div><div>For example, if you look at the implementation of the `callExpr` matcher, you see:</div><div><br></div><div>```</div><div>const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;<br></div><div>```</div><div><br></div><div>"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)<br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>(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)</div><div><br></div><div>-- Sean Silva</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<span class="gmail-m_-6269180875227927887gmail-HOEnZb"><font color="#888888"><br>
--<br>
Richard Braun<br>
</font></span><div class="gmail-m_-6269180875227927887gmail-HOEnZb"><div class="gmail-m_-6269180875227927887gmail-h5">______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br></div></div>