【问题标题】:Generate source code with for loop使用 for 循环生成源代码
【发布时间】:2016-08-12 21:09:03
【问题描述】:

我有两个类 C1 和 C2,它们可以通过方法 printCode() 生成 C++ 代码。使用 C1、C2 的对象,我可以生成如下 C++ 代码:

C1* array1[100];
C2* array2[100];

// Create objects to generate code
for (int i = 0; i < 100; i++) {
    array1[i] = new C1(i);
    array2[i] = new C2(i);
}
[...]
// Generate code
for (int i = 0; i < 100; i++) {
    array1[i]->printCode();
    array2[i]->printCode();
}

生成的代码:

// f represents a set of operations
// code generated by array1[0], array2[0]
(x[0], x[1], ..., x[n]) := f(0, x[0], x[1], ..., x[n]); 
// code generated by array1[1], array2[1]
(x[0], x[1], ..., x[n]) := f(1, x[0], x[1], ..., x[n]);
[...]
// code generated by array1[99], array2[99]
(x[0], x[1], ..., x[n]) := f(99, x[0], x[1], ..., x[n]);

我怎样才能生成它(相同的输出,更小的代码大小):

for (int i = 0; i < 100; i++)
    (x[0], x[1], ..., x[n]) := f(i, x[0], x[1], ..., x[n]);

编辑:C1、C2 的示例定义:

const int n = 1000; 
class C1 {
public:
    C1(int x) : my_var(x) {}
    void printCode() {
        for (int i = 0; i < n - 1; i++) {
            // func1 is defined in the generated code
            // the generated code sees foo(my_var) as a constant
            cout << "x[" << i << "] = func1(x[" << i << "], x[" << i + 1 "] + " << bar(my_var) << endl;
        }
    }

private:
    int my_var;
    int foo(int x) { ... }
}

C2 类似:

class C2 {
public:
    C2(int x) : my_var(x) {}
    void printCode() {
        for (int i = 0; i < n - 1; i++) {
            // func2 is defined in the generated code
            // the generated code sees bar(my_var) as a constant
            cout << "x[" << i << "] = func2(x[" << i << "], x[" << i + 1 "] + " << bar(my_var) << endl;
        }
    }

private:
    int my_var;
    int bar(int x) { ... }
}

如上定义C1、C2,生成的代码为:

// definitions of func1, func2
int func1(int x, int y) { ... }
int func2(int x, int y) { ... }

...

// Code generated by C1(0)
x[0] = func1(x[0], x[1]) + f0;  // f0 = C1.foo(0)
x[1] = func1(x[1], x[2]) + f0;
...
x[998] = func1(x[998], x[999]) + f0;
// Code generated by C2(0)
x[1] = func2(x[0], x[1]) + b0;  // b0 = C2.bar(0)
x[2] = func2(x[1], x[2]) + b0;
...
x[999] = func2(x[998], x[999]) + b0;

// Code generated by C1(1), C2(1)
// Code generated by C1(2), C2(2)
...
// Code generated by C1(99), C2(99)

我想要什么:

for (int i = 0; i < 100; i++) {
    x[0] = func1(x[0], x[1]) + f[i];  // f[i] = C1.foo(i)
    x[1] = func1(x[1], x[2]) + f[i];
    ...
    x[998] = func1(x[998], x[999]) + f[i];

    x[1] = func2(x[0], x[1]) + b[i];  // b[i] = C2.bar(i)
    x[2] = func2(x[1], x[2]) + b[i];
    ...
    x[999] = func2(x[998], x[999]) + b[i];
}

【问题讨论】:

  • 您需要提供更多关于您的课程C1C2 是如何实现的详细信息
  • @teivaz 我已经添加了 C1、C2 的代码。
  • 显然我添加的示例引起了一些混乱。 printCode()里面的for循环只是为了说明这个函数打印了很多代码。在我的应用程序中,printCode() 无法优化。

标签: c++ for-loop code-generation


【解决方案1】:

您需要的是某种形式的 for 循环抽象表示。因此,不要编写从 1 到 100 的循环,而是像这样在循环类型的对象上创建:

auto loop = createLoop("int", "i", 1, 100);
loop->add( createC1("i") );
loop->add( createC2("i") );
loop->printCode(stdout);

通过将构造函数封装在工厂方法中,您可以让工厂方法返回unique_ptr,从而避免内存泄漏,并摆脱所有手动跟踪堆对象(不要在您的代码库)。

C1 和 C2 需要一种方法,即它们可以存储符号而不仅仅是常量,就像您拥有的那样。支持这一点的最佳方法是让它们将字符串值作为成员而不是 int。

来自循环的 printCode 必须从它的成员 C1 和 C2 调用 printCode。

【讨论】:

    【解决方案2】:

    大概是这样的:

    void printCode() {
        cout << "for (int i = 0; i < " << n - 1 << " ; i++) {" << endl;
            // func2 is defined in the generated code
            // the generated code sees bar(my_var) as a constant
        cout << "x[i] = func2(x[i], x[i + 1] + " << bar(my_var) << ");" << endl;
        cout << "}" << endl;
    }
    

    【讨论】:

    • 对不起,如果我的解释不清楚。您的修复将创建:code_generated_by C1[0], C2[0]; code_generated_by C1[1], C2[1]; ...; code_generated_by C1[99], C2[99]。我想要的是:for (int i = 0; i &lt; 100; i++) { code_generated_by C1[i], C2[i]; }
    • 呃,在这种情况下你不能在循环中调用它。生成什么代码取决于您如何调用方法(即,如果您调用C1, C2, C1, C2,这正是将要生成的内容)。你需要一个包装器生成器。
    • 那么基本上是生成生成器的生成器?
    • 有点,是的。如果您想要一个循环,则需要对generateCode 进行一次调用-也许使用循环计数 C1/C2 参数化的生成器就足够了,该参数在内部知道如何生成C1 /C2。或者,如果您的目标是更多的重用,一个模板化的“循环”生成器只需要 C1/C2 来实现循环中打印的内容并处理循环本身
    猜你喜欢
    • 2012-01-21
    • 1970-01-01
    • 2013-12-16
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-09
    相关资源
    最近更新 更多