3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-07 18:05:21 +00:00
z3/lib/ast_smt_pp.cpp
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

1215 lines
35 KiB
C++

/*++
Copyright (c) 2008 Microsoft Corporation
Module Name:
ast_smt_pp.cpp
Abstract:
Pretty printer of AST formulas as SMT benchmarks.
Author:
Michal Moskal (micmo) 2008-04-09.
Nikolaj Bjorner (nbjorner)
Revision History:
--*/
#include<sstream>
#include<iostream>
#include"ast_smt_pp.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"array_decl_plugin.h"
#include"datatype_decl_plugin.h"
#include"vector.h"
#include"for_each_ast.h"
#include"decl_collector.h"
// ---------------------------------------
// smt_renaming
const static char* m_predef_names[] = {
"=", ">=", "<=", "+", "-", "*", ">", "<", "!=", "or", "and", "implies", "not", "iff", "xor",
"true", "false", "forall", "exists", "let", "flet", NULL
};
symbol smt_renaming::fix_symbol(symbol s, int k) {
std::ostringstream buffer;
char const * data = s.is_numerical() ? "" : s.bare_str();
if (data[0] && !data[1]) {
switch (data[0]) {
case '/': data = "op_div"; break;
case '%': data = "op_mod"; break;
default: break;
}
}
if (k == 0 && *data) {
if (s.is_numerical()) {
return s;
}
if (is_special(data)) {
return s;
}
if (all_is_legal(data)) {
return s;
}
}
if (s.is_numerical()) {
buffer << s << k;
return symbol(buffer.str().c_str());
}
buffer << "|";
if (*data == '|') {
while (*data) {
if (*data == '|') {
if (!data[1]) {
break;
}
buffer << "\\";
}
buffer << *data;
++data;
}
}
else {
while (*data) {
if (*data == '|') {
buffer << "\\";
}
buffer << *data;
++data;
}
}
if (k > 0) {
buffer << k;
}
buffer << "|";
return symbol(buffer.str().c_str());
}
bool smt_renaming::is_legal(char c) {
return c == '.' || c == '_' || c == '\''
|| c == '?' || c == '!' || isalnum(c);
}
bool smt_renaming::is_special(char const* s) {
if (!s) return false;
if (s[0] != '|') return false;
++s;
while (*s) {
if (s[0] == '|') {
return (0 == s[1]);
}
++s;
}
return false;
}
bool smt_renaming::is_numerical(char const* s) {
while (*s) {
if (!isdigit(*s)) {
return false;
}
++s;
}
return true;
}
bool smt_renaming::all_is_legal(char const* s) {
if (!s) return false;
if (is_numerical(s)) return false;
while (*s) {
if (!is_legal(*s)) return false;
++s;
}
return true;
}
smt_renaming::smt_renaming() {
for (const char **p = m_predef_names; *p; ++p) {
symbol s(*p);
m_translate.insert(s, s);
m_rev_translate.insert(s, s);
}
}
symbol smt_renaming::get_symbol(symbol s0) {
symbol s;
if (m_translate.find(s0, s)) {
return s;
}
int k = 0;
do {
s = fix_symbol(s0, k++);
}
while (m_rev_translate.contains(s));
m_translate.insert(s0, s);
m_rev_translate.insert(s, s0);
return s;
}
// ---------------------------------------
// smt_printer
class smt_printer {
std::ostream& m_out;
ast_manager& m_manager;
ptr_vector<quantifier>& m_qlists;
smt_renaming& m_renaming;
unsigned m_indent;
unsigned m_num_var_names;
char const* const* m_var_names;
ptr_vector<expr> m_todo;
ast_mark m_mark;
unsigned m_num_lets;
arith_util m_autil;
bv_util m_bvutil;
family_id m_basic_fid;
family_id m_bv_fid;
family_id m_arith_fid;
family_id m_array_fid;
family_id m_dt_fid;
family_id m_label_fid;
symbol m_logic;
symbol m_AUFLIRA;
bool m_no_lets;
bool m_is_smt2;
bool m_simplify_implies;
expr* m_top;
bool is_bool(sort* s) {
return
m_basic_fid == s->get_family_id() &&
s->get_decl_kind() == BOOL_SORT;
}
bool is_bool(expr* e) {
return is_bool(m_manager.get_sort(e));
}
bool is_proof(sort* s) {
return
m_basic_fid == s->get_family_id() &&
s->get_decl_kind() == PROOF_SORT;
}
bool is_proof(expr* e) {
return is_proof(m_manager.get_sort(e));
}
void pp_id(expr* n) {
if (m_is_smt2) {
m_out << (is_bool(n)?"$x":(is_proof(n)?"@x":"?x")) << n->get_id();
}
else {
m_out << (is_bool(n)?"$x":"?x") << n->get_id();
}
}
void pp_decl(func_decl* d) {
symbol sym = m_renaming.get_symbol(d->get_name());
if (d->get_family_id() == m_dt_fid) {
m_out << sym;
}
else if (m_manager.is_ite(d)) {
if (!m_is_smt2 && is_bool(d->get_range())) {
m_out << "if_then_else";
}
else {
m_out << "ite";
}
}
else if (!m_is_smt2 && m_manager.is_implies(d)) {
m_out << "implies";
}
else if (m_is_smt2 && m_manager.is_iff(d)) {
m_out << "=";
}
else if (m_is_smt2 && m_manager.is_implies(d)) {
m_out << "=>";
}
else if (m_is_smt2 && is_decl_of(d, m_arith_fid, OP_UMINUS)) {
m_out << "-";
}
else {
visit_params(false, sym, d->get_num_parameters(), d->get_parameters());
}
m_out << " ";
}
bool is_sort_param(unsigned num_params, parameter const* params) {
return
num_params == 1 &&
params[0].is_ast() &&
is_sort(params[0].get_ast());
}
void visit_params(bool is_sort_symbol, symbol const& sym, unsigned num_params, parameter const* params) {
if (0 == num_params) {
m_out << sym;
return;
}
if (m_is_smt2) {
if (is_sort_symbol && sym != symbol("BitVec")) {
m_out << "(" << sym << " ";
}
else if (!is_sort_symbol && is_sort_param(num_params, params)) {
m_out << "(as " << sym << " ";
}
else {
m_out << "(_ " << sym << " ";
}
}
else {
m_out << sym << "[";
}
for (unsigned i = 0; i < num_params; ++i) {
parameter const& p = params[i];
if (p.is_ast()) {
if (is_sort(p.get_ast())) {
visit_sort(to_sort(p.get_ast()));
}
else if (is_expr(p.get_ast())) {
pp_expr(to_expr(p.get_ast()));
}
else if (is_func_decl(p.get_ast())) {
pp_decl(to_func_decl(p.get_ast()));
}
else {
m_out << "#" << p.get_ast()->get_id();
}
}
else {
m_out << p;
}
if (i + 1 < num_params) {
if (m_is_smt2) {
m_out << " ";
}
else {
m_out << ": ";
}
}
}
if (m_is_smt2) {
m_out << ")";
}
else {
m_out << "]";
}
}
bool is_auflira() const {
return m_logic == m_AUFLIRA;
}
void visit_sort(sort* s, bool bool2int = false) {
symbol sym;
if (bool2int && is_bool(s)) {
sym = symbol("Int");
} else if (s->is_sort_of(m_bv_fid, BV_SORT)) {
sym = symbol("BitVec");
}
else if (s->is_sort_of(m_arith_fid, REAL_SORT)) {
sym = s->get_name();
}
else if (m_manager.is_bool(s)) {
sym = symbol("Bool");
}
else if (s->is_sort_of(m_arith_fid, INT_SORT)) {
sym = s->get_name();
}
else if (s->is_sort_of(m_array_fid, ARRAY_SORT) && m_is_smt2) {
sym = "Array";
}
else if (s->is_sort_of(m_array_fid, ARRAY_SORT) && !m_is_smt2) {
unsigned num_params = s->get_num_parameters();
SASSERT(num_params >= 2);
if (is_auflira()) {
sort* rng = to_sort(s->get_parameter(1).get_ast());
if (rng->get_family_id() == m_array_fid) {
m_out << "Array2";
}
else {
m_out << "Array1";
}
return;
}
sort* s1 = to_sort(s->get_parameter(0).get_ast());
sort* s2 = to_sort(s->get_parameter(1).get_ast());
if (num_params == 2 &&
s1->is_sort_of(m_bv_fid, BV_SORT) &&
s2->is_sort_of(m_bv_fid, BV_SORT)) {
m_out << "Array";
m_out << "[" << s1->get_parameter(0).get_int();
m_out << ":" << s2->get_parameter(0).get_int() << "]";
return;
}
m_out << "(Array ";
for (unsigned i = 0; i < num_params; ++i) {
visit_sort(to_sort(s->get_parameter(i).get_ast()));
if (i + 1 < num_params) {
m_out << " ";
}
}
m_out << ")";
return;
}
else if (s->is_sort_of(m_dt_fid, DATATYPE_SORT)) {
m_out << m_renaming.get_symbol(s->get_name());
return;
}
else {
sym = m_renaming.get_symbol(s->get_name());
}
visit_params(true, sym, s->get_num_parameters(), s->get_parameters());
}
void display_rational(rational const & r, bool is_int) {
bool d = !is_int;
if (r.is_int()) {
m_out << r << (d ? ".0" : "");
}
else {
m_out << "(/ " << numerator(r) << (d ? ".0" : "") << " " << denominator(r) << (d ? ".0" : "") << ")";
}
}
void pp_arg(expr *arg, app *parent)
{
if (!m_is_smt2 && is_bool(arg) && is_var(arg) && parent->get_family_id() == m_basic_fid) {
m_out << "(not (= ";
pp_marked_expr(arg);
m_out << " 0))";
} else if (!m_is_smt2 && is_bool(arg) && !is_var(arg) &&
parent->get_family_id() != m_basic_fid &&
parent->get_family_id() != m_dt_fid) {
m_out << "(ite ";
pp_marked_expr(arg);
m_out << " 1 0)";
} else {
pp_marked_expr(arg);
}
}
void visit_app(app* n) {
rational val;
bool is_int, pos;
buffer<symbol> names;
unsigned bv_size;
unsigned num_args = n->get_num_args();
func_decl* decl = n->get_decl();
if (m_autil.is_numeral(n, val, is_int)) {
if (val.is_neg()) {
val.neg();
m_out << "(~ ";
display_rational(val, is_int);
m_out << ")";
}
else {
display_rational(val, is_int);
}
}
else if (m_bvutil.is_numeral(n, val, bv_size)) {
if (m_is_smt2) {
m_out << "(_ bv" << val << " " << bv_size << ")";
}
else {
m_out << "bv" << val << "[" << bv_size << "]";
}
}
else if (m_bvutil.is_bit2bool(n)) {
unsigned bit = n->get_decl()->get_parameter(0).get_int();
if (m_is_smt2) {
m_out << "(= ((_ extract " << bit << " " << bit << ") ";
pp_marked_expr(n->get_arg(0));
m_out << ") (_ bv1 1))";
}
else {
m_out << "(= (extract[" << bit << ":" << bit << "] ";
pp_marked_expr(n->get_arg(0));
m_out << ") bv1[1])";
}
}
else if (m_manager.is_label(n, pos, names) && names.size() >= 1) {
if (m_is_smt2) {
m_out << "(! ";
pp_marked_expr(n->get_arg(0));
m_out << (pos?":lblpos":":lblneg") << " " << m_renaming.get_symbol(names[0]) << ")";
}
else {
m_out << "(" << (pos?"lblpos":"lblneg") << " " << m_renaming.get_symbol(names[0]) << " ";
expr* ch = n->get_arg(0);
pp_marked_expr(ch);
m_out << ")";
}
}
else if (m_manager.is_label_lit(n, names) && names.size() >= 1) {
if (m_is_smt2) {
m_out << "(! true :lblpos " << m_renaming.get_symbol(names[0]) << ")";
}
else {
m_out << "(lblpos " << m_renaming.get_symbol(names[0]) << " true )";
}
}
else if (num_args == 0) {
if (decl->private_parameters()) {
m_out << m_renaming.get_symbol(decl->get_name());
}
else {
symbol sym = m_renaming.get_symbol(decl->get_name());
visit_params(false, sym, decl->get_num_parameters(), decl->get_parameters());
}
}
else if (num_args == 1 && n->get_family_id() == m_label_fid) {
expr* ch = n->get_arg(0);
pp_marked_expr(ch);
}
else if (m_simplify_implies && m_manager.is_implies(decl) && m_manager.is_implies(n->get_arg(1))) {
expr *curr = n;
expr *arg;
m_out << "(implies (and";
while (m_manager.is_implies(curr)) {
arg = to_app(curr)->get_arg(0);
m_out << " ";
pp_arg(arg, n);
curr = to_app(curr)->get_arg(1);
}
m_out << ") ";
pp_arg(curr, n);
m_out << ")";
} else if (m_manager.is_distinct(decl)) {
ptr_vector<expr> args(num_args, n->get_args());
unsigned idx = 0;
m_out << "(and";
while (true) {
while (idx < args.size() && !args[idx])
idx++;
if (idx >= args.size()) break;
sort * s = m_manager.get_sort(args[idx]);
unsigned next = idx + 1;
// check if there is only a single one
while (next < args.size() && (!args[next] || m_manager.get_sort(args[next]) != s))
next++;
if (next >= args.size()) {
args[idx] = 0;
// if so, skip it
continue;
}
// otherwise print all of the relevant sort
m_out << " (distinct";
for (unsigned i = idx; i < args.size(); ++i) {
if (args[i] && s == m_manager.get_sort(args[i])) {
m_out << " ";
pp_marked_expr(args[i]);
args[i] = 0;
}
}
m_out << ")";
}
m_out << " true)";
}
else {
m_out << "(";
pp_decl(decl);
for (unsigned i = 0; i < num_args; ++i) {
pp_arg(n->get_arg(i), n);
if (i + 1 < num_args) {
m_out << " ";
}
}
m_out << ")";
}
}
void print_no_lets(expr *e)
{
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, true, m_simplify_implies, m_is_smt2, m_indent, m_num_var_names, m_var_names);
p(e);
}
void print_bound(symbol const& name) {
if (name.is_numerical() || '?' != name.bare_str()[0]) {
m_out << "?";
}
m_out << name;
}
void visit_quantifier(quantifier* q) {
m_qlists.push_back(q);
m_out << "(";
if (q->is_forall()) {
m_out << "forall ";
}
else {
m_out << "exists ";
}
if (m_is_smt2) {
m_out << "(";
}
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
sort* s = q->get_decl_sort(i);
m_out << "(";
print_bound(m_renaming.get_symbol(q->get_decl_name(i)));
m_out << " ";
visit_sort(s, true);
m_out << ") ";
}
if (m_is_smt2) {
m_out << ")";
}
if (m_is_smt2 && q->get_num_patterns() > 0) {
m_out << "(!";
}
{
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, false, m_is_smt2, m_simplify_implies, m_indent, m_num_var_names, m_var_names);
p(q->get_expr());
}
for (unsigned i = 0; i < q->get_num_patterns(); ++i) {
app *pat = reinterpret_cast<app*> (q->get_pattern(i));
if (pat->get_num_args() == 1 && is_app(pat->get_arg(0))) {
app *app = to_app(pat->get_arg(0));
if (app->get_num_args() == 1 && app->get_decl()->get_name().str() == "sk_hack") {
/*
m_out << " :ex_act { ";
print_no_lets(app->get_arg(0));
m_out << "}";
*/
continue;
}
}
m_out << " :pat { ";
for (unsigned j = 0; j < pat->get_num_args(); ++j) {
print_no_lets(pat->get_arg(j));
m_out << " ";
}
m_out << "}";
}
if (m_is_smt2 && q->get_num_patterns() > 0) {
m_out << ")";
}
m_out << ")";
newline();
m_qlists.pop_back();
}
void newline() {
unsigned i = m_indent;
m_out << "\n";
while (i > 0) { m_out << " "; --i; }
}
void visit_var(var* v) {
unsigned idx = v->get_idx();
for (unsigned i = m_qlists.size(); ; --i) {
if (i == 0) {
break;
}
quantifier* q = m_qlists[i-1];
unsigned num_decls = q->get_num_decls();
if (idx < num_decls) {
unsigned offs = num_decls-idx-1;
symbol name = m_renaming.get_symbol(q->get_decl_name(offs));
print_bound(name);
return;
}
idx -= num_decls;
}
if (idx < m_num_var_names) {
m_out << m_var_names[m_num_var_names - idx - 1];
}
else {
m_out << "?" << idx;
}
}
void pp_marked_expr(expr* n) {
if (m_mark.is_marked(n)) {
pp_id(n);
}
else {
pp_expr(n);
}
}
void pp_expr(expr* n) {
switch(n->get_kind()) {
case AST_QUANTIFIER:
visit_quantifier(to_quantifier(n));
break;
case AST_APP:
visit_app(to_app(n));
break;
case AST_VAR:
visit_var(to_var(n));
break;
default:
UNREACHABLE();
}
}
void visit_expr(expr* n) {
if (m_is_smt2) {
m_out << "(let ((";
}
else if (is_bool(n)) {
m_out << "(flet (";
}
else {
m_out << "(let (";
}
pp_id(n);
m_out << " ";
pp_expr(n);
if (m_is_smt2) {
m_out << ")";
}
m_out << ")";
newline();
}
bool is_unit(expr* n) {
if (n->get_ref_count() <= 2 && is_small(n)) {
return true;
}
if (n == m_top) {
return true;
}
switch(n->get_kind()) {
case AST_VAR:
return true;
case AST_APP:
return to_app(n)->get_num_args() == 0;
default:
return false;
}
}
static const unsigned m_line_length = 80;
bool is_small(expr* n) {
unsigned sz = 0;
return is_small(n, sz);
}
bool is_small(expr* n, unsigned& sz) {
if (sz > m_line_length) {
return false;
}
if (m_mark.is_marked(n)) {
sz += 5;
return sz <= m_line_length;
}
switch(n->get_kind()) {
case AST_QUANTIFIER:
return false;
case AST_VAR:
sz += 5;
return sz <= m_line_length;
case AST_APP: {
app* a = to_app(n);
func_decl* d = a->get_decl();
symbol const& s = d->get_name();
if (s.is_numerical()) {
sz += 4;
}
if (s.is_numerical()) {
sz += 7;
}
else {
sz += 3 + static_cast<unsigned>(strlen(s.bare_str()));
}
for (unsigned i = 0; i < a->get_num_args() && sz <= m_line_length; ++i) {
sz += 1;
if (!is_small(a->get_arg(i), sz)) {
return false;
}
}
return sz <= m_line_length;
}
default:
return false;
}
}
bool visit_children(expr* n) {
unsigned todo_size = m_todo.size();
switch(n->get_kind()) {
case AST_QUANTIFIER:
case AST_VAR:
break;
case AST_APP: {
app* a = to_app(n);
for (unsigned i = 0; i < a->get_num_args(); ++i) {
expr* ch = a->get_arg(i);
if (!is_unit(ch) && !m_mark.is_marked(ch)) {
m_todo.push_back(ch);
}
}
break;
}
default:
UNREACHABLE();
break;
}
bool all_visited = todo_size == m_todo.size();
return all_visited;
}
public:
smt_printer(std::ostream& out, ast_manager& m, ptr_vector<quantifier>& ql, smt_renaming& rn,
symbol logic, bool no_lets, bool is_smt2, bool simplify_implies, unsigned indent, unsigned num_var_names = 0, char const* const* var_names = 0) :
m_out(out),
m_manager(m),
m_qlists(ql),
m_renaming(rn),
m_indent(indent),
m_num_var_names(num_var_names),
m_var_names(var_names),
m_num_lets(0),
m_autil(m),
m_bvutil(m),
m_logic(logic),
m_AUFLIRA("AUFLIRA"),
// It's much easier to read those testcases with that.
m_no_lets(no_lets),
m_is_smt2(is_smt2),
m_simplify_implies(simplify_implies)
{
m_basic_fid = m.get_basic_family_id();
m_label_fid = m.get_family_id("label");
m_bv_fid = m.get_family_id("bv");
m_arith_fid = m.get_family_id("arith");
m_array_fid = m.get_family_id("array");
m_dt_fid = m.get_family_id("datatype");
}
void operator()(expr* n) {
m_top = n;
if (!m_no_lets) {
switch(n->get_kind()) {
case AST_APP:
for (unsigned i = 0; i < to_app(n)->get_num_args(); ++i) {
m_todo.push_back(to_app(n)->get_arg(i));
}
break;
// Don't do this for quantifiers -- they need to have the body be
// visited when the m_qlist contains the relevant quantifier.
default:
break;
}
}
while (!m_todo.empty()) {
expr* m = m_todo.back();
if (m_mark.is_marked(m)) {
m_todo.pop_back();
}
else if (is_unit(m)) {
m_todo.pop_back();
}
else if (visit_children(m)) {
m_todo.pop_back();
m_mark.mark(m, true);
visit_expr(m);
++m_num_lets;
}
}
pp_marked_expr(n);
for (unsigned i = 0; i < m_num_lets; ++i) {
m_out << ")";
}
m_mark.reset();
m_num_lets = 0;
m_top = 0;
}
void pp_dt(ast_mark& mark, sort* s) {
SASSERT(s->is_sort_of(m_dt_fid, DATATYPE_SORT));
datatype_util util(m_manager);
ptr_vector<func_decl> const* decls;
ptr_vector<sort> rec_sorts;
rec_sorts.push_back(s);
mark.mark(s, true);
// collect siblings and sorts that have not already been printed.
for (unsigned h = 0; h < rec_sorts.size(); ++h) {
s = rec_sorts[h];
decls = util.get_datatype_constructors(s);
for (unsigned i = 0; i < decls->size(); ++i) {
func_decl* f = (*decls)[i];
for (unsigned j = 0; j < f->get_arity(); ++j) {
sort* s2 = f->get_domain(j);
if (!mark.is_marked(s2)) {
if (s2->get_family_id() == null_family_id) {
pp_sort_decl(mark, s2);
}
else if (!util.is_datatype(s2)) {
// skip
}
else if (util.are_siblings(s, s2)) {
rec_sorts.push_back(s2);
mark.mark(s2, true);
}
else {
pp_sort_decl(mark, s2);
}
}
}
}
}
if (m_is_smt2) {
// TBD: datatypes may be declared parametrically.
// get access to parametric generalization, or print
// monomorphic specialization with a tag that gets reused at use-point.
m_out << "(declare-datatypes () (";
}
else {
m_out << ":datatypes (";
}
for (unsigned si = 0; si < rec_sorts.size(); ++si) {
s = rec_sorts[si];
m_out << "(";
m_out << m_renaming.get_symbol(s->get_name());
m_out << " ";
decls = util.get_datatype_constructors(s);
for (unsigned i = 0; i < decls->size(); ++i) {
func_decl* f = (*decls)[i];
ptr_vector<func_decl> const& accs = *util.get_constructor_accessors(f);
if (m_is_smt2 || accs.size() > 0) {
m_out << "(";
}
m_out << m_renaming.get_symbol(f->get_name());
// if (accs.size() > 0) {
m_out << " ";
// }
for (unsigned j = 0; j < accs.size(); ++j) {
func_decl* a = accs[j];
m_out << "(" << m_renaming.get_symbol(a->get_name()) << " ";
visit_sort(a->get_range());
m_out << ")";
if (j + 1 < accs.size()) m_out << " ";
}
if (m_is_smt2 || accs.size() > 0) {
m_out << ")";
if (i + 1 < decls->size()) {
m_out << " ";
}
}
}
m_out << ")";
if (si + 1 < rec_sorts.size()) {
m_out << " ";
}
}
if (m_is_smt2) {
m_out << ")";
}
m_out << ")";
newline();
}
void pp_sort_decl(ast_mark& mark, sort* s) {
if (mark.is_marked(s)) {
return;
}
if (s->is_sort_of(m_dt_fid, DATATYPE_SORT)) {
pp_dt(mark, s);
}
else {
if (m_is_smt2) {
m_out << "(declare-sort ";
}
else {
m_out << ":extrasorts (";
}
visit_sort(s);
m_out << ")";
newline();
}
mark.mark(s, true);
}
void operator()(func_decl* d) {
if (m_is_smt2) {
m_out << "(declare-fun ";
pp_decl(d);
m_out << "(";
for (unsigned i = 0; i < d->get_arity(); ++i) {
if (i > 0) m_out << " ";
visit_sort(d->get_domain(i), true);
}
m_out << ") ";
visit_sort(d->get_range());
m_out << ")";
newline();
}
else {
m_out << "(";
pp_decl(d);
for (unsigned i = 0; i < d->get_arity(); ++i) {
m_out << " ";
visit_sort(d->get_domain(i), true);
}
m_out << " ";
visit_sort(d->get_range());
m_out << ")";
}
}
void visit_pred(func_decl* d) {
m_out << "(";
pp_decl(d);
for (unsigned i = 0; i < d->get_arity(); ++i) {
m_out << " ";
visit_sort(d->get_domain(i), true);
}
m_out << ")";
}
};
// ---------------------------------------
// ast_smt_pp:
ast_smt_pp::ast_smt_pp(ast_manager& m):
m_manager(m),
m_assumptions(m),
m_assumptions_star(m),
m_benchmark_name(),
m_source_info(),
m_status("unknown"),
m_category(),
m_logic(),
m_dt_fid(m.get_family_id("datatype")),
m_is_declared(&m_is_declared_default),
m_simplify_implies(true)
{}
void ast_smt_pp::display_expr(std::ostream& strm, expr* n) {
ptr_vector<quantifier> ql;
smt_renaming rn;
smt_printer p(strm, m_manager, ql, rn, m_logic, false, false, m_simplify_implies, 0);
p(n);
}
void ast_smt_pp::display_expr_smt2(std::ostream& strm, expr* n, unsigned indent, unsigned num_var_names, char const* const* var_names) {
ptr_vector<quantifier> ql;
smt_renaming rn;
smt_printer p(strm, m_manager, ql, rn, m_logic, false, true, m_simplify_implies, indent, num_var_names, var_names);
p(n);
}
void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
ptr_vector<quantifier> ql;
decl_collector decls(m_manager);
smt_renaming rn;
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
decls.visit(m_assumptions[i].get());
}
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
decls.visit(m_assumptions_star[i].get());
}
decls.visit(n);
if (m_manager.is_proof(n)) {
strm << "(";
}
if (m_benchmark_name != symbol::null) {
strm << "; " << m_benchmark_name << "\n";
}
if (m_source_info != symbol::null && m_source_info != symbol("")) {
strm << "; :source { " << m_source_info << " }\n";
}
if (m_manager.is_bool(n)) {
strm << "(set-info :status " << m_status << ")\n";
}
if (m_category != symbol::null && m_category != symbol("")) {
strm << "; :category { " << m_category << " }\n";
}
if (m_logic != symbol::null && m_logic != symbol("")) {
strm << "(set-logic " << m_logic << ")\n";
}
if (m_attributes.size() > 0) {
strm << "; " << m_attributes.c_str();
}
ast_mark sort_mark;
for (unsigned i = 0; i < decls.get_num_sorts(); ++i) {
sort* s = decls.get_sorts()[i];
if (!(*m_is_declared)(s)) {
smt_printer p(strm, m_manager, ql, rn, m_logic, true, true, m_simplify_implies, 0);
p.pp_sort_decl(sort_mark, s);
}
}
for (unsigned i = 0; i < decls.get_num_decls(); ++i) {
func_decl* d = decls.get_func_decls()[i];
if (!(*m_is_declared)(d)) {
smt_printer p(strm, m_manager, ql, rn, m_logic, true, true, m_simplify_implies, 0);
p(d);
}
}
for (unsigned i = 0; i < decls.get_num_preds(); ++i) {
func_decl* d = decls.get_pred_decls()[i];
if (!(*m_is_declared)(d)) {
smt_printer p(strm, m_manager, ql, rn, m_logic, true, true, m_simplify_implies, 0);
p(d);
}
}
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
strm << "(assert\n";
smt_printer p(strm, m_manager, ql, rn, m_logic, false, true, m_simplify_implies, 0);
p(m_assumptions[i].get());
strm << ")\n";
}
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
strm << "(assert\n";
smt_printer p(strm, m_manager, ql, rn, m_logic, false, true, m_simplify_implies, 0);
p(m_assumptions_star[i].get());
strm << ")\n";
}
smt_printer p(strm, m_manager, ql, rn, m_logic, false, true, m_simplify_implies, 0);
if (m_manager.is_bool(n)) {
strm << "(assert\n";
p(n);
strm << ")\n";
strm << "(check-sat)\n";
}
else if (m_manager.is_proof(n)) {
strm << "(proof\n";
p(n);
strm << "))\n";
}
else {
p(n);
}
}
void ast_smt_pp::display(std::ostream& strm, expr* n) {
ptr_vector<quantifier> ql;
decl_collector decls(m_manager);
smt_renaming rn;
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
decls.visit(m_assumptions[i].get());
}
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
decls.visit(m_assumptions_star[i].get());
}
decls.visit(n);
strm << "(benchmark ";
if (m_benchmark_name != symbol::null) {
strm << m_benchmark_name << "\n";
}
else {
strm << "unnamed\n";
}
if (m_source_info != symbol::null && m_source_info != symbol("")) {
strm << ":source { " << m_source_info << " }\n";
}
strm << ":status " << m_status << "\n";
if (m_category != symbol::null && m_category != symbol("")) {
strm << ":category { " << m_category << " }\n";
}
if (m_logic != symbol::null && m_logic != symbol("")) {
strm << ":logic " << m_logic << "\n";
}
if (m_attributes.size() > 0) {
strm << m_attributes.c_str();
}
ast_mark sort_mark;
for (unsigned i = 0; i < decls.get_num_sorts(); ++i) {
sort* s = decls.get_sorts()[i];
if (!(*m_is_declared)(s)) {
smt_printer p(strm, m_manager, ql, rn, m_logic, true, false, m_simplify_implies, 0);
p.pp_sort_decl(sort_mark, s);
}
}
for (unsigned i = 0; i < decls.get_num_decls(); ++i) {
func_decl* d = decls.get_func_decls()[i];
if (!(*m_is_declared)(d)) {
strm << ":extrafuns (";
smt_printer p(strm, m_manager, ql, rn, m_logic, true, false, m_simplify_implies, 0);
p(d);
strm << ")\n";
}
}
for (unsigned i = 0; i < decls.get_num_preds(); ++i) {
func_decl* d = decls.get_pred_decls()[i];
if (!(*m_is_declared)(d)) {
strm << ":extrapreds (";
smt_printer p(strm, m_manager, ql, rn, m_logic, true, false, m_simplify_implies, 0);
p.visit_pred(d);
strm << ")\n";
}
}
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
expr * e = m_assumptions[i].get();
strm << ":assumption\n";
smt_printer p(strm, m_manager, ql, rn, m_logic, false, false, m_simplify_implies, 0);
p(e);
strm << "\n";
}
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
strm << ":assumption-core\n";
smt_printer p(strm, m_manager, ql, rn, m_logic, false, false, m_simplify_implies, 0);
p(m_assumptions_star[i].get());
strm << "\n";
}
{
strm << ":formula\n";
smt_printer p(strm, m_manager, ql, rn, m_logic, false, false, m_simplify_implies, 0);
p(n);
strm << "\n";
}
strm << ")\n";
}