/*++ 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 #include #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& m_qlists; smt_renaming& m_renaming; unsigned m_indent; unsigned m_num_var_names; char const* const* m_var_names; ptr_vector 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 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 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 (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(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& 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 const* decls; ptr_vector 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 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 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 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 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 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"; }