作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
让我们首先考虑 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/
我是一名优秀的程序员,十分优秀!