使用 for 循环生成源代码
Generate source code with for loop
我有两个 类 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];
}
可能是这样的:
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;
}
您需要的是 for 循环的某种形式的抽象表示。因此,不是编写从 1 到 100 的循环,而是创建循环类型的对象,如下所示:
auto loop = createLoop("int", "i", 1, 100);
loop->add( createC1("i") );
loop->add( createC2("i") );
loop->printCode(stdout);
通过将构造函数封装在工厂方法中,可以让工厂方法returnunique_ptr
,从而避免内存泄漏,摆脱所有手动跟踪堆对象(不要'不要在你的代码库中使用 raw new。
C1 和 C2 需要一种方法,它们可以存储符号,而不仅仅是常量,就像您拥有的那样。最好的支持方式,让他们有一个字符串值作为成员而不是 int。
循环中的 printCode 必须从其成员 C1 和 C2 调用 printCode。
我有两个 类 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];
}
可能是这样的:
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;
}
您需要的是 for 循环的某种形式的抽象表示。因此,不是编写从 1 到 100 的循环,而是创建循环类型的对象,如下所示:
auto loop = createLoop("int", "i", 1, 100);
loop->add( createC1("i") );
loop->add( createC2("i") );
loop->printCode(stdout);
通过将构造函数封装在工厂方法中,可以让工厂方法returnunique_ptr
,从而避免内存泄漏,摆脱所有手动跟踪堆对象(不要'不要在你的代码库中使用 raw new。
C1 和 C2 需要一种方法,它们可以存储符号,而不仅仅是常量,就像您拥有的那样。最好的支持方式,让他们有一个字符串值作为成员而不是 int。
循环中的 printCode 必须从其成员 C1 和 C2 调用 printCode。