我正在生成 C++ 代码,看起来它会变得非常混乱,即使我的简单生成类已经有大量的特殊情况。这是现在的代码:http: //github.com/alex/alex-s-language/tree/local%2Fcpp-generation/alexs_lang/cpp。
8 回答
我编写Cog部分是为了从 XML 数据模式生成 C++ 代码。它允许您使用嵌入在 C++ 源文件中的 Python 代码来生成 C++ 源代码。
我用于代码生成的一种技术是完全不用担心代码生成器中的格式。然后,作为生成代码后的下一步,运行它indent
以合理地格式化它,以便您可以阅读(更重要的是,调试)它。
请参阅构建测试用例的工具。
目前尚不清楚您的问题是什么。
如果您的问题是“我如何处理生成类中的所有特殊情况?” 那么这里有一些建议。如果您的问题是其他问题,请更新您的问题。
使用模板生成器。 例如, Mako会让您的生活更简单。
写一个你的结果的例子。
${thing}
用占位符替换零件。由于您从可行的东西开始,因此将其转换为模板很容易。当用另一种语言生成代码时,您需要将所有其他语言的类定义设计为灵活的汇编。您希望生成尽可能少的新鲜代码。您想稍微调整和自定义,但又不想从头开始生成很多东西。
特殊情况最好用普通多态处理。公共超类的单独子类可以实现各种异常和特殊情况。策略设计模式 可以很好地处理真正复杂的情况。
本质上,您拥有代表现实世界对象的 Python 类。这些类具有可以适应 C++ 模板的属性,以生成这些对象的 C++ 版本。
我同意 S.Lott 的观点,你应该写出一个你想要生成的例子。
解决代码生成问题应该比没有解决问题简单。
这是因为您的整个程序必须处理大量输入信息,并且如果该信息的子集很少更改,例如每周一次,则代码生成器只需要以该子集为条件。剩余输入的生成代码条件更频繁地更改。这是一种分而治之的策略。它的另一个名称是“部分评估”。
生成的代码也应该运行得更快,因为它不太通用。
在您的特定情况下,在 2 次(或更多次)通道中进行代码生成没有害处。就像在第 1 阶段一样,您会生成声明。在通过 2 时,您生成过程代码。或者,您可以生成两个输出流,并在最后连接它们。
希望有帮助。对不起,如果我只是说显而易见的话。
正如 Ned 所建议的,Cog 是编写样板代码的绝佳工具。例如,我必须为某些类编写 AOP 风格的事件系统支持,它会像这样工作:
- 你为一个类声明一个方法
- 对于每个方法,都需要在调用时触发一个事件,将方法的参数作为事件参数传递
所以我做了一个特殊的 python 声明函数,我会在一个 cog 区域上调用它,它会为每个方法和事件生成样板声明和定义。在 cog 区域的末尾,用户放置一个隐藏实现并由 AOP 包装器调用的函数的代码块,大致如下:
class MyFoo
{
public:
/*[[[cog
import myAOPDeclarators
AOP = myAOPDeclarators.AOP
AOP.declareAOPInterceptorMethod( 'invokeSomeStuff' , '(int param1, std::string param2)' )
]]]*/
//AOP wrapper
void invokeSomeStuff_ImplementationAOP(int param1, std::string param2);
void invokeSomeStuff(int param1, std::string param2) {
sendAOPPreEvent( param1 , param2 , "invokeSomeStuff" );
invokeSomeStuff_ImplementationAOP( param1 , param2);
}
void invokeSomeStuff_ImplementationAOP(int param1, std::string param2)
//[[[end]]]
{
// ...invokeSomeStuff implementation, not automatically generated
}
我可以为您提供代码生成的最佳指南是;使您生成的代码与您手写的代码一样具有可读性。它使代码生成的使用变得透明(甚至比模板代码更透明,购买 YMMV),当然,正如 Greg 建议的那样,缩进可以在之后应用,因此将缩进修补与代码生成混合起来真的没有任何意义如果一个工具无论如何都可以对源文件进行后处理
我有一个代码生成系统,我使用它的最佳选择之一是将大部分生成的程序放在非生成代码中,例如库/运行时。使用模板也很有效。复杂的模板系统可能很难手动使用,但您不能手动使用它们,因此请利用这一点。
它实际上只是直接递归,除了我需要将所有函数声明拉出并将它们放在其他地方,并且对于所有函数调用我需要构建所有参数的向量,然后将其传递给函数,因为 C++ 没有向量的语法。
我也在寻找类似的东西并发现了这个问题。我对 cog 不是很满意,所以我最终编写了自己的类似但添加了一些 (imo) 非常需要的功能。