<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jun 11, 2020, at 11:50 AM, Madhur Amilkanthwar <<a href="mailto:madhur13490@gmail.com" class="">madhur13490@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="auto" class="">Sounds interesting. It would be a good addition if you can support a bit of type system and ensuring type sanity too somehow.</div></div></blockquote><div>That was part of my original plan, still thinking on how to make good use of the type system.</div><div><br class=""></div><div>-Min</div><br class=""><blockquote type="cite" class=""><div class=""><br class=""><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 12, 2020, 12:02 AM Min-Yih Hsu via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space" class="">Hi Clang folks,<div class=""><br class=""></div><div class="">Recently I have been working on a side project, Nacro (<a href="https://github.com/mshockwave/nacro" target="_blank" rel="noreferrer" class="">https://github.com/mshockwave/nacro</a>), that you might find interesting.</div><div class=""><br class=""></div><div class=""><span style="" class="">Nacro is a small DSL aim to provide a better C/C++ macro experience. Here is an example:</span></div><div class=""><span style="" class="">```</span></div><div class=""><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;padding:16px;overflow:auto;line-height:1.45;background-color:rgb(246,248,250);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;color:rgb(36,41,46);font-variant-ligatures:normal" class="">#<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">pragma</span> nacro rule myPrint
(val:$expr) -> $stmt {
    <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">printf</span>(<span style="box-sizing:border-box;color:rgb(3,47,98)" class=""><span style="box-sizing:border-box" class="">"</span>%d<span style="box-sizing:border-box" class="">\n</span><span style="box-sizing:border-box" class="">"</span></span>, val * <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">2</span>)
}

#<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">pragma</span> nacro rule genColors
(cases:$expr*) -> {
    $<span style="box-sizing:border-box;color:rgb(0,92,197)" class="">loop</span>(c in cases) {
        <span style="box-sizing:border-box;color:rgb(215,58,73)" class="">case</span> c:
        <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">printf</span>(<span style="box-sizing:border-box;color:rgb(3,47,98)" class=""><span style="box-sizing:border-box" class="">"</span>the color is %s<span style="box-sizing:border-box" class="">\n</span><span style="box-sizing:border-box" class="">"</span></span>, $<span style="box-sizing:border-box;color:rgb(0,92,197)" class="">str</span>(c));
        <span style="box-sizing:border-box;color:rgb(215,58,73)" class="">break</span>;
    }
}

<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">enum</span> Color { RED, BLUE, YELLOW };
<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">void</span> <span style="box-sizing:border-box;color:rgb(111,66,193)" class="">printColor</span>(<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">enum</span> Color color) {
    <span style="box-sizing:border-box;color:rgb(215,58,73)" class="">switch</span>(color) <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">genColors</span>(RED, BLUE, YELLOW)
}

<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">int</span> <span style="box-sizing:border-box;color:rgb(111,66,193)" class="">main</span>() {
    <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">myPrint</span>(<span style="box-sizing:border-box;color:rgb(0,92,197)" class="">1</span> + <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">3</span>)   <span style="box-sizing:border-box;color:rgb(106,115,125)" class=""><span style="box-sizing:border-box" class="">//</span> print out '8'</span>
    <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">printColor</span>(RED); <span style="box-sizing:border-box;color:rgb(106,115,125)" class=""><span style="box-sizing:border-box" class="">//</span> print 'the color is RED'</span>
    <span style="box-sizing:border-box;color:rgb(215,58,73)" class="">return</span> <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">0</span>;
}</pre></div><div class=""><span style="" class="">```</span></div><div class=""><span style="" class="">You can create a nacro rule with a pragma directive and follows with definitions written a simple DSL. The defined nacro rule works just like a normal macro function (i.e. expanded during preprocessing and called like a function), but with some extra features:</span></div><div class=""><font class=""> - Multiline definitions without ‘\’.</font></div><div class=""><font class=""> - Expression Protection: As shown in the ‘myPrint’ nacro above, you don’t need to add parens around expressions anymore, the nacro preprocessor will do that for you.</font></div><div class=""><font class=""> - Loops, one of the most exciting features in nacro: You can use “$loop” directive to ‘unroll’ a list of argument (argument type trailing with ‘*’, like ‘$expr*’. It’s equivalent to VA_ARGS) during preprocessing.</font></div><div class=""><font class=""> - Detecting invalid capturing. This is still an unstable feature, but basically it’s aiming to detect issues like this:</font></div><div class=""><font class="">```</font></div><div class=""><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;padding:16px;overflow:auto;line-height:1.45;background-color:rgb(246,248,250);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;color:rgb(36,41,46);font-variant-ligatures:normal" class="">#<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">define</span> <span style="box-sizing:border-box;color:rgb(111,66,193)" class="">foo</span>(<span style="box-sizing:border-box;color:rgb(227,98,9)" class="">arg</span>) {\
    <span style="box-sizing:border-box;color:rgb(215,58,73)" class="">int</span> x = <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">0</span>;  \
    <span style="box-sizing:border-box;color:rgb(215,58,73)" class="">return</span> arg + x; \
}

<span style="box-sizing:border-box;color:rgb(106,115,125)" class=""><span style="box-sizing:border-box" class="">//</span> ERROR: caller will always return 0 </span>
<span style="box-sizing:border-box;color:rgb(106,115,125)" class=""><span style="box-sizing:border-box" class="">//</span> regardless the argument value</span>
<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">int</span> <span style="box-sizing:border-box;color:rgb(111,66,193)" class="">caller</span>(<span style="box-sizing:border-box;color:rgb(215,58,73)" class="">int</span> x) {
    <span style="box-sizing:border-box;color:rgb(0,92,197)" class="">foo</span>(x)
}</pre><div class=""><br class=""></div></div><div class=""><font class="">```</font></div><div class=""><font class="">Please checkout the its wiki page (</font><a href="https://github.com/mshockwave/nacro/wiki/Invalid-Capture-Detection" target="_blank" rel="noreferrer" class="">https://github.com/mshockwave/nacro/wiki/Invalid-Capture-Detection</a><span style="" class="">) for more info.</span></div><div class=""><span style="" class=""><br class=""></span></div><div class=""><font class="">Another important thing is that nacro _doesn’t require a custom Clang / LLVM_. All of the features are implemented in a Clang plugin. So all you need is a Clang 10 by your hand and the plugin.</font></div><div class=""><font class=""><br class=""></font></div><div class=""><font class="">Though not modifying Clang actually put a tons of restrictions and force me to create many hacky workarounds that might be broken in newer version of Clang. For example, as a preprocessor plugin, all i can do is mutating and injecting tokens. But the preprocessor doesn’t like it, or in other words, current preprocessor doesn’t have a good support on this kind of actions. Especially while I was dealing with SourceLocation: there are many time i need to use an imprecise one or even fake one.</font></div><div class=""><font class=""><br class=""></font></div><div class=""><font class="">Another hard part is the Invalid Capture Detection. My original plan was to </font><span style="" class="">automatically </span><font class="">fix it rather than throwing an error message. However, that will require symbol table and scope info that merely exist in AST. Though Parser/Sema has those info but currently we don’t have any plugin support on Parser/Sema. </font></div><div class=""><font class=""><br class=""></font></div><div class=""><font class="">Hope you find this project interesting, or at least find it amusing. </font></div><div class=""><font class=""><br class=""></font></div><div class=""><font class="">-Min</font></div></div>_______________________________________________<br class="">
cfe-dev mailing list<br class="">
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" rel="noreferrer" class="">cfe-dev@lists.llvm.org</a><br class="">
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer noreferrer" target="_blank" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></body></html>