智能自动C代码生成器,支持Python中的嵌套if

2 投票
4 回答
562 浏览
提问于 2025-04-16 03:26

我正在用Python自动生成C++代码,特别是我需要从一系列事件中选择一些事件。我声明了一些选择:

selectionA = Selection(name="selectionA", formula="A>10")
selectionB = Selection(name="selectionB", formula="cobject->f()>50")
selectionC = selectionA * selectionB # * means AND

这段代码会生成C++代码:

for(...) { // cicle on events
  event = GetEvent(i);

  bool selectionA = A>10;
  bool selectionB = cobject->f()>50;
  bool selectionC = (A>10) and (cobject->f()>50);

  if (selectionA) { histo_selectionA->Fill(event); }
  if (selectionB) { histo_selectionB->Fill(event); }
  if (selectionC) { histo_selectionC->Fill(event); }
}

这并不是很聪明,因为更聪明的代码应该是:

bool selectionC = selectionA and selectionB

这个问题看起来简单,但实际上并不简单,因为我有100多个基础选择(比如selectionAselectionB)和300多个派生选择,当然,派生选择可以从其他派生选择中派生出来。显而易见的派生选择并不是通过常规模式从基础选择中派生出来的。

我知道这个问题很难回答,但有没有人能给我一些提示?比如:真的有必要写聪明的代码吗?我的意思是,编译器不能优化这段代码吗?

4 个回答

0

作为我评论的补充,我觉得你甚至不需要我之前提到的那个跟踪变量。为什么不试试这个呢?

import string

class Selection:
    selections = []
    letters = string.letters[26:] + string.letters[:26]

    def __init__(self, name, formula):
        self.name = name
        self.formula = formula
        Selection.selections.append(self)

    def __mul__(self, selection):
        name = 'selection' + letters[len(selections)]
        return Selection(name, self.name + ' and ' + selection.name)

    @classmethod
    def generate(c):
        code = []
        for selection in c.selections:
            code.append('bool ')
            code.append(selection.name)
            code.append(' = ')
            code.append(selection.formula)
            code.append(';\n')

        code.append('\n')

        for selection in c.selections:
            code.append('if (')
            code.append(selection.name)
            code.append(') { histo_')
            code.append(selection.name)
            code.append('->Fill(event); }\n')

        return ''.join(code)

当然,这个方法只适用于你只有52个选择对象的情况,但这个限制是因为这个类只生成像selection[A-Za-z]这样的名称。

1

编译器可能会对这段代码进行优化,但如果你有成百上千个复杂的表达式相互依赖,我怀疑效果会好到哪里去。

不过更基本的问题是:你真的需要优化吗?计算机运行得很快,如果你不经常执行那段代码,cobject->f()>50运行一次和十次可能没什么太大区别。

另一方面,如果cobject->f()有副作用(比如,它会打印一些东西),那么编译器就不会优化掉重复的调用,你需要确保在生成的代码中,它只在你希望打印东西的次数被调用。

最好的解决办法是,如果你的Selection类在作为派生定义的一部分使用时,能够直接输出name而不是formula。这有多难,取决于你生成代码的方式。

2

编译器可能无法优化这段代码,部分原因是 cobject->f() 可能会有一些编译器看不到的副作用。

你可以通过将你的布尔值声明为 const 来稍微帮助一下优化。

另外,看起来你已经在重载运算符来组合选择了。所以,想要让组合选择使用其组成部分的名称,而不是表达式,这应该不会太难。这可以为你做一些优化,并且如果你把选择的布尔值声明为 const,编译器可能会进一步优化。

你还需要注意,在Python中创建选择对象时,要按照相同的顺序来初始化 bool 标志。这可以确保每个 bool 在后续使用之前都已经声明和初始化。你可以通过在Python的 Selection 类中创建一个列表,并在 __init__ 方法中将新的 Selection 添加到这个列表来实现。当然,如果你创建了 Selection 对象后又把它们丢掉,那可能会有问题。但如果你把它们都保留着,那就没问题了。

撰写回答