<div dir="auto">Sounds interesting. It would be a good addition if you can support a bit of type system and ensuring type sanity too somehow.</div><br><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">cfe-dev@lists.llvm.org</a>> wrote:<br></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">Hi Clang folks,<div><br></div><div>Recently I have been working on a side project, Nacro (<a href="https://github.com/mshockwave/nacro" target="_blank" rel="noreferrer">https://github.com/mshockwave/nacro</a>), that you might find interesting.</div><div><br></div><div><span style="color:rgb(0,0,0)">Nacro is a small DSL aim to provide a better C/C++ macro experience. Here is an example:</span></div><div><span style="color:rgb(0,0,0)">```</span></div><div><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">#<span style="box-sizing:border-box;color:rgb(215,58,73)">pragma</span> nacro rule myPrint
(val:$expr) -> $stmt {
    <span style="box-sizing:border-box;color:rgb(0,92,197)">printf</span>(<span style="box-sizing:border-box;color:rgb(3,47,98)"><span style="box-sizing:border-box">"</span>%d<span style="box-sizing:border-box">\n</span><span style="box-sizing:border-box">"</span></span>, val * <span style="box-sizing:border-box;color:rgb(0,92,197)">2</span>)
}

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

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

<span style="box-sizing:border-box;color:rgb(215,58,73)">int</span> <span style="box-sizing:border-box;color:rgb(111,66,193)">main</span>() {
    <span style="box-sizing:border-box;color:rgb(0,92,197)">myPrint</span>(<span style="box-sizing:border-box;color:rgb(0,92,197)">1</span> + <span style="box-sizing:border-box;color:rgb(0,92,197)">3</span>)   <span style="box-sizing:border-box;color:rgb(106,115,125)"><span style="box-sizing:border-box">//</span> print out '8'</span>
    <span style="box-sizing:border-box;color:rgb(0,92,197)">printColor</span>(RED); <span style="box-sizing:border-box;color:rgb(106,115,125)"><span style="box-sizing:border-box">//</span> print 'the color is RED'</span>
    <span style="box-sizing:border-box;color:rgb(215,58,73)">return</span> <span style="box-sizing:border-box;color:rgb(0,92,197)">0</span>;
}</pre></div><div><span style="color:rgb(0,0,0)">```</span></div><div><span style="color:rgb(0,0,0)">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><font color="#000000"> - Multiline definitions without ‘\’.</font></div><div><font color="#000000"> - 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><font color="#000000"> - 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><font color="#000000"> - Detecting invalid capturing. This is still an unstable feature, but basically it’s aiming to detect issues like this:</font></div><div><font color="#000000">```</font></div><div><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">#<span style="box-sizing:border-box;color:rgb(215,58,73)">define</span> <span style="box-sizing:border-box;color:rgb(111,66,193)">foo</span>(<span style="box-sizing:border-box;color:rgb(227,98,9)">arg</span>) {\
    <span style="box-sizing:border-box;color:rgb(215,58,73)">int</span> x = <span style="box-sizing:border-box;color:rgb(0,92,197)">0</span>;  \
    <span style="box-sizing:border-box;color:rgb(215,58,73)">return</span> arg + x; \
}

<span style="box-sizing:border-box;color:rgb(106,115,125)"><span style="box-sizing:border-box">//</span> ERROR: caller will always return 0 </span>
<span style="box-sizing:border-box;color:rgb(106,115,125)"><span style="box-sizing:border-box">//</span> regardless the argument value</span>
<span style="box-sizing:border-box;color:rgb(215,58,73)">int</span> <span style="box-sizing:border-box;color:rgb(111,66,193)">caller</span>(<span style="box-sizing:border-box;color:rgb(215,58,73)">int</span> x) {
    <span style="box-sizing:border-box;color:rgb(0,92,197)">foo</span>(x)
}</pre><div><br></div></div><div><font color="#000000">```</font></div><div><font color="#000000">Please checkout the its wiki page (</font><a href="https://github.com/mshockwave/nacro/wiki/Invalid-Capture-Detection" target="_blank" rel="noreferrer">https://github.com/mshockwave/nacro/wiki/Invalid-Capture-Detection</a><span style="color:rgb(0,0,0)">) for more info.</span></div><div><span style="color:rgb(0,0,0)"><br></span></div><div><font color="#000000">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><font color="#000000"><br></font></div><div><font color="#000000">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><font color="#000000"><br></font></div><div><font color="#000000">Another hard part is the Invalid Capture Detection. My original plan was to </font><span style="color:rgb(0,0,0)">automatically </span><font color="#000000">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><font color="#000000"><br></font></div><div><font color="#000000">Hope you find this project interesting, or at least find it amusing. </font></div><div><font color="#000000"><br></font></div><div><font color="#000000">-Min</font></div></div>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" rel="noreferrer">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div>