《领域特定语言》一1.5使用代码生成

1.5使用代码生成

在迄今为止的讨论中,要处理DSL,组装“语义模型”(第11章),然后执行语义模型,提供我们希望从控制器得到的行为。在语言圈子里,这种方式称为解释(interpretation)。在解释文本时,会先解析文本,然后程序立刻产生结果。(在软件圈子里,解释是个棘手的词语,它承载了太多含义,然而,这里严格限制为立即执行的形式。)
在语言领域里,与解释相对的是编译。在编译(compilation)时,先解析程序文本,产生中间输出,然后单独处理输出,提供预期行为。在DSL的上下文里,编译方式通常指的是代码生成(code generation)。
用状态机解释这个差异有点困难,因此,换用另外一个小例子。想象一下,有某种规则判定人们是否符合某种资格,也许是为了满足保险资格。比如,如图1-5所示,一个规则是年龄在21~40岁。这个规则可以是一个DSL,检查像我这样的候选人是否具备资格。
如果解释,资格判定处理器会解析规则,在执行时加载语义模型,也许是启动时加载。当检查某个候选人时,它会对 这个候选人运行语义模型,获得一个结果。
如图1-6所示,在编译的情况下,解析器会加载语义模型,把它当做资格-判定处理器构建过程的一部分。在构建期间,DSL处理器会产生一些代码,这些代码经过编译、打包,并且纳入资格判定处理器,也可能当做某种共享库。然后,运行这段中间代码,对候选人进行评估。

例子里的状态机使用的是解释:在运行时解析配置代码,并组成语义模型。但其实也可以生成一些代码,以免在烤面包机里出现解析器和模型代码。
代码生成通常很笨拙,因为它常常需要进行额外的编译步骤。为了构建程序,首先需要编译状态框架和解析器,其次运行解析器,为格兰特小姐的控制器生成源代码,然后编译生成的代码。这样做,构建过程就变得复杂许多。
然而,代码生成的一个优势在于,编写解析器和生成代码可以用不同的语言。在这个情况下,如果生成代码用的是动态语言,比如JavaScript或是JRuby,第二个编译步骤就可以省略。
如果所用DSL的语言平台缺乏支持DSL的工具,代码生成的作用也会凸显出来。比如,我们不得不在一些老式的烤面包机上运行这个安全系统,而它们又只能理解编译过的C,那我们可以这样做,实现一个代码生成器,使用组装的语义模型作为输入,产生可以编译为运行在老式烤面包机的C代码。在最近做的一些项目里,我们曾为MathCAD、SQL和 COBOL等生成代码。
许多与DSL相关的作品都会关注代码生成,更有甚者,把代码生成当做这个活动的主要目标。随之而来的就是,涌现了一大批文章和书籍,赞美代码生成的优点。然而,在我看来,代码生成仅仅是一种实现机制,实际上,大多数情况下 都用不到。当然,有很多情况必须要用代码生成,但的确有很多情况确实用不到。
许多人用了代码生成之后,就舍弃了语义模型,他们在解析输入文本之后,就直接产生生成的代码。虽然对于使用代码生成的DSL而言,这也是一种常见的方式,但除非是最简单的情况,否则不推荐任何人这么做。语义模型的存在,可以将解析、执行语义以及代码生成分开。整个活动会因为这个划分变得简单许多。它也给了我们改变自己想法的机会; 比如,无须修改代码生成的例程就可以把内部DSL改成外部DSL。类似地,可以很容易产生多种输出,而无须担心解析器变得复杂。就同一种语义模型而言,既可以用解释模型,也可以选择代码生成。
因此,在本书的大部分内容里,假设存在一个语义模型,它是DSL工作的核心。
常见的代码生成风格有两种。第一种是“第一遍”代码,这种代码是一个模板,之后要手动修改。第二种是确保生成代码绝对不需要手动修改,也许还要排除调试期间所加的追踪信息。我几乎总是倾向于后者,因为这样可以更自由地重 新生成代码。对DSL而言,这点尤其正确,因为我们希望对于DSL所定义的逻辑而言,它是主要的表现形式。这意味着,无论何时,要修改行为,必须能够轻松修改DSL。因此,我们必须保证,任何生成的代码都没有经过手动编辑,虽然它可以调用手写的代码,或者由手写的代码调用。

时间: 2024-10-21 23:38:39

《领域特定语言》一1.5使用代码生成的相关文章

《领域特定语言》一导读

前 言 在我开始编程之前,DSL(Domain–Specific Language,领域特定语言)就已经成了程序世界中的一员.随便找个UNIX或者Lisp老手问问,他一定会跟你滔滔不绝地谈起DSL是怎么成为他的镇宅之宝的,直到你被烦得痛不欲生为止.但即便这样,DSL却从未成为计算领域的一大亮点.大多数人都是从别人那里学到DSL,而且只学到了有限的几种技术. 我写这本书就是为了改变这个现状.我希望通过本书介绍的大量DSL技术,让你有足够的信息来做出决策:是否在工作中使用DSL,以及选择哪一种DSL

如何设计一门编程语言(十) 正则表达式与领域特定语言(DSL)

几个月前就一直有博友关心DSL的问题,于是我想一想,我在gac.codeplex.com里面也创建了一些DSL,于是今天就来说一说这个事情. 创建DSL恐怕是很多人第一次设计一门语言的经历,很少有人一开始上来就设计通用语言的.我自己第一次做这种事情是在高中写这个傻逼ARPG的时候了.当时做了一个超简单的脚本语言,长的就跟汇编差不多,虽然每一个指令都写成了调用函数的形态.虽然这个游戏需要脚本在剧情里面控制一些人物的走动什么的,但是所幸并不复杂,于是还是完成了任务.一眨眼10年过去了,现在在写Gac

《领域特定语言》一第1章 入 门 例 子1.1 哥特式建筑安全系统

第1章 入 门 例 子 落笔之初,我需要快速地解释一下本书的内容,就是解释什么是领域特定语言(Domain– Specific Language,DSL).为达此目的,我一般都会先展示一个具体的例子,随后再给出抽象的定义.因此,我会从一个例子开始,展示DSL可以采用的不同形式.在第2章里,我会试着把这个定义概括为一些更广泛适用的东西. 1.1 哥特式建筑安全系统 在我的童年记忆里,电视上播放的那些低劣的冒险电影是模糊却持久的.通常,这些电影的场景会安排某个古旧的城堡.密室或走廊在其中起着重要的作

《领域特定语言》一第2章 使用DSL 2.1定义DSL

第2章 使用DSL 看过上一章的例子后,即便尚未给出DSL的一般定义,对于何为DSL,你也应该已经有了自己的认识.(第10章中有更多例子.)现在,要开始讨论DSL的定义及其优势与问题.这样就可以为下一章讨论DSL实现提供一些上下文. 2.1定义DSL "领域特定语言"是一个很有用的术语和概念,但其边界很模糊.一些东西很明显是DSL,但另一些可能会引发争议.这一术语由来已久,不过,正如软件行业中的很多东西一样,它也从未有过一个确切的定义.然而,就本书而言,定义是非常有价值的.领域特定语言

《领域特定语言》一1.3 为格兰特小姐的控制器编写程序

1.3 为格兰特小姐的控制器编写程序 至此,我们已经实现了状态机模型,接下来,就可以为格兰特小姐的控制器编写程序了,如下所示: Event doorClosed = new Event("doorClosed", "D1CL"); Event drawerOpened = new Event("drawerOpened", "D2OP"); Event lightOn = new Event("lightOn&quo

《领域特定语言》一2.4 广义的语言处理

2.4 广义的语言处理 本书是关于领域专用语言的,但它也涉及语言处理技术.之所以二者重合,是因为在普通的开发团队里,用到语言处理技术的情况,90%都是为了DSL.但是,这些技术也可以用于其他方面,若不讨论这些情况,将是我的失职.我曾遇到过这方面一个很好的例子,那是在一次拜访ThoughtWorks项目团队时.他们有一个任务,要与某第三方系统通信,发送的消息以COBOL copybook定义.COBOL copybook是一种用来描述记录的数据结构格式.因为系统中有很多地方要用到,所以我的同事Br

《领域特定语言》一1.2 状态机模型

1.2 状态机模型 一旦团队达成共识,认为对于指定控制器如何运作而言,状态机是一个恰当的抽象,那么,下一步就是确保这个抽象能够运用到软件自身.如果人们在考虑控制器行为时,也要考虑事件.状态和转换,那么,我们希望这些词汇也可以出现在软件代码里.从本质上说,这就是领域驱动设计(Domain–Driven Design)中的Ubiquitous Language [Evans DDD] 原则,也就是说,我们在领域人员(那些描述建筑安全该如何运作的人)和程序员之间构建的一种共享语言.对于Java程序来说

《领域特定语言》一2.3DSL的问题

2.3DSL的问题 前面已经讨论了何时该采用DSL,接下来就该谈论什么时候不该采用DSL,或者至少是使用DSL应注意的问题.从根本上说,不使用DSL的唯一原因就是,在你的场景下,使用DSL得不到任何好处,或者,至少是DSL的好处不足以抵消构建它的成本.虽然DSL在有些场合下适用,但同样会带来一些问题.总的来说,我认为通常是高估了这些问题,一般人们不太熟悉如何构造DSL,以及DSL如何适应更为广阔的软件开发图景.还有,许多常提及的DSL问题混淆了DSL和模型,这也伤及了DSL的优势.许多DSL问题

《领域特定语言》一第3章 实现DSL 3.1DSL处理之架构

第3章 实现DSL 至此,对于什么是DSL,以及为何要用DSL,我们已经透彻理解.如果要开始构建DSL,那么现在该深入研究所用的技术了.虽然构建内部DSL和外部DSL所用的技术有所不同,但它们还是有一些共通之处的.本章主要关注内部DSL和外部DSL的一些共通问题,而下一章再讨论各自具体的问题.本章先不谈语言工作台,留待后续探讨. 3.1DSL处理之架构 关于DSL实现的大体结构(见图3-1),也就是所谓的DSL系统架构─可能是我们要谈论的最重要的内容之一. 迄今为止,你应该已经厌倦了听我说了无数