【问题标题】:What are some techniques for code generation?有哪些代码生成技术?
【发布时间】:2010-09-22 14:41:00
【问题描述】:

我正在生成 C++ 代码,看起来它会变得非常混乱,即使我的简单生成类已经有大量的特殊情况。这是现在的代码:http://github.com/alex/alex-s-language/tree/local%2Fcpp-generation/alexs_lang/cpp

【问题讨论】:

    标签: c++ python code-generation


    【解决方案1】:

    我编写Cog 部分是为了从 XML 数据模式生成 C++ 代码。它允许您使用嵌入在 C++ 源文件中的 Python 代码来生成 C++ 源代码。

    【讨论】:

      【解决方案2】:

      我用于代码生成的一种技术是完全不用担心代码生成器中的格式。然后,作为生成代码后的下一步,通过indent 运行它以合理地格式化它,以便您可以阅读(更重要的是,调试)它。

      【讨论】:

      • 嗯... indent 仅适用于 C。而且在生成 Python 代码时,你真的必须担心格式化
      • eliben:没错,你必须为 Python 做一些更复杂的事情。我想知道是否有任何模块可以帮助做到这一点。
      • 在 Python 中几乎不需要代码生成,因为您可以使用动态语言和内省/反射技术来达到相同的目的。
      • 生成漂亮的代码非常容易。只需使用 push()/write()/pop() 方法创建一个类,并确保 write() 方法考虑了当前的 push/pop 计数。我每天都使用代码生成器,生成的 C++ 和 C# 代码看起来和我自己的代码一模一样。
      • @MB:这是一种方法,但在 XSLT 中很难做到(是的,我使用 XSLT 生成 C++ 代码)。
      【解决方案3】:

      Tooling to Build Test Cases

      不清楚你的问题是什么。

      如果您的问题是“如何处理生成类中的所有特殊情况?”那么这里有一些建议。如果您的问题是其他问题,请更新您的问题。

      1. 使用模板生成器。例如,Mako 会让您的生活更简单。

        写一个你的结果的例子。用${thing} 占位符替换部件。既然您从可行的东西开始,将其转换为模板很容易。

      2. 当生成另一种语言的代码时,您需要将所有其他语言的类定义设计为灵活汇编。您希望生成尽可能少的新鲜代码。您想稍微调整和自定义,但又不想从头开始生成很多东西。

      3. 特殊情况最好用普通多态处理。公共超类的独立子类可以实现各种异常和特殊情况。 策略设计模式可以很好地处理真正复杂的情况。

        本质上,您拥有代表现实世界对象的 Python 类。这些类具有可以适应 C++ 模板的属性,以生成这些对象的 C++ 版本。

      【讨论】:

      • 您博客上的文章还有其他链接吗?链接失效了。
      【解决方案4】:

      我同意 S.Lott 的观点,你应该写出一个你想要生成的例子。

      使用代码生成解决问题应该比没有解决问题简单。

      这是因为您的整个程序必须处理大量输入信息,并且如果该信息的子集很少更改(例如每周一次),则代码生成器只需要以该子集为条件。剩余输入的生成代码条件更频繁地更改。 这是一种分而治之的策略。它的另一个名称是“部分评估”。

      生成的代码也应该运行得更快,因为它不太通用。

      在您的具体情况下,在 2 次(或更多次)通道中生成代码并没有什么害处。就像在第 1 阶段一样,您会生成声明。在通过 2 时,您生成过程代码。或者,您可以生成两个输出流,并在最后将它们连接起来。

      希望对您有所帮助。抱歉,我只是在说显而易见的事情。

      【讨论】:

        【解决方案5】:

        正如 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 建议的那样,缩进可以在之后应用,因此将缩进修补与代码生成混合起来真的没有任何意义如果一个工具无论如何都可以对源文件进行后处理

        【讨论】:

          【解决方案6】:

          我有一个代码生成系统,我使用它的最佳选择之一是将大部分生成的程序放在非生成代码中,例如库/运行时。使用模板也很有效。复杂的模板系统可能很难手动使用,但你不能手动使用它们,所以要利用它。

          【讨论】:

            【解决方案7】:

            它实际上只是直接递归,除了我需要将所有函数声明拉出并将它们放在其他地方,事实上,对于所有函数调用,我需要构建所有参数的向量,然后传递它到函数,因为 C++ 没有向量的语法。

            【讨论】:

            • 它确实有可变参数的语法,如果你需要的话。但是您想生成将三个参数推送到向量并将其传递给四参数函数的代码吗?
            【解决方案8】:

            我也在寻找类似的东西并发现了这个问题。我对 cog 不是很满意,所以我最终自己编写了一个类似的但添加了一些 (imo) 非常需要的功能。

            https://github.com/icholy/swapm

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-03-10
              • 1970-01-01
              • 1970-01-01
              • 2015-07-31
              • 2010-09-05
              • 1970-01-01
              • 2011-02-20
              相关资源
              最近更新 更多