C ++代码生成的优雅方式 [英] Elegant way for C++ code generation

查看:147
本文介绍了C ++代码生成的优雅方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am currently working on a database related project in which I generate a lot of C++ code. This code is compiled then and loaded as a dynamic library. I use this techniques to build efficient code for the database schema and queries.

目前,我使用简单的文件写生成代码(什么是好的,概念实施)。现在,我正在寻找一个更优雅但可比较灵活的解决方案来生成C ++代码。

Currently, I am using simple file write to generate the code (what was okay for the proof-of-concept implementation). Now, I am searching for a more elegant but comparable flexible solution to generate C++ code.

我搜索了很多,但我发现的所有解决方案是相当复杂/

I searched quite a lot but all the solutions I found so far are rather complex/extensive, not efficient enough, or not flexible enough.

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

What libraries are you using in your C++ projects to generate code?

Best,
Moritz

Best, Moritz

推荐答案

您可以使用程序转换系统(PTS)以可靠的方式定义和编写代码模板。

You can use a program transformation system (PTS) to define and compose code templates in a reliable way.

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

Most PTS enable one to define a grammar, and then parse source code into ASTs using that grammar. More importantly, they accept patterns: source code fragments (usually of a nonterminal or a list of nonterminals) with placeholders that correspond to wellformed sub-fragments (nonterminals representing subtrees). These patterns usually insist that a named placeholder match identically (see example below). Such patterns can be used to match against a parsed AST as a way to find code fragments using the surface syntax.

所以,可以使用一个模式:

So, one might use a pattern:

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

来搜索由相同子树的产品组成的子表达式。
这将匹配

to hunt for subexpressions which consist of products of identical subtrees. This will match

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

但不包括

    2 * (x-3)

但同样有趣的是, em>代码生成器,通过为变量实例化具有绑定值(树)的模式。所以,
instantiate x_squared(2 ^ x)产生

But just as interestingly, such patterns can be used as code generators, by instantiating the pattern with bound value (trees) for the variables. So, "instantiate x_squared(2^x)" produces

     (2^x)*(2^x)

本身,这只是一种奇特的宏计划。这是一个更好的,因为它可以告诉你在编译时(模式)你正在编写的是否有意义。所以你得到代码片段的组成的类型检查。例如,你可能会意外编写instantiate x_squared(int q),但一个好的PTS将对象int q不是一个term;

By itself, this is just a fancy sort of macro scheme. It is a lot better, in that it can tell you "at compile time" (for the patterns) whether what you are composing makes sense or not. So you get type checking of the composition of the code fragments. For instance, you might accidentally code "instantiate x_squared(int q)", but a good PTS will object that "int q" is not a "term"; you find the bug when you build the code generator.

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

Where this gets really interesting is where one can build many different code fragments, from many different patterns, and compose those fragments with yet more patterns. This allows one to build very complex code. All of this is a (syntax-type) safe way; resulting trees are valid syntax. (You can still bollix semantics; nothing is perfect). As the complexity of the code you can generate goes up, it is good to have this additional checking to help you avoid generating bad code.

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

A PTS has an additional advantage: after composing code fragments, it can apply source-to-source transformations to optimize the resulting code. Thus you can produce optimized code according to your ability to write matching transformations, and harnessing knowledge you have during code generation. Imagine you generate code for a matrix multiply:

 ... P * Q ...

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

and your code generator somehow or other knows that Q is an identity matrix. Then the following optimization can remove an expensive matrix multiply:

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

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

This transformation takes advantage of pattern matching (to find a matrix product) in the generated code, pattern instantiation (to generate a replacement for the matched product), and additional knowledge or analysis (is_identity_matrix) that the code generation can do.

您需要一个能够处理C ++解析的PTS;这些都有点难以找到。我设计的(DMS软件再造工具包)恰好这样做。此答案中的示例为DMS样式。

You need a PTS capable of handling C++ parsing; those are a bit hard to find. The one I designed (DMS Software Reengineering Toolkit) happens to do this. The examples in this answer are DMS-style.

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

Here's a technical paper that describes a large-scale reengineering task done by DMS on C++ code. A number of examples in the paper are actually quite complex patterns used to instantiate code; the reengineering task had to generate a new set of APIs for an existing chunk of code.

这篇关于C ++代码生成的优雅方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆