gpt4 book ai didi

python - 如何将 python 比较 ast 节点转换为 c?

转载 作者:行者123 更新时间:2023-12-03 13:32:39 24 4
gpt4 key购买 nike

让我们首先考虑 python3.8.5's grammar ,在这种情况下,我有兴趣弄清楚如何将 python 比较转换为 c。
为了简单起见,我们假设我们正在处理一个非常小的 Python 平凡子集,我们只想转译平凡的 Compare 表达式:

expr = Compare(expr left, cmpop* ops, expr* comparators)
如果我没记错的话,python 中的表达式如 a<b<c被转换成类似 a<b && b<c 的东西其中 b 只计算一次...所以我想在 c 中你应该做类似 bool v0=a<b; bool v1=v0<c 的事情为了防止在第一个子句为真的情况下对 b 进行多次评估。
不幸的是,我不知道如何将其放入代码中,到目前为止,这就是我所拥有的:
import ast
import shutil
import textwrap
from subprocess import PIPE
from subprocess import Popen


class Visitor(ast.NodeVisitor):
def visit(self, node):
ret = super().visit(node)
if ret is None:
raise Exception("Unsupported node")
return ret

def visit_Expr(self, node):
return f"{self.visit(node.value)};"

def visit_Eq(self, node):
return "=="

def visit_Lt(self, node):
return "<"

def visit_LtE(self, node):
return "<="

def visit_Load(self, node):
return "//load"

def visit_Name(self, node):
return f"{node.id}"

def visit_Compare(self, node):
left = self.visit(node.left)
ops = [self.visit(x) for x in node.ops]
comparators = [self.visit(x) for x in node.comparators]

if len(ops) == 1 and len(comparators) == 1:
return f"({left} {ops[0]} {comparators[0]})"
else:
lhs = ",".join([f"'{v}'" for v in ops])
rhs = ",".join([f"{v}" for v in comparators])
return f"cmp<{lhs}>({rhs})"

def visit_Call(self, node):
func = self.visit(node.func)
args = [self.visit(x) for x in node.args]
# keywords = [self.visit(x) for x in node.keywords]
return f"{func}({','.join(args)})"

def visit_Module(self, node):
return f"{''.join([self.visit(x) for x in node.body])}"

def visit_Num(self, node):
return node.n


if __name__ == "__main__":
out = Visitor().visit(
ast.parse(
textwrap.dedent(
"""
1 == 1<3
1 == (1<3)
1 == (0 < foo(0 <= bar() < 3, baz())) < (4 < 5)
foo(0 <= bar() < 3, baz())
"""
)
)
)

if shutil.which("clang-format"):
cmd = "clang-format -style webkit -offset 0 -length {} -assume-filename None"
p = Popen(
cmd.format(len(out)), stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True
)
out = p.communicate(input=out.encode("utf-8"))[0].decode("utf-8")
print(out)
else:
print(out)
如您所见,输出将是某种不可编译的 c 输出:
cmp<'==', '<'>(1, 3);
(1 == (1 < 3));
cmp<'==', '<'>((0 < foo(cmp<'<=', '<'>(bar(), 3), baz())), (4 < 5));
foo(cmp<'<=', '<'>(bar(), 3), baz());
问题,什么是算法(python 工作示例在这里是理想的,但只是一些允许我改进提供的片段的通用伪代码也可以)允许我将 python 比较表达式转换为 c?

最佳答案

正确翻译为:

if 1 == 2 < 3:
是:
int i1 = 1;
int i2 = 2;
int i3 = 3;
if(i1 == i2 && i2 < i3) {
(编辑:这仍然不正确,因为它不会短路)
或者,最后一个不必是临时变量:
int i1 = 1;
int i2 = 2;
if(i1 == i2 && i2 < 3) {
或者:(此版本在比较表达式中保留要比较的表达式)
int i1;
if(1 == (i1 = 2) && i2 < 3) {
你的编译器需要知道被比较的值是 int s 以便它可以声明临时变量。而且它还需要选择每次都不同的临时变量名,所以如果你有两个这样的比较,那么它不会尝试生成多个具有相同名称的变量。
您可能会意识到可以对表达式 2 求值。不止一次,所以编译器可以生成以下代码:
if(1 == 2 && 2 < 3) {
但这是一个可选的额外项目。
请注意,在同一个表达式中可能有多个这些:
if 1 < (2 if (6 < 7 < 8) else 3) < 4:
翻译成这样:
int i1 = 1;
int i2 = 6;
int i3 = 7;
int i4 = 8;
int i5 = (i2 < i3 && i3 < i4 ? 2 : 3);
int i6 = 4;
if(i1 < i5 && i5 < i6) {
或者:
int i1;
int i2;
if(1 < (i1 = (6 < (i2 = 7) && i2 < 8 ? 2 : 3)) && i1 < 4) {
// ^^^^^^^^^^^^^^^^^^^^^^ inside
// ^^^^^^^^^^^ ^^^^^^^^^^^ outside

关于python - 如何将 python 比较 ast 节点转换为 c?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63069595/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com