网站开发搜索功能怎么实现,车子网站,html5自适应网站源码,泉州网站的建设1.5使用代码生成 在迄今为止的讨论中#xff0c;要处理DSL#xff0c;组装“语义模型”#xff08;第11章#xff09;#xff0c;然后执行语义模型#xff0c;提供我们希望从控制器得到的行为。在语言圈子里#xff0c;这种方式称为解释#xff08;interpretation… 1.5使用代码生成 在迄今为止的讨论中要处理DSL组装“语义模型”第11章然后执行语义模型提供我们希望从控制器得到的行为。在语言圈子里这种方式称为解释interpretation。在解释文本时会先解析文本然后程序立刻产生结果。在软件圈子里解释是个棘手的词语它承载了太多含义然而这里严格限制为立即执行的形式。在语言领域里与解释相对的是编译。在编译compilation时先解析程序文本产生中间输出然后单独处理输出提供预期行为。在DSL的上下文里编译方式通常指的是代码生成code generation。用状态机解释这个差异有点困难因此换用另外一个小例子。想象一下有某种规则判定人们是否符合某种资格也许是为了满足保险资格。比如如图1-5所示一个规则是年龄在2140岁。这个规则可以是一个DSL检查像我这样的候选人是否具备资格。如果解释资格判定处理器会解析规则在执行时加载语义模型也许是启动时加载。当检查某个候选人时它会对 这个候选人运行语义模型获得一个结果。如图1-6所示在编译的情况下解析器会加载语义模型把它当做资格-判定处理器构建过程的一部分。在构建期间DSL处理器会产生一些代码这些代码经过编译、打包并且纳入资格判定处理器也可能当做某种共享库。然后运行这段中间代码对候选人进行评估。 例子里的状态机使用的是解释在运行时解析配置代码并组成语义模型。但其实也可以生成一些代码以免在烤面包机里出现解析器和模型代码。代码生成通常很笨拙因为它常常需要进行额外的编译步骤。为了构建程序首先需要编译状态框架和解析器其次运行解析器为格兰特小姐的控制器生成源代码然后编译生成的代码。这样做构建过程就变得复杂许多。然而代码生成的一个优势在于编写解析器和生成代码可以用不同的语言。在这个情况下如果生成代码用的是动态语言比如JavaScript或是JRuby第二个编译步骤就可以省略。如果所用DSL的语言平台缺乏支持DSL的工具代码生成的作用也会凸显出来。比如我们不得不在一些老式的烤面包机上运行这个安全系统而它们又只能理解编译过的C那我们可以这样做实现一个代码生成器使用组装的语义模型作为输入产生可以编译为运行在老式烤面包机的C代码。在最近做的一些项目里我们曾为MathCAD、SQL和 COBOL等生成代码。许多与DSL相关的作品都会关注代码生成更有甚者把代码生成当做这个活动的主要目标。随之而来的就是涌现了一大批文章和书籍赞美代码生成的优点。然而在我看来代码生成仅仅是一种实现机制实际上大多数情况下 都用不到。当然有很多情况必须要用代码生成但的确有很多情况确实用不到。许多人用了代码生成之后就舍弃了语义模型他们在解析输入文本之后就直接产生生成的代码。虽然对于使用代码生成的DSL而言这也是一种常见的方式但除非是最简单的情况否则不推荐任何人这么做。语义模型的存在可以将解析、执行语义以及代码生成分开。整个活动会因为这个划分变得简单许多。它也给了我们改变自己想法的机会 比如无须修改代码生成的例程就可以把内部DSL改成外部DSL。类似地可以很容易产生多种输出而无须担心解析器变得复杂。就同一种语义模型而言既可以用解释模型也可以选择代码生成。因此在本书的大部分内容里假设存在一个语义模型它是DSL工作的核心。常见的代码生成风格有两种。第一种是“第一遍”代码这种代码是一个模板之后要手动修改。第二种是确保生成代码绝对不需要手动修改也许还要排除调试期间所加的追踪信息。我几乎总是倾向于后者因为这样可以更自由地重 新生成代码。对DSL而言这点尤其正确因为我们希望对于DSL所定义的逻辑而言它是主要的表现形式。这意味着无论何时要修改行为必须能够轻松修改DSL。因此我们必须保证任何生成的代码都没有经过手动编辑虽然它可以调用手写的代码或者由手写的代码调用。