﻿<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta charset="utf-8">
  <title>Code checkers &amp; generators</title>
  <style>
    .previewPage {
      margin: 64px auto;
      width: 920px;
    }
  </style>
</head>
<body>
  <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="607">
    <tr>
      <td width="230" align="left" valign="top">Document number:</td>
      <td width="735">N3883</td>
    </tr>
    <tr>
      <td width="230" align="left" valign="top">Date:</td>
      <td width="735">2014-01-17</td>
    </tr>
    <tr>
      <td width="230" align="left" valign="top">Project:</td>
      <td width="735">Programming Language C++, Evolution Working Group</td>
    </tr>
    <tr>
      <td width="230" align="left" valign="top">Reply-to:</td>
      <td width="735">Németh Péter &lt;<a href="mailto:hun.nemethpeter@gmail.com">hun.nemethpeter@gmail.com</a>&gt;</td>
    </tr>
  </table>

  <div class="page">
    <div class="previewPage">
    <div id="readme" class="announce md">
      <article class="markdown-body entry-content">
        <h1>
<a name="code-checkers--generators" class="anchor" href="#code-checkers--generators"><span class="octicon octicon-link"></span></a>Code checkers &amp; generators</h1>

<p>Native Json &amp; HTML, built-in tutorial, easy meta programming, reflection proposal to C++</p>

<h2>
<a name="why" class="anchor" href="#why"><span class="octicon octicon-link"></span></a>Why?</h2>

<p>C++ is a great programming language, but it falters when we try to use it for cloning and
generating code parts. Programmable code generators let you create very complex clones of a given code part
(class, enums, templates, statements, etc.) with familiar syntax.
The result is extraordinarily expressive, readable, and quick to develop.</p>

<h2>
<a name="motivating-example" class="anchor" href="#motivating-example"><span class="octicon octicon-link"></span></a>Motivating example</h2>

<div class="highlight highlight-C++"><pre><span class="c1">// origin</span>
<span class="k">class</span> <span class="nc">User</span>
<span class="p">{</span>
  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
  <span class="n">Date</span> <span class="n">birthDate</span><span class="p">;</span>
  <span class="kt">double</span> <span class="n">weight</span><span class="p">;</span>

  <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">User</span><span class="o">&amp;</span> <span class="n">rhs</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span> <span class="c1">// declaring</span>
<span class="p">};</span>

<span class="c1">// driver</span>
<span class="k">class</span> <span class="nc">EqualityDriver</span>
<span class="p">{</span>
  <span class="n">constexpr</span> <span class="n">EqualityDriver</span><span class="p">(</span><span class="k">const</span> <span class="n">ClassDecl</span><span class="o">&amp;</span> <span class="n">classDecl</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">class_name</span> <span class="o">=</span> <span class="n">classDecl</span><span class="p">.</span><span class="n">getTypeName</span><span class="p">();</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="n">field</span> <span class="o">:</span> <span class="n">classDecl</span><span class="p">.</span><span class="n">fields</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">field</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o">==</span> <span class="s">"weight"</span><span class="p">)</span> <span class="c1">// you can filter out members</span>
        <span class="k">continue</span><span class="p">;</span>
      <span class="n">members</span><span class="p">.</span><span class="n">emplace_back</span><span class="p">(</span><span class="n">field</span><span class="p">.</span><span class="n">getName</span><span class="p">());</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">meta</span><span class="o">::</span><span class="n">id_name</span><span class="o">&gt;</span> <span class="n">members</span><span class="p">;</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">type_name</span> <span class="n">class_name</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// pattern</span>
<span class="err">$</span><span class="n">define</span> <span class="n">OperatorEqGenerator</span><span class="p">(</span><span class="n">EqualityDriver</span> <span class="n">driver</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">bool</span> <span class="err">$</span><span class="n">driver</span><span class="p">.</span><span class="n">class_name</span><span class="o">::</span><span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="err">$</span><span class="n">driver</span><span class="p">.</span><span class="n">class_name</span><span class="o">&amp;</span> <span class="n">rhs</span><span class="p">)</span> <span class="k">const</span>
  <span class="p">{</span>
    <span class="k">return</span> <span class="nb">true</span>
      <span class="err">$</span><span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">member</span> <span class="o">:</span> <span class="n">driver</span><span class="p">.</span><span class="n">members</span><span class="p">)</span> <span class="p">{</span>
        <span class="o">&amp;&amp;</span> <span class="err">$</span><span class="n">member</span> <span class="o">==</span> <span class="n">rhs</span><span class="p">.</span><span class="err">$</span><span class="n">member</span>
      <span class="p">}</span>
    <span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// usage</span>
<span class="err">$</span><span class="n">OperatorEqGenerator</span><span class="p">(</span><span class="n">User</span><span class="p">);</span> <span class="c1">// define an operator== for User</span>
</pre></div>

<h2>
<a name="how" class="anchor" href="#how"><span class="octicon octicon-link"></span></a>How?</h2>

<p>The idea comes from the AngularJS templating system which is a proven to work and efficient solution for HTML templating.
Drivers are constexpr objects. Manipulating code parts are directed with directives.</p>

<p>Directives are: <code>$define</code>, <code>$use</code>, <code>$for</code>, <code>$if</code>, <code>$switch</code></p>

<p><code>$define</code> and <code>$use</code> directives expect a driver which is a constexpr object.
In directives and in template driver variables you can use the constexpr object's methods and members.
Generating code parts is safe, because you can create only a typed id.</p>

<p>Some basic rules:</p>

<ul>
<li>you have to use the <code>{ ... }</code> syntax after <code>$for</code>, <code>$if</code>, <code>$switch</code> directives</li>
<li>you can create <code>meta::id_name</code> (in member, variable or parameter declaration context)</li>
<li>you can create <code>meta::type_name</code> and this can be used where a new type is introduced (e.g. after <code>class</code> keyword)</li>
<li>
<code>$define</code> defines a pattern. Can be used later with the <code>$name</code> syntax, where name is the defined name.</li>
<li>if <code>$name</code> expects a grammar, then <code>(</code> and <code>)</code> can be optional</li>
<li>
<code>$define</code> is namespace friendly (macro #define is not)</li>
<li>
<code>$use</code> can be attached to a template or can be scoped with <code>{ ... }</code>
</li>
</ul><h2>
<a name="where-does-the-magic-happen" class="anchor" href="#where-does-the-magic-happen"><span class="octicon octicon-link"></span></a>Where does the magic happen?</h2>

<ol>
<li>Getting compiler generated AST node

<ul>
<li>An AST node is a wrapped version of the internal one, where the interface is standardized</li>
<li>The compiler sees that <code>$OperatorEqGenerator</code> is a defined generator with a driver where the driver expects one parameter</li>
<li>The compiler generates an AST node struct for <code>User</code> with base type <code>decl</code>.</li>
<li>The compiler tries to cast <code>decl</code> to <code>ClassDecl</code>. If it fails, the compiler tells that the driver expects <code>ClassDecl</code>.</li>
</ul>
</li>
<li>Inject generated tokens

<ul>
<li>
<code>meta::id_name</code> can be constructed from string</li>
<li>with the dollar <code>$</code> syntax it can be pasted (e.g. <code>$member</code>) as a normal id in a generator template</li>
<li>
<code>meta::id_name</code> can be pasted as a string literal</li>
</ul>
</li>
<li>Parameter passing in templates

<ul>
<li>for one parameter <code>template&lt;typename T&gt; $use(Driver driver)</code> Driver got the AST nodized T</li>
<li>for more parameter <code>template&lt;class T, class U&gt; $use(Driver driver)</code> Driver constructor expects the same number of parameters as template has.</li>
<li>manual parameter passing <code>template&lt;class T, class U&gt; $use(Driver driver(U))</code> here only <code>U</code> is used.</li>
</ul>
</li>
<li>New keyword <code>astnode</code> in template parameter

<ul>
<li>
<code>template&lt;astnode Node&gt; $use(AssertDriver driver)</code> where astnode can be an expression, but Driver gets an AST node</li>
<li>
<code>astnode</code> template parameter must be used with a driver</li>
<li>the grammar of astnode is defined in the driver's constructor parameters, it can be complex grammar</li>
</ul>
</li>
</ol><h2>
<a name="standardized-ast-nodes" class="anchor" href="#standardized-ast-nodes"><span class="octicon octicon-link"></span></a>Standardized AST nodes</h2>

<p>TODO: modelled after clang <a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">http://clang.llvm.org/doxygen/classclang_1_1Decl.html</a></p>

<p>Clang Decl API uses <code>camelCase</code> C++ STL uses <code>underscores_type</code>. Only a minimal subset of ClangAPI is needed.</p>

<h2>
<a name="other-use-cases" class="anchor" href="#other-use-cases"><span class="octicon octicon-link"></span></a>Other use cases</h2>

<h3>
<a name="struct-of-arrays-vector" class="anchor" href="#struct-of-arrays-vector"><span class="octicon octicon-link"></span></a>Struct-of-Arrays vector</h3>

<div class="highlight highlight-C++"><pre><span class="c1">// origin</span>
<span class="k">struct</span> <span class="n">S</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">a</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">b</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">c</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// driver</span>
<span class="k">class</span> <span class="nc">SoADriver</span>
<span class="p">{</span>
<span class="nl">public:</span>
  <span class="k">struct</span> <span class="n">Member</span>
  <span class="p">{</span>
    <span class="n">meta</span><span class="o">::</span><span class="n">id_name</span> <span class="n">name</span><span class="p">;</span>
    <span class="n">meta</span><span class="o">::</span><span class="n">type_name</span> <span class="n">type</span><span class="p">;</span>
  <span class="p">};</span>
  <span class="n">constexpr</span> <span class="nf">SoADriver</span><span class="p">(</span><span class="k">const</span> <span class="n">ClassDecl</span><span class="o">&amp;</span> <span class="n">fromClassDecl</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">new_class_name</span><span class="p">)</span>
    <span class="o">:</span> <span class="n">new_class_name</span><span class="p">(</span><span class="n">new_class_name</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="n">field</span> <span class="o">:</span> <span class="n">fromClassDecl</span><span class="p">.</span><span class="n">fields</span><span class="p">())</span>
      <span class="n">members</span><span class="p">.</span><span class="n">emplace_back</span><span class="p">({</span><span class="n">field</span><span class="p">.</span><span class="n">getTypeName</span><span class="p">(),</span>  <span class="n">field</span><span class="p">.</span><span class="n">getName</span><span class="p">()</span> <span class="o">+</span> <span class="s">"s"</span><span class="p">,</span> <span class="p">});</span>
  <span class="p">}</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">type_name</span> <span class="n">new_class_name</span><span class="p">;</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Member</span><span class="o">&gt;</span> <span class="n">members</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// pattern</span>
<span class="err">$</span><span class="n">define</span> <span class="n">SoAGenerator</span><span class="p">(</span><span class="n">SoADriver</span> <span class="n">driver</span><span class="p">)</span>
<span class="p">{</span>
  <span class="k">class</span> <span class="err">$</span><span class="nc">driver</span><span class="p">.</span><span class="n">new_class_name</span>
  <span class="p">{</span>
    <span class="err">$</span><span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">member</span> <span class="o">:</span> <span class="n">driver</span><span class="p">.</span><span class="n">members</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="err">$</span><span class="n">member</span><span class="p">.</span><span class="n">type</span><span class="o">&gt;</span> <span class="err">$</span><span class="n">member</span><span class="p">.</span><span class="n">name</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">};</span>
<span class="p">}</span>

<span class="c1">// usage</span>
<span class="err">$</span><span class="n">SoAGenerator</span><span class="p">(</span><span class="n">S</span><span class="p">,</span> <span class="s">"SoA_vector_of_S"</span><span class="p">);</span>
</pre></div>

<h3>
<a name="replacing-assert" class="anchor" href="#replacing-assert"><span class="octicon octicon-link"></span></a>Replacing assert</h3>

<p>My best solution is to introduce a new keyword called <code>astnode</code></p>

<div class="highlight highlight-C++"><pre><span class="c1">// origin</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
  <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
  <span class="n">assert</span><span class="p">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="p">);</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// driver</span>
<span class="k">class</span> <span class="nc">AssertDriver</span>
<span class="p">{</span>
<span class="nl">public:</span>
  <span class="n">constexpr</span> <span class="n">ArrayDriver</span><span class="p">(</span><span class="k">const</span> <span class="n">ExpressionDecl</span><span class="o">&amp;</span> <span class="n">decl</span><span class="p">)</span> <span class="c1">// if astnode is not an expression we got compilation error</span>
     <span class="n">expessionDecl</span><span class="p">(</span><span class="n">decl</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="c1">// check decl is boolean expr</span>
  <span class="p">}</span>
  <span class="k">const</span> <span class="n">expessionDecl</span><span class="o">&amp;</span> <span class="n">decl</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// template with attached driver</span>
<span class="c1">// new keyword astnode, allowed only with $use</span>
<span class="k">template</span><span class="o">&lt;</span><span class="n">astnode</span> <span class="n">Node</span><span class="o">&gt;</span> <span class="err">$</span><span class="n">use</span><span class="p">(</span><span class="n">AssertDriver</span> <span class="n">driver</span><span class="p">)</span>
<span class="kt">void</span> <span class="n">assert</span><span class="p">(</span><span class="n">Node</span><span class="p">)</span>
<span class="p">{</span>
  <span class="c1">// this will run between two sequence points</span>
  <span class="c1">// after Node is evaluated</span>
  <span class="c1">// `get_result()` is a const ref to the result</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="err">$</span><span class="n">driver</span><span class="p">.</span><span class="n">decl</span><span class="p">.</span><span class="n">get_result</span><span class="p">())</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"failed assert: "</span> <span class="o">&lt;&lt;</span> <span class="err">$</span><span class="n">driver</span><span class="p">.</span><span class="n">decl</span><span class="p">.</span><span class="n">to_string</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="err">$</span><span class="n">driver</span><span class="p">.</span><span class="n">decl</span><span class="p">.</span><span class="n">source</span><span class="p">.</span><span class="n">get_start_pos</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// usage</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
  <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
  <span class="n">assert</span><span class="p">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<h3>
<a name="enumerating-enums" class="anchor" href="#enumerating-enums"><span class="octicon octicon-link"></span></a>Enumerating enums</h3>

<p>This code snippet converts a string to an enum. The converter implementation is a function template.
The function template parameter is "captured" before template instatization, and processed with <code>EnumDriver</code>.
<code>EnumDriver</code>'s constructor is waiting an <code>const EnumDecl&amp;</code> that is the AST node of <code>T</code>.</p>

<div class="highlight highlight-C++"><pre><span class="c1">// origin</span>
<span class="k">enum</span> <span class="k">class</span> <span class="nc">EVote</span>
<span class="p">{</span>
  <span class="n">Yes</span><span class="p">,</span>
  <span class="n">RatherYes</span><span class="p">,</span>
  <span class="n">Undecided</span><span class="p">,</span>
  <span class="n">RatherNo</span><span class="p">,</span>
  <span class="n">No</span>
<span class="p">};</span>

<span class="c1">// driver</span>
<span class="k">class</span> <span class="nc">EnumDriver</span>
<span class="p">{</span>
  <span class="nl">public:</span>
    <span class="n">constexpr</span> <span class="n">EnumDriver</span><span class="p">(</span><span class="k">const</span> <span class="n">EnumDecl</span><span class="o">&amp;</span> <span class="n">enumDecl</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="n">enumerator</span> <span class="o">:</span> <span class="n">enumDecl</span><span class="p">.</span><span class="n">enumerators</span><span class="p">())</span>
        <span class="n">enumValueNames</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">enumerator</span><span class="p">.</span><span class="n">getName</span><span class="p">());</span>
    <span class="p">}</span>

    <span class="c1">// meta::vector is a constexpr vector</span>
    <span class="n">meta</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">meta</span><span class="o">::</span><span class="n">id_name</span><span class="o">&gt;</span> <span class="n">enumValueNames</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// template with attached driver</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="err">$</span><span class="n">use</span><span class="p">(</span><span class="n">EnumDriver</span> <span class="n">driver</span><span class="p">)</span>
<span class="kt">void</span> <span class="n">Json</span><span class="o">::</span><span class="n">readFrom</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
  <span class="n">obj</span> <span class="o">=</span> <span class="n">llvm</span><span class="o">::</span><span class="n">StringSwitch</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
    <span class="err">$</span><span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">enumValueName</span> <span class="o">:</span> <span class="n">driver</span><span class="p">.</span><span class="n">enumValueNames</span><span class="p">)</span> <span class="p">{</span>
      <span class="p">.</span><span class="n">Case</span><span class="p">(</span><span class="err">$</span><span class="n">enumValueName</span><span class="p">.</span><span class="n">asStr</span><span class="p">(),</span> <span class="err">$</span><span class="n">enumValueName</span><span class="p">)</span> <span class="p">}</span>
  <span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
  <span class="n">Evote</span> <span class="n">vote</span><span class="p">;</span>
  <span class="n">Json</span><span class="o">::</span><span class="n">readFrom</span><span class="p">(</span><span class="n">vote</span><span class="p">,</span> <span class="s">"EVote::Undecided"</span><span class="p">);</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<h3>
<a name="deprecating-c-style-macro" class="anchor" href="#deprecating-c-style-macro"><span class="octicon octicon-link"></span></a>Deprecating C style macro</h3>

<p>We can replace the old macro system with this new one. For this reason <code>$if</code> and <code>$swicth</code> is introduced.
For normal code flow, this conditional compilation would be as harmful (or helpful) as the normal macro style one.
This is just a new syntax.</p>

<p>Pro:</p>

<ul>
<li>namespace friendly</li>
<li>object oriented design</li>
<li>simple: only <code>$if</code> &amp; <code>$else</code> instead of <code>#ifdef</code>, <code>#ifndef</code>, <code>#elif</code>, <code>#endif</code>, <code>#if defined</code>
</li>
</ul><p>Con:</p>

<ul>
<li>cannot be used for header guard</li>
<li>
<code>{</code> and <code>}</code> does not introduce scope but it seems so from the syntax</li>
</ul><p>Some intended usage:</p>

<p>Instead of</p>

<div class="highlight highlight-C++"><pre><span class="cp">#define DEBUG 1</span>

<span class="kt">void</span> <span class="nf">printBackTrace</span><span class="p">()</span> <span class="p">{</span>
<span class="cp">#if DEBUG</span>
  <span class="c1">// do something</span>
<span class="cp">#else</span>
  <span class="c1">// do nothing</span>
<span class="cp">#endif</span>
<span class="p">}</span>
</pre></div>

<p>we can write</p>

<div class="highlight highlight-C++"><pre><span class="k">enum</span> <span class="k">class</span> <span class="nc">Configuration</span>
<span class="p">{</span>
  <span class="n">Debug</span><span class="p">,</span>
  <span class="n">Release</span>
<span class="p">};</span>
<span class="k">enum</span> <span class="k">class</span> <span class="nc">Platform</span>
<span class="p">{</span>
  <span class="n">Win32</span><span class="p">,</span>
  <span class="n">Win64</span><span class="p">,</span>
  <span class="n">Linux</span>
<span class="p">};</span>
<span class="k">struct</span> <span class="n">ConfigurationDriver</span>
<span class="p">{</span>
  <span class="n">constexpr</span> <span class="n">Configuration</span> <span class="n">configuration</span> <span class="o">=</span> <span class="n">Configuration</span><span class="o">::</span><span class="n">Debug</span><span class="p">;</span>
  <span class="n">constexpr</span> <span class="n">Platform</span> <span class="n">platform</span> <span class="o">=</span> <span class="n">Platform</span><span class="o">::</span><span class="n">Linux</span><span class="p">;</span>
  <span class="n">constexpr</span> <span class="nf">ConfigurationDriver</span><span class="p">()</span> <span class="p">{}</span>
<span class="p">};</span>

<span class="c1">// start using ConfigurationDriver</span>
<span class="err">$</span><span class="n">use</span><span class="p">(</span><span class="n">ConfigurationDriver</span> <span class="n">driver</span><span class="p">)</span>
<span class="p">{</span>

<span class="c1">// function with a driver</span>
<span class="kt">void</span> <span class="n">printBackTrace</span><span class="p">()</span>
<span class="p">{</span>
  <span class="err">$</span><span class="k">if</span> <span class="p">(</span><span class="n">driver</span><span class="p">.</span><span class="n">configuration</span> <span class="o">==</span> <span class="n">Configuration</span><span class="o">::</span><span class="n">Debug</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="n">realPrintBackTrace</span><span class="p">();</span>
  <span class="p">}</span>
  <span class="err">$</span><span class="k">else</span>
  <span class="p">{</span>
    <span class="c1">// do nothing</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// function with a driver</span>
<span class="kt">void</span> <span class="n">foo</span><span class="p">()</span>
<span class="p">{</span>
  <span class="err">$</span><span class="k">switch</span> <span class="p">(</span><span class="n">driver</span><span class="p">.</span><span class="n">platform</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="err">$</span><span class="k">case</span> <span class="n">Platform</span>:<span class="o">:</span><span class="n">Win32</span> <span class="c1">// fallthrough</span>
    <span class="err">$</span><span class="k">case</span> <span class="n">Platform</span>:<span class="o">:</span><span class="n">Win64</span>
    <span class="p">{</span>
      <span class="n">WinApiXyz</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="err">$</span><span class="k">case</span> <span class="n">Platform</span>:<span class="o">:</span><span class="n">Linux</span>
    <span class="p">{</span>
      <span class="n">GlibcCallXyz</span><span class="p">();</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="p">}</span> <span class="c1">// $use</span>
</pre></div>

<h3>
<a name="deprecating-template-metaprogramming" class="anchor" href="#deprecating-template-metaprogramming"><span class="octicon octicon-link"></span></a>Deprecating template metaprogramming</h3>

<p>Working with code generators and checkers is much easier, faster and safer than TMP.
My proposal is to issue a deprecate warning when template instantiation depth reaches a low number e.g. <code>16</code>.
This limit may be removed with a  compiler switch e.g. <code>-ftemplate-depth-20000</code>
With native DSL support we can invent a new DSL language for functional style metaprogramming and for concepts checking. </p>

<h3>
<a name="code-checking-also-concepts-check" class="anchor" href="#code-checking-also-concepts-check"><span class="octicon octicon-link"></span></a>Code checking (also concepts check)</h3>

<p>If we use the <code>$use</code> without an instance name it means that the driver is doing only checks</p>

<h4>
<a name="for-concepts-check" class="anchor" href="#for-concepts-check"><span class="octicon octicon-link"></span></a>For concepts check</h4>

<div class="highlight highlight-C++"><pre><span class="c1">// attached checker for a class template</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="err">$</span><span class="n">use</span><span class="p">(</span><span class="n">ConceptsChecker</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Foo</span>
<span class="p">{</span>
<span class="p">}</span>

<span class="k">struct</span> <span class="n">ConceptsChecker</span> <span class="p">{</span>
  <span class="n">constexpr</span> <span class="n">ConceptsChecker</span><span class="p">(</span><span class="k">const</span> <span class="n">ClassDecl</span><span class="o">&amp;</span> <span class="n">classDecl</span><span class="p">)</span> <span class="c1">// first check, T must be an class</span>
  <span class="p">{</span>
    <span class="c1">// for more check, see http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html</span>
    <span class="n">static_assert</span><span class="p">(</span><span class="n">classDecl</span><span class="p">.</span><span class="n">hasMoveConstructor</span><span class="p">(),</span> <span class="s">"Move constructor is missing"</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">};</span>
</pre></div>

<h4>
<a name="for-compile-time-call-site-parameter-check" class="anchor" href="#for-compile-time-call-site-parameter-check"><span class="octicon octicon-link"></span></a>For compile time call site parameter check</h4>

<div class="highlight highlight-C++"><pre><span class="k">struct</span> <span class="n">FormatChecker</span> <span class="p">{</span>
  <span class="c1">// http://clang.llvm.org/doxygen/classclang_1_1Expr.html</span>
  <span class="n">constexpr</span> <span class="n">FormatChecker</span><span class="p">(</span><span class="k">const</span> <span class="n">meta</span><span class="o">::</span><span class="n">expr</span><span class="o">&amp;</span> <span class="n">expr</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">expr</span><span class="p">.</span><span class="n">isa</span><span class="o">&lt;</span><span class="n">meta</span><span class="o">::</span><span class="n">string_literal</span><span class="o">&gt;</span><span class="p">())</span> 
    <span class="p">{</span>
       <span class="c1">// do format check for format string</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">};</span>

<span class="c1">// attached checker for a normal function</span>
<span class="kt">void</span> <span class="nf">printDate</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">formatStr</span><span class="p">)</span> <span class="err">$</span><span class="n">use</span><span class="p">(</span><span class="n">FormatChecker</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">}</span>
</pre></div>

<h4>
<a name="for-compile-time-general-call-site-check-ideal-for-ex-tutorials-and-coding-style-checkers" class="anchor" href="#for-compile-time-general-call-site-check-ideal-for-ex-tutorials-and-coding-style-checkers"><span class="octicon octicon-link"></span></a>For compile time general call site check, ideal for ex. tutorials and coding style checkers.</h4>

<div class="highlight highlight-C++"><pre><span class="c1">// attached checker after a normal function</span>
<span class="k">struct</span> <span class="n">TutorialChecker</span> <span class="p">{</span>
  <span class="n">constexpr</span> <span class="n">TutorialChecker</span><span class="p">(</span><span class="k">const</span> <span class="n">meta</span><span class="o">::</span><span class="n">compound_stmt</span><span class="o">&amp;</span> <span class="n">stmt</span><span class="p">)</span>
  <span class="p">{</span>
     <span class="c1">// check for C function and show std::cout example</span>
  <span class="p">}</span>
<span class="p">};</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
  <span class="n">printf</span><span class="p">(</span><span class="s">"My first program!"</span><span class="p">);</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span> <span class="err">$</span><span class="n">use</span> <span class="p">(</span><span class="n">TutorialChecker</span><span class="p">,</span> <span class="n">CodingStyleChecker</span><span class="p">)</span>

</pre></div>

<h3>
<a name="domain-specific-language-support" class="anchor" href="#domain-specific-language-support"><span class="octicon octicon-link"></span></a>Domain-specific language support</h3>

<p>With the help of this we can achieve native HTML, Json, XML, Regex, SQL, whatever support. It would be pretty awesome.
If we can solve with C++ modules to use JIT compiler on constexpr drivers it does not slow down the compilation too much.
The grammar of astnode is defined in the driver's constructor parameters, it can be complex grammar.
We should indicate, that a struct is a grammar struct, with inherited meta::grammar.
The grammar struct should not contain any method (including ctor, dtor, ..)</p>

<div class="highlight highlight-C++"><pre><span class="c1">// full grammar is here: http://www.json.org/</span>
<span class="k">struct</span> <span class="n">JsonParamGrammarItem</span> <span class="o">:</span> <span class="n">meta</span><span class="o">::</span><span class="n">grammar</span>
<span class="p">{</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">id_name</span> <span class="n">key</span><span class="p">;</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">op_name</span> <span class="n">colon</span> <span class="o">=</span> <span class="sc">':'</span><span class="p">;</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">expr</span> <span class="n">value</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="n">JsonParamGrammarTail</span> <span class="o">:</span> <span class="n">meta</span><span class="o">::</span><span class="n">grammar</span>
<span class="p">{</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">id_name</span> <span class="n">comma</span> <span class="o">=</span> <span class="sc">','</span><span class="p">;</span>
  <span class="n">JsonParamGrammarItem</span> <span class="n">item</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="n">JsonParamGrammar</span> <span class="o">:</span> <span class="n">meta</span><span class="o">::</span><span class="n">grammar</span>
<span class="p">{</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">symbol</span> <span class="n">open_brace</span> <span class="o">=</span> <span class="sc">'{'</span><span class="p">;</span>
  <span class="n">JsonParamGrammarItem</span> <span class="n">paramFirst</span><span class="p">;</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">JsonParamGrammarTail</span><span class="o">&gt;</span> <span class="n">paramMore</span><span class="p">;</span> <span class="c1">// this can be used for varargs ...</span>
  <span class="n">meta</span><span class="o">::</span><span class="n">symbol</span> <span class="n">close_brace</span> <span class="o">=</span> <span class="sc">'}'</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">JsonParamDriver</span>
<span class="p">{</span>
   <span class="n">constexpr</span> <span class="n">JsonParamDriver</span><span class="p">(</span><span class="n">JsonParamGrammar</span> <span class="n">grammar</span><span class="p">);</span>
<span class="p">};</span>

<span class="cm">/*</span>
<span class="cm">grammar rules</span>
<span class="cm">or - meta::or</span>
<span class="cm">and - member in struct</span>
<span class="cm">optional - meta::optional</span>
<span class="cm">any - meta::vector</span>

<span class="cm">so JsonParamGrammarItem is</span>
<span class="cm">meta::id_name &amp; ':' &amp; meta::expr</span>
<span class="cm">*/</span>

<span class="c1">// usage</span>
<span class="k">class</span> <span class="nc">SomeWidget</span>
<span class="p">{</span>
  <span class="k">template</span><span class="o">&lt;</span><span class="n">astnode</span> <span class="n">Node</span><span class="o">&gt;</span>
  <span class="n">SomeWidget</span><span class="p">(</span><span class="n">Node</span><span class="p">)</span> <span class="err">$</span><span class="n">use</span><span class="p">(</span><span class="n">JsonParamDriver</span> <span class="n">driver</span><span class="p">)</span>
  <span class="p">{</span>
    <span class="p">...</span>
    <span class="c1">// We should process with an other driver that associate member names with param names.</span>
  <span class="p">}</span>

  <span class="n">SomeWindow</span> <span class="n">window</span><span class="p">;</span>
  <span class="n">SomeLabel</span> <span class="n">label</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">SomeWidget</span> <span class="nf">widget</span><span class="p">({</span>
                     <span class="nl">window:</span> <span class="s">"Hello world"</span><span class="p">,</span>
                     <span class="nl">label:</span>  <span class="s">"Foo"</span>
                  <span class="p">});</span>
</pre></div>

<h2>
<a name="todo" class="anchor" href="#todo"><span class="octicon octicon-link"></span></a>TODO</h2>

<p>I selected the first one.</p>

<p>Which is better, so how hard for the compiler?
 <code>$driver.class_name</code> is one token</p>

<ul>
<li><code>bool $driver.class_name::operator==</code></li>
<li><code>bool $driver.class_name$::operator==</code></li>
<li><code>bool $(driver.class_name)::operator==</code></li>
</ul><p>How can I name this paper?</p>

<ul>
<li>Code checkers &amp; generators</li>
<li>Compile time reflection</li>
<li>Template drivers</li>
<li>AngularC++</li>
</ul><p>What is the name of the <code>$define</code> thing?</p>

<ul>
<li>pattern</li>
<li>macro-ng</li>
<li>new macro</li>
<li>generator template</li>
<li>named generator</li>
</ul><p>Standardize Clang Api names from <a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html</a></p>

<ul>
<li>
<code>meta::class_name</code> from <a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html</a>
</li>
<li>
<code>meta::template_name</code> from <a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateDecl.html">http://clang.llvm.org/doxygen/classclang_1_1TemplateDecl.html</a>
</li>
<li>
<code>meta::namespace_name</code> from <a href="http://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html">http://clang.llvm.org/doxygen/classclang_1_1NamespaceDecl.html</a>
</li>
<li>
<code>meta::function_name</code> from <a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html</a>
</li>
<li>
<code>meta::value_name</code> from <a href="http://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html">http://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html</a>
</li>
<li>
<code>meta::operator_name</code> from <a href="http://clang.llvm.org/doxygen/OperatorKinds_8h_source.html">http://clang.llvm.org/doxygen/OperatorKinds_8h_source.html</a>
</li>
<li>...</li>
</ul><p>Restrict pattern to a subgrammar item</p>

<ul>
<li><code>$define MyFooAttribute : meta::attribute_decl { [[ foo ]] }</code></li>
<li><code>$define MyFooAttribute() : meta::attribute_decl { [[ foo ]] }</code></li>
<li><code>$define MyFooAttribute $use(SomeGrammarStruct) { [[ foo ]] }</code></li>
<li><code>$define MyFooAttribute() $use(SomeGrammarStruct) { [[ foo ]] }</code></li>
</ul><p>Syntax of a member in <code>$for</code>, because it is always <code>const auto&amp;</code></p>

<ul>
<li>
<code>$for (auto member : driver.members)</code> no copy, it is $for(const auto&amp; member : ...</li>
<li>
<code>$for (const auto&amp; member : driver.members)</code> ok..., but simply long</li>
<li>
<code>$for (member : driver.members)</code> ok..., but maybe too short, where is the type?!</li>
</ul><h2>
<a name="links" class="anchor" href="#links"><span class="octicon octicon-link"></span></a>Links</h2>

<p>The idea of this proposal comes from the AngularJS HTML template framework:
<a href="http://angularjs.org/">http://angularjs.org/</a></p>

<p>prebuilt directives ngRepeat directive in module ng:
<a href="http://docs.angularjs.org/api/ng.directive:ngRepeat">http://docs.angularjs.org/api/ng.directive:ngRepeat</a></p>

<p>These code snippet based on this repo:
<a href="https://github.com/hun-nemethpeter/cpp-reflector-mini">https://github.com/hun-nemethpeter/cpp-reflector-mini</a></p>

<p>Call for Compile-Time Reflection Proposals:
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3814.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3814.html</a></p>
      </article>
    </div>
  </div>
  
  <div>&nbsp;</div>
  </div>

</body></html>
