C ++代码生成的优雅方式

时间:2015-01-23 04:54:29

标签: c++ code-generation

我目前正在开发一个与数据库相关的项目,我在其中生成了大量的C ++代码。然后编译此代码并将其作为动态库加载。我使用这种技术为数据库模式和查询构建有效的代码。

目前,我使用简单的文件写入来生成代码(对于概念验证实现来说还可以)。现在,我正在寻找一种更优雅但可比较的灵活解决方案来生成C ++代码。

我搜索了很多,但到目前为止我找到的所有解决方案都相当复杂/广泛,效率不够,或者不够灵活。

您在C ++项目中使用哪些库来生成代码?

最佳, Moritz的

1 个答案:

答案 0 :(得分:1)

您可以使用program transformation system (PTS)以可靠的方式定义和撰写代码模板。

大多数PTS允许一个人定义语法,然后使用该语法将源代码解析为AST。更重要的是,它们接受模式:源代码片段(通常是非终结符或非终结符列表),其占位符对应于格式良好的子片段(非终结符表示子树)。这些模式通常坚持命名占位符匹配相同(参见下面的示例)。这些模式可用于匹配解析的AST,作为使用表面语法查找代码片段的方法。

所以,人们可能会使用一种模式:

   pattern x_squared(t: term): product
      = " \t * \t ";

寻找由相同子树的产品组成的子表达式。 这将匹配

   (p + q[17])*(p+q[17)

但不是

    2 * (x-3)

但同样有趣的是,这些模式可以用作代码生成器,通过实例化变量的绑定值(树)模式。所以, "实例化x_squared(2 ^ x)"产生

     (2^x)*(2^x)

就其本身而言,这只是一种奇特的宏观方案。它更好,因为它可以告诉你"在编译时" (对于模式)你的作曲是否有意义。因此,您可以对代码片段的组成进行类型检查。例如,您可能会意外编码"实例化x_squared(int q)"但是一个好的PTS会反对" int q"不是"术语&#34 ;;你在构建代码生成器时发现了这个bug。

这真的很有趣的地方是可以从许多不同的模式构建许多不同的代码片段,并用更多的模式组合这些片段。这允许人们构建非常复杂的代码。所有这些都是(语法类型)安全的方式;结果树是有效的语法。 (你仍然可以使用bollix语义;没有什么是完美的)。由于您可以生成的代码的复杂性增加,最好进行额外的检查以帮助您避免生成错误的代码。

PTS还有一个额外的优势:在编写代码片段之后,它可以应用源到源的转换来优化生成的代码。因此,您可以根据编写匹配转换的能力以及利用代码生成期间的知识生成优化代码。 想象一下,您为矩阵乘法生成代码:

 ... P * Q ...

并且您的代码生成器以某种方式或其他方式知道Q是一个单位矩阵。 然后,以下优化可以删除昂贵的矩阵乘法:

  rule optimize_matrix_times_unit(m: term, n: term): product -> product
       " \m * \q "
   ->  " \m "
    if is_identity_matrix(q)

此转换利用生成代码中的模式匹配(查找矩阵产品),模式实例化(生成匹配产品的替换)以及代码生成可以执行的其他知识或分析(is_identity_matrix)。

您需要一个能够处理C ++解析的PTS;那些有点难找。我设计的那个(DMS Software Reengineering Toolkit)就是这么做的。这个答案中的例子是DMS风格。

这里的a technical paper描述了DMS在C ++代码上完成的大规模再造任务。本文中的一些例子实际上是用于实例化代码的非常复杂的模式;重新设计任务必须为现有的代码块生成一组新的API。