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

Elegant way for C++ code generation

本文关键字:方式 代码生成 C++      更新时间:2023-10-16

我目前正在做一个与数据库相关的项目,其中我生成了很多C++代码。然后编译此代码并将其加载为动态库。我使用此技术为数据库架构和查询构建高效的代码。

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

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

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

最好莫里茨

可以使用程序转换系统 (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"不是"术语";您在构建代码生成器时会发现错误。

真正有趣的是,人们可以从许多不同的模式构建许多不同的代码片段,并用更多的模式组合这些片段。这允许人们构建非常复杂的代码。 所有这些都是一种(语法类型)安全的方式;生成的树是有效的语法。(你仍然可以使用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软件再造工具包)恰好可以做到这一点。 此答案中的示例是 DMS 样式的。

这是一篇技术论文,描述了DMS对C++代码完成的大规模重新设计任务。论文中的许多示例实际上是用于实例化代码的非常复杂的模式;重新设计任务必须为现有代码块生成一组新的 API。