Я сталкиваюсь с некоторыми тонкими деталями, которые я не очень хорошо понимаю. Я разрабатываю инструмент для удаления мертвого кода, предполагая следующий пример:
int main(){
if(1==0){
neverexecutes();
}
}
Я перевожу это на AST ( pycparser ), и когда я сталкиваюсь с условием if 1==0
Я перевожу его на Z3, используя следующий метод:
def evaluate_ast(self, node: c_ast.Node):
"""Translates a c_ast.Node to a z3 predicate."""
typ = type(node)
if typ == c_ast.BinaryOp:
leftnode = self.evaluate_ast(node.left)
rightnode = self.evaluate_ast(node.right)
if node.op == '&&':
return And(leftnode, rightnode)
elif node.op == '||':
return Or(leftnode, rightnode)
elif node.op == '==':
return leftnode == rightnode
elif node.op == '<':
return leftnode < rightnode
elif node.op == '<=':
return leftnode <= rightnode
elif node.op == '>':
return leftnode > rightnode
elif node.op == '>=':
return leftnode >= rightnode
elif node.op == '!=':
return leftnode != rightnode
elif node.op == '/':
return leftnode / rightnode
elif node.op == '+':
return leftnode + rightnode
elif typ == c_ast.Assignment and node.op == '=':
leftnode = self.evaluate_ast(node.lvalue)
rightnode = self.evaluate_ast(node.rvalue)
return leftnode == rightnode
(...)
1==0
переводится в k!0
, и решатель отвечает sat
, что неверно.
Если я изменю обработка равенства C99 выглядит следующим образом:
elif node.op == '==':
return And(leftnode == rightnode)
это работает, я предполагаю, что у меня такая же проблема со всеми бинарными операторами. Что мне здесь не хватает? Система только с False
не должна быть unsat
? Я думаю, что k!0
- это просто перевод какого-то ложного значения в Z3.
Я думаю, что это также графика немного лучше, мой вопрос:
>>> from z3 import *
>>> s = Solver()
>>> s.add(False)
>>> s.check()
unsat
>>> s.reset()
>>> s.add(1==0)
>>> s.check()
unsat
>>> s.reset()
>>> s.add(Bool(1==0))
>>> s.check()
sat
В чем разница между False
, 1==0
и Bool(1==0)
?