【发布时间】:2020-11-14 02:02:22
【问题描述】:
让我们从考虑python3.8.5's grammar开始,在这种情况下,我有兴趣弄清楚如何将python比较转换为c。
为了简单起见,假设我们正在处理一个非常小的 python 平凡子集,我们只想转换平凡的比较表达式:
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 in为了防止在第一个子句为真的情况下对 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 工作示例在这里是理想的,但只是一些允许我改进提供的 sn-p 的通用伪代码也可以)到c?
【问题讨论】:
-
没有标准的 C 表达式可以得到你想要的行为。
-
"所以我想在 c 中你应该做类似 bool v0=a
-
原来转译并不像改变语法那么简单!
-
应该类似于
int i1 = 1; int i2 = 1; int i3 = 3; if(i1 == i2 && i2 < i3)。如果您使编译器更智能,它可能会判断 1 是否被评估两次并不重要,因此它可以将其更改为if(1 == 1 && 1 < 3) -
return f"cmp<{lhs}>({rhs})"的目的是什么?这不是 C 代码的样子。
标签: python c compiler-construction abstract-syntax-tree transpiler