Skip to content

Commit

Permalink
chore: deploy docs of project Nop Entropy via GitHub Actions
Browse files Browse the repository at this point in the history
  • Loading branch information
nop-cao committed Aug 31, 2024
1 parent b31d1d3 commit 79d2c81
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1258,7 +1258,7 @@ <h1 class="Article-title">低代码平台中的元编程(Meta Programming)</h1>

</header>
<div class="Article-content col-md-9"><p>在众多的编程语言中,爷爷辈的Lisp语言一直是一个独特的存在,这种独特性有人把它总结为”Lisp是可编程的编程语言”<br>。这指的是Lisp具有强大的元编程能力,可以由程序员自主创造新的语法抽象。<br>编程通俗的说就是<strong>写代码</strong>, 而所谓的元编程指的是<strong>写生成代码的代码</strong><br>Lisp通过宏提供了元编程的能力,而Lisp宏本质上就是一种内嵌在语言中的代码生成器。除了Lisp语言之外,Scala和Rust这些比较现代的程序语言也提供了所谓的宏的设计,但是宏一般被看作是非常复杂的底层技术,很少进入普通程序员的工具箱。</p>
<p>Nop平台的XLang语言是实现可逆计算原理的核心技术之一,为了落实可逆计算理论所提出的 <code>App = Biz x-extends Generator&lt;DSL&gt;</code><br>这样一种面向DSL和差量编程的新的编程范式,<br>XLang定义了一整套系统化的、覆盖应用系统开发方方面面的Generator方案。Lisp的宏仅仅是提供了生成Lisp<br>AST的元编程机制,而XLang除了引入宏函数用于生成XLang AST之外,还提供了面向代码生成的Xpl模板语法,<br>生成的范围从局部的函数实现体,到单个模型文件,再到整个模块目录。特别是Nop平台中定义的所有DSL语言都内置了<code>x:gen-extends</code><br>这样的差量生成机制,可以在模型解析、加载的过程中动态生成模型差量再自动实现差量合并,<br>从而创造了一种新的软件结构复用手段,解决了很多在传统编程范式下难以处理的技术问题。在本文中,我将简单介绍一下Nop平台中所内置的这些元编程机制。</p>
<p>Nop平台的XLang语言是实现可逆计算原理的核心技术之一,为了落实可逆计算理论所提出的 <code>App = Delta x-extends Generator&lt;DSL&gt;</code><br>这样一种面向DSL和差量编程的新的编程范式,<br>XLang定义了一整套系统化的、覆盖应用系统开发方方面面的Generator方案。Lisp的宏仅仅是提供了生成Lisp<br>AST的元编程机制,而XLang除了引入宏函数用于生成XLang AST之外,还提供了面向代码生成的Xpl模板语法,<br>生成的范围从局部的函数实现体,到单个模型文件,再到整个模块目录。特别是Nop平台中定义的所有DSL语言都内置了<code>x:gen-extends</code><br>这样的差量生成机制,可以在模型解析、加载的过程中动态生成模型差量再自动实现差量合并,<br>从而创造了一种新的软件结构复用手段,解决了很多在传统编程范式下难以处理的技术问题。在本文中,我将简单介绍一下Nop平台中所内置的这些元编程机制。</p>
<h2 id="宏函数"><a href="#宏函数" class="headerlink" title="宏函数"></a>宏函数</h2><p>XLang语言中也定义了类似Lisp宏的宏函数。所谓宏函数是在编译期执行,自动生成Expression抽象语法树节点的函数。</p>
<p>宏函数具有特殊的参数要求,并且需要增加<code>@Macro</code><br>注解。具体示例可以参见<a target="_blank" rel="noopener" href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-xlang/src/main/java/io/nop/xlang/functions/GlobalFunctions.java">GlobalFunctions</a></p>
<blockquote>
Expand Down Expand Up @@ -1324,7 +1324,7 @@ <h2 id="宏函数"><a href="#宏函数" class="headerlink" title="宏函数"></a
</tr>
</tbody></table>
<p>因为宏函数在编译期执行,因此用宏函数来实现解析功能可以优化系统执行性能。例如从XNode中读取子节点a的b属性时</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><code class="hljs plaintext">node.selectOne(xpath `a/@b`) <br></code></pre></td></tr></table></figure>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><code class="hljs plaintext">node.selectOne(xpath `a/@b`)<br></code></pre></td></tr></table></figure>

<p>因为xpath是一个宏函数,所以它在编译期就会完成解析,在运行期相当于是传送一个常量对象给selectOne函数。</p>
<p>通过宏函数可以实现自定义的语法结构,例如IF(X,Y,Z)会被转换为if语句。</p>
Expand All @@ -1339,7 +1339,7 @@ <h2 id="面向代码生成的Xpl模板语言"><a href="#面向代码生成的Xpl
<li>sql模式:输出SQL语句,对于表达式输出结果,自动变换为SQL参数</li>
</ol>
<p>例如对于以下SQL输出,</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><code class="hljs plaintext">&lt;filter:sql&gt;<br> o.id in (select o.id from MyTable o where o.id = $&#123;entity.id&#125;) <br>&lt;/filter:sql&gt; <br></code></pre></td></tr></table></figure>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><code class="hljs plaintext">&lt;filter:sql&gt;<br> o.id in (select o.id from MyTable o where o.id = $&#123;entity.id&#125;)<br>&lt;/filter:sql&gt;<br></code></pre></td></tr></table></figure>

<p>实际会生成 <code>o.id in (select o.id from MyTable o where o.id = ? )</code>,表达式的值不会直接拼接到SQL文本中,而是会被替换为SQL参数。</p>
<h2 id="编译期表达式"><a href="#编译期表达式" class="headerlink" title="编译期表达式"></a>编译期表达式</h2><p>Xpl模板语言内置了<code>&lt;macro:gen&gt;</code><code>&lt;macro:script&gt;</code>等标签,它们会在编译期自动执行。</p>
Expand Down Expand Up @@ -1390,7 +1390,7 @@ <h2 id="XDSL的差量生成与合并机制"><a href="#XDSL的差量生成与合
<figure class="highlight plaintext"><table><tr><td class="code"><pre><code class="hljs plaintext">&lt;model x:extends=&quot;A,B&quot;&gt;<br> &lt;x:gen-extends&gt;<br> &lt;C/&gt;<br> &lt;D/&gt;<br> &lt;/x:gen-extends&gt;<br><br> &lt;x:post-extends&gt;<br> &lt;E/&gt;<br> &lt;F/&gt;<br> &lt;/x:post-extends&gt;<br>&lt;/model&gt;<br></code></pre></td></tr></table></figure>

<p>合并结果为</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><code class="hljs plaintext">F x-extends E x-extends model x-extends D x-extends C x-extends B x-extends A <br></code></pre></td></tr></table></figure>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><code class="hljs plaintext">F x-extends E x-extends model x-extends D x-extends C x-extends B x-extends A<br></code></pre></td></tr></table></figure>

<p>当前模型会覆盖<code>x:gen-extends</code><code>x:extends</code>的结果,而<code>x:post-extends</code>会覆盖当前模型。</p>
<p>借助于<code>x:extends</code><code>x:gen-extends</code><br>我们可以有效的实现DSL的分解和组合。具体介绍参见 <a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/612512300">XDSL:通用的领域特定语言设计</a></p>
Expand Down
4 changes: 4 additions & 0 deletions projects/nop-entropy/docs/dev-guide/xlang/xdsl/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,10 @@ <h3 id="超越接口和组件的Delta定制"><a href="#超越接口和组件的D
<p>与传统的编程语言所提供的定制机制相比,<strong>Delta定制的规则非常通用直观,与具体的应用实现无关</strong>。以ORM引擎所用到的数据库Dialect定制为例,如果要扩展Hibernate框架内置的<code>MySQLDialect</code>,我们必须要具有一定的Hibernate框架的知识,如果用到了Spring集成,则我们还需要了解Spring对Hibernate的封装方式,具体从哪里找到Dialect并配置到当前<code>SessionFactory</code>中。而在Nop平台中,我们只需要增加文件<code>/_vfs/default/nop/dao/dialect/mysql.dialect.xml</code>,就可以确保所有用到MySQL方言的地方都会更新为使用新的Dialect模型。</p>
<p>Delta定制代码存放在单独的目录中,可以与程序主应用的代码相分离。例如将delta定制文件打包为<code>nop-platform-delta</code>模块中,需要使用此定制的时候只要引入对应模块即可。我们也可以同时引入多个delta目录,然后通过<code>nop.core.vfs.delta-layer-ids</code>参数来控制delta层的顺序。例如配置 <code>nop.core.vfs.delta-layer-ids=base,hunan</code> 表示启用两个delta层,一个是基础产品层,在其上是某个具体部署版本所使用的delta层。通过这种方式,我们可以以极低的成本实现软件的产品化:<strong>一个功能基本完善的基础产品在各个客户处实施的时候可以完全不修改基础产品的代码,而是只增加Delta定制代码</strong></p>
<h3 id="三-Antlr扩展"><a href="#三-Antlr扩展" class="headerlink" title="三. Antlr扩展"></a>三. Antlr扩展</h3><p>Nop平台对于自定义程序语法的DSL开发也提供了一定的支持,可以基于Antlr4的g4文件定义直接生成AST的解析器(Antlr内置只支持解析到<code>ParseTree</code>,需要手工编写从<code>ParseTree</code>到AST的转换代码)。具体参见<a href="../antlr/">antlr.md</a></p>
<h2 id="在任意XML-JSON基础上增加XDSL支持"><a href="#在任意XML-JSON基础上增加XDSL支持" class="headerlink" title="在任意XML&#x2F;JSON基础上增加XDSL支持"></a>在任意XML&#x2F;JSON基础上增加XDSL支持</h2><p>任何XML和JSON都可以被自动改造为XDSL。比如说前端AMIS框架本身采用了JSON格式,我们不需要对AMIS引擎进行任何修改,通过统一的DeltaJsonLoader,就可以为AMIS引入可逆计算的分解合并机制。</p>
<figure class="highlight json"><table><tr><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br> <span class="hljs-attr">&quot;x:extends&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;继承已有的其他AMIS文件,实现页面分解,AMIS并没有内置的分解机制&quot;</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">&quot;title&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;在继承的页面基础上可以差量化定制修正&quot;</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">&quot;x:override&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;缺省合并运算采用merge方式,可以通过x:override修改为remove/replace/bounded-merge等&quot;</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">&quot;x:gen-extends&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;这里可以写xpl模板语言来动态生成基础对象结构&quot;</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">&quot;feature:on&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;这里的特性表达式返回true的时候本节点才存在,否则自动删除节点&quot;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p>具体XDSL使用了哪些语法属性,参见<a target="_blank" rel="noopener" href="https://gitee.com/canonical-entropy/nop-entropy/blob/master/nop-xdefs/src/main/resources/_vfs/nop/schema/xdsl.xdef">xdsl.xdef元模型定义</a>.<br><code>x:override</code>合并算子的介绍参见<a href="../x-override/">x-override.md</a></p>

</div>
<footer class="Article-footer col-md-3">
Expand Down

0 comments on commit 79d2c81

Please sign in to comment.