使用for循环生成源代码

时间:2016-04-20 09:32:32

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

我有两个类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];
}

2 个答案:

答案 0 :(得分:0)

它可能是这样的:

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;
}

答案 1 :(得分:0)

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

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

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

C1和C2需要一种方式,它们可以像你一样存储符号而不仅仅是常量。最好的方法是支持它,让它们有一个字符串值作为成员而不是int。

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