3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00
This commit is contained in:
Nikolaj Bjorner 2019-02-28 08:35:26 -08:00
commit b632c08fe0
48 changed files with 1162 additions and 205 deletions

View file

@ -89,7 +89,14 @@ app * arith_decl_plugin::mk_numeral(algebraic_numbers::anum const & val, bool is
parameter p(idx, true);
SASSERT(p.is_external());
func_decl * decl = m_manager->mk_const_decl(m_rootv_sym, m_real_decl, func_decl_info(m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM, 1, &p));
return m_manager->mk_const(decl);
app * r = m_manager->mk_const(decl);
if (log_constant_meaning_prelude(r)) {
am().display_root_smt2(m_manager->trace_stream(), val);
m_manager->trace_stream() << "\n";
}
return r;
}
}
@ -415,6 +422,10 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
r = m_manager->mk_const(m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, 2, p)));
m_manager->inc_ref(r);
m_small_ints.setx(u_val, r, 0);
if (log_constant_meaning_prelude(r)) {
m_manager->trace_stream() << u_val << "\n";
}
}
return r;
}
@ -425,6 +436,10 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
r = m_manager->mk_const(m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, 2, p)));
m_manager->inc_ref(r);
m_small_reals.setx(u_val, r, 0);
if (log_constant_meaning_prelude(r)) {
m_manager->trace_stream() << u_val << "\n";
}
}
return r;
}
@ -436,7 +451,14 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
decl = m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
else
decl = m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
return m_manager->mk_const(decl);
app * r = m_manager->mk_const(decl);
if (log_constant_meaning_prelude(r)) {
val.display_smt2(m_manager->trace_stream());
m_manager->trace_stream() << "\n";
}
return r;
}
func_decl * arith_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const * parameters, unsigned arity) {

View file

@ -141,7 +141,7 @@ func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const*
std::ostringstream buffer;
buffer << "map expects to take as many arguments as the function being mapped, "
<< "it was given " << arity << " but expects " << f->get_arity();
m_manager->raise_exception(buffer.str().c_str());
m_manager->raise_exception(buffer.str());
return nullptr;
}
if (arity == 0) {
@ -158,14 +158,14 @@ func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const*
if (!is_array_sort(domain[i])) {
std::ostringstream buffer;
buffer << "map expects an array sort as argument at position " << i;
m_manager->raise_exception(buffer.str().c_str());
m_manager->raise_exception(buffer.str());
return nullptr;
}
if (get_array_arity(domain[i]) != dom_arity) {
std::ostringstream buffer;
buffer << "map expects all arguments to have the same array domain, "
<< "this is not the case for argument " << i;
m_manager->raise_exception(buffer.str().c_str());
m_manager->raise_exception(buffer.str());
return nullptr;
}
for (unsigned j = 0; j < dom_arity; ++j) {
@ -173,7 +173,7 @@ func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const*
std::ostringstream buffer;
buffer << "map expects all arguments to have the same array domain, "
<< "this is not the case for argument " << i;
m_manager->raise_exception(buffer.str().c_str());
m_manager->raise_exception(buffer.str());
return nullptr;
}
}
@ -181,7 +181,7 @@ func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const*
std::ostringstream buffer;
buffer << "map expects the argument at position " << i
<< " to have the array range the same as the function";
m_manager->raise_exception(buffer.str().c_str());
m_manager->raise_exception(buffer.str());
return nullptr;
}
}
@ -244,7 +244,7 @@ func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
if (num_parameters != arity) {
std::stringstream strm;
strm << "select requires " << num_parameters << " arguments, but was provided with " << arity << " arguments";
m_manager->raise_exception(strm.str().c_str());
m_manager->raise_exception(strm.str());
return nullptr;
}
ptr_buffer<sort> new_domain; // we need this because of coercions.
@ -256,7 +256,7 @@ func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
std::stringstream strm;
strm << "domain sort " << sort_ref(domain[i+1], *m_manager) << " and parameter ";
strm << parameter_pp(parameters[i], *m_manager) << " do not match";
m_manager->raise_exception(strm.str().c_str());
m_manager->raise_exception(strm.str());
UNREACHABLE();
return nullptr;
}
@ -284,7 +284,7 @@ func_decl * array_decl_plugin::mk_store(unsigned arity, sort * const * domain) {
std::ostringstream buffer;
buffer << "store expects the first argument to be an array taking " << num_parameters+1
<< ", instead it was passed " << (arity - 1) << "arguments";
m_manager->raise_exception(buffer.str().c_str());
m_manager->raise_exception(buffer.str());
UNREACHABLE();
return nullptr;
}

View file

@ -28,6 +28,7 @@ Revision History:
#include "ast/ast_smt2_pp.h"
#include "ast/array_decl_plugin.h"
#include "ast/ast_translation.h"
#include "util/z3_version.h"
// -----------------------------------
@ -662,6 +663,23 @@ ast* ast_table::pop_erase() {
//
// -----------------------------------
/**
\brief Checks wether a log is being generated and, if necessary, adds the beginning of an "[attach-meaning]" line
to that log. The theory solver should add some description of the meaning of the term in terms of the theory's
internal reasoning to the end of the line and insert a line break.
\param a the term that should be described.
\return true if a log is being generated, false otherwise.
*/
bool decl_plugin::log_constant_meaning_prelude(app * a) {
if (m_manager->has_trace_stream()) {
m_manager->trace_stream() << "[attach-meaning] #" << a->get_id() << " " << m_manager->get_family_name(m_family_id).str() << " ";
return true;
}
return false;
}
func_decl * decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned num_args, expr * const * args, sort * range) {
ptr_buffer<sort> sorts;
@ -1347,6 +1365,7 @@ ast_manager::ast_manager(proof_gen_mode m, char const * trace_file, bool is_form
if (trace_file) {
m_trace_stream = alloc(std::fstream, trace_file, std::ios_base::out);
m_trace_stream_owner = true;
*m_trace_stream << "[tool-version] Z3 " << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "." << Z3_BUILD_NUMBER << "\n";
}
if (!is_format_manager)
@ -1565,8 +1584,8 @@ void ast_manager::raise_exception(char const * msg) {
throw ast_exception(msg);
}
void ast_manager::raise_exception(std::string const& msg) {
throw ast_exception(msg.c_str());
void ast_manager::raise_exception(std::string && msg) {
throw ast_exception(std::move(msg));
}
@ -2183,7 +2202,14 @@ app * ast_manager::mk_app_core(func_decl * decl, unsigned num_args, expr * const
}
if (m_trace_stream && r == new_node) {
*m_trace_stream << "[mk-app] #" << r->get_id() << " ";
if (is_proof(r)) {
if (decl == mk_func_decl(m_basic_family_id, PR_UNDEF, 0, nullptr, 0, static_cast<expr * const *>(nullptr)))
return r;
*m_trace_stream << "[mk-proof] #";
} else {
*m_trace_stream << "[mk-app] #";
}
*m_trace_stream << r->get_id() << " ";
if (r->get_num_args() == 0 && r->get_decl()->get_name() == "int") {
ast_ll_pp(*m_trace_stream, *this, r);
}
@ -2329,7 +2355,7 @@ var * ast_manager::mk_var(unsigned idx, sort * s) {
var * r = register_node(new_node);
if (m_trace_stream && r == new_node) {
*m_trace_stream << "[mk-var] #" << r->get_id() << "\n";
*m_trace_stream << "[mk-var] #" << r->get_id() << " " << idx << "\n";
}
return r;
}
@ -2458,6 +2484,11 @@ quantifier * ast_manager::mk_quantifier(quantifier_kind k, unsigned num_decls, s
if (m_trace_stream && r == new_node) {
trace_quant(*m_trace_stream, r);
*m_trace_stream << "[attach-var-names] #" << r->get_id();
for (unsigned i = 0; i < num_decls; ++i) {
*m_trace_stream << " (|" << decl_names[num_decls - i - 1].str() << "| ; |" << decl_sorts[num_decls - i -1]->get_name().str() << "|)";
}
*m_trace_stream << "\n";
}
return r;

View file

@ -998,6 +998,17 @@ protected:
virtual void inherit(decl_plugin* other_p, ast_translation& ) { }
/**
\brief Checks wether a log is being generated and, if necessary, adds the beginning of an "[attach-meaning]" line
to that log. The theory solver should add some description of the meaning of the term in terms of the theory's
internal reasoning to the end of the line and insert a line break.
\param a the term that should be described.
\return true if a log is being generated, false otherwise.
*/
bool log_constant_meaning_prelude(app * a);
friend class ast_manager;
public:
@ -1563,7 +1574,7 @@ public:
// Equivalent to throw ast_exception(msg)
Z3_NORETURN void raise_exception(char const * msg);
Z3_NORETURN void raise_exception(std::string const& s);
Z3_NORETURN void raise_exception(std::string && s);
std::ostream& display(std::ostream& out, parameter const& p);

View file

@ -951,7 +951,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
strm << "(set-logic " << m_logic << ")\n";
}
if (!m_attributes.empty()) {
strm << "; " << m_attributes.c_str();
strm << "; " << m_attributes;
}
#if 0

View file

@ -624,7 +624,7 @@ func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
if (m.get_sort(args[i]) != r->get_domain(i)) {
std::ostringstream buffer;
buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " does not match declaration " << mk_pp(r, m);
m.raise_exception(buffer.str().c_str());
m.raise_exception(buffer.str());
return nullptr;
}
}
@ -868,7 +868,21 @@ app * bv_util::mk_numeral(rational const & val, sort* s) const {
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
parameter p[2] = { parameter(val), parameter(static_cast<int>(bv_size)) };
return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, nullptr);
app * r = m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, nullptr);
if (m_plugin->log_constant_meaning_prelude(r)) {
if (bv_size % 4 == 0) {
m_manager.trace_stream() << "#x";
val.display_hex(m_manager.trace_stream(), bv_size);
m_manager.trace_stream() << "\n";
} else {
m_manager.trace_stream() << "#b";
val.display_bin(m_manager.trace_stream(), bv_size);
m_manager.trace_stream() << "\n";
}
}
return r;
}
sort * bv_util::mk_sort(unsigned bv_size) {

View file

@ -126,6 +126,7 @@ inline func_decl * get_div0_decl(ast_manager & m, func_decl * decl) {
}
class bv_decl_plugin : public decl_plugin {
friend class bv_util;
protected:
symbol m_bv_sym;
symbol m_concat_sym;
@ -432,7 +433,53 @@ public:
app * mk_bvsmul_no_udfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_UDFL, n, m); }
app * mk_bvumul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_NO_OVFL, n, m); }
app * mk_bv(unsigned n, expr* const* es) { return m_manager.mk_app(get_fid(), OP_MKBV, n, es); }
private:
void log_bv_from_exprs(app * r, unsigned n, expr* const* es) {
if (m_manager.has_trace_stream()) {
for (unsigned i = 0; i < n; ++i) {
if (!m_manager.is_true(es[i]) && !m_manager.is_false(es[i]))
return;
}
if (m_plugin->log_constant_meaning_prelude(r)) {
if (n % 4 == 0) {
m_manager.trace_stream() << " #x";
m_manager.trace_stream() << std::hex;
uint8_t hexDigit = 0;
unsigned curLength = (4 - n % 4) % 4;
for (unsigned i = 0; i < n; ++i) {
hexDigit <<= 1;
++curLength;
if (m_manager.is_true(es[i])) {
hexDigit |= 1;
}
if (curLength == 4) {
m_manager.trace_stream() << hexDigit;
hexDigit = 0;
}
}
m_manager.trace_stream() << std::dec;
} else {
m_manager.trace_stream() << " #b";
for (unsigned i = 0; i < n; ++i) {
m_manager.trace_stream() << (m_manager.is_true(es[i]) ? 1 : 0);
}
}
m_manager.trace_stream() << ")\n";
}
}
}
public:
app * mk_bv(unsigned n, expr* const* es) {
app * r = m_manager.mk_app(get_fid(), OP_MKBV, n, es);
log_bv_from_exprs(r, n, es);
return r;
}
};

View file

@ -342,7 +342,7 @@ namespace datatype {
std::ostringstream buffer;
buffer << "second argument to field update should be " << mk_ismt2_pp(rng, m)
<< " instead of " << mk_ismt2_pp(domain[1], m);
m.raise_exception(buffer.str().c_str());
m.raise_exception(buffer.str());
return nullptr;
}
range = domain[0];
@ -453,6 +453,48 @@ namespace datatype {
}
}
void plugin::log_axiom_definitions(symbol const& s, sort * new_sort) {
symbol const& family_name = m_manager->get_family_name(get_family_id());
for (constructor const* c : *m_defs[s]) {
func_decl_ref f = c->instantiate(new_sort);
const unsigned num_args = f->get_arity();
if (num_args == 0) continue;
for (unsigned i = 0; i < num_args; ++i) {
m_manager->trace_stream() << "[mk-var] " << family_name << "#" << m_id_counter << " " << i << "\n";
++m_id_counter;
}
const unsigned constructor_id = m_id_counter;
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << constructor_id << " " << f->get_name();
for (unsigned i = 0; i < num_args; ++i) {
m_manager->trace_stream() << " " << family_name << "#" << constructor_id - num_args + i;
}
m_manager->trace_stream() << "\n";
++m_id_counter;
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " pattern " << family_name << "#" << constructor_id << "\n";
++m_id_counter;
m_axiom_bases.insert(f->get_name(), constructor_id + 4);
std::ostringstream var_sorts;
for (accessor const* a : *c) {
var_sorts << " (;" << a->range()->get_name() << ")";
}
std::string var_description = var_sorts.str();
unsigned i = 0;
for (accessor const* a : *c) {
func_decl_ref acc = a->instantiate(new_sort);
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " " << acc->get_name() << " " << family_name << "#" << constructor_id << "\n";
++m_id_counter;
m_manager->trace_stream() << "[mk-app] " << family_name << "#" << m_id_counter << " = " << family_name << "#" << constructor_id - num_args + i
<< " " << family_name << "#" << m_id_counter - 1 << "\n";
++m_id_counter;
m_manager->trace_stream() << "[mk-quant] " << family_name << "#" << m_id_counter << " constructor_accessor_axiom " << family_name << "#" << constructor_id + 1
<< " " << family_name << "#" << m_id_counter - 1 << "\n";
m_manager->trace_stream() << "[attach-var-names] " << family_name << "#" << m_id_counter << var_description << "\n";
++m_id_counter;
++i;
}
}
}
bool plugin::mk_datatypes(unsigned num_datatypes, def * const * datatypes, unsigned num_params, sort* const* sort_params, sort_ref_vector & new_sorts) {
begin_def_block();
for (unsigned i = 0; i < num_datatypes; ++i) {
@ -470,6 +512,9 @@ namespace datatype {
sort_ref_vector ps(*m_manager);
for (symbol const& s : m_def_block) {
new_sorts.push_back(m_defs[s]->instantiate(ps));
if (m_manager->has_trace_stream()) {
log_axiom_definitions(s, new_sorts.back());
}
}
return true;
}

View file

@ -206,13 +206,17 @@ namespace datatype {
class plugin : public decl_plugin {
mutable scoped_ptr<util> m_util;
map<symbol, def*, symbol_hash_proc, symbol_eq_proc> m_defs;
map<symbol, unsigned, symbol_hash_proc, symbol_eq_proc> m_axiom_bases;
unsigned m_id_counter;
svector<symbol> m_def_block;
unsigned m_class_id;
void inherit(decl_plugin* other_p, ast_translation& tr) override;
void log_axiom_definitions(symbol const& s, sort * new_sort);
public:
plugin(): m_class_id(0) {}
plugin(): m_id_counter(0), m_class_id(0) {}
~plugin() override;
void finalize() override;
@ -247,6 +251,7 @@ namespace datatype {
def const& get_def(sort* s) const { return *(m_defs[datatype_name(s)]); }
def& get_def(symbol const& s) { return *(m_defs[s]); }
bool is_declared(sort* s) const { return m_defs.contains(datatype_name(s)); }
unsigned get_axiom_base_id(symbol const& s) { return m_axiom_bases[s]; }
util & u() const;
private:

View file

@ -54,7 +54,7 @@ namespace datalog {
}
std::ostringstream buffer;
buffer << msg << ", value is not within bound " << low << " <= " << val << " <= " << up;
m_manager->raise_exception(buffer.str().c_str());
m_manager->raise_exception(buffer.str());
return false;
}
@ -676,7 +676,7 @@ namespace datalog {
}
std::stringstream strm;
strm << "sort '" << mk_pp(s, m) << "' is not recognized as a sort that contains numeric values.\nUse Bool, BitVec, Int, Real, or a Finite domain sort";
m.raise_exception(strm.str().c_str());
m.raise_exception(strm.str());
return nullptr;
}

View file

@ -92,7 +92,14 @@ func_decl * fpa_decl_plugin::mk_numeral_decl(mpf const & v) {
}
app * fpa_decl_plugin::mk_numeral(mpf const & v) {
return m_manager->mk_const(mk_numeral_decl(v));
app * r = m_manager->mk_const(mk_numeral_decl(v));
if (log_constant_meaning_prelude(r)) {
m_fm.display_smt2(m_manager->trace_stream(), v, false);
m_manager->trace_stream() << "\n";
}
return r;
}
bool fpa_decl_plugin::is_numeral(expr * n, mpf & val) {

View file

@ -86,7 +86,7 @@ struct enum2bv_rewriter::imp {
void throw_non_fd(expr* e) {
std::stringstream strm;
strm << "unable to handle nested data-type expression " << mk_pp(e, m);
throw rewriter_exception(strm.str().c_str());
throw rewriter_exception(strm.str());
}
void check_for_fd(unsigned n, expr* const* args) {

View file

@ -46,7 +46,7 @@ inline br_status unsigned2br_status(unsigned u) {
class rewriter_exception : public default_exception {
public:
rewriter_exception(char const * msg):default_exception(msg) {}
rewriter_exception(std::string && msg) : default_exception(std::move(msg)) {}
};
#endif

View file

@ -562,6 +562,29 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
result_pr = nullptr;
br_status st = reduce_app_core(f, num, args, result);
if (st != BR_FAILED && m().has_trace_stream()) {
family_id fid = f->get_family_id();
if (fid == m_b_rw.get_fid()) {
decl_kind k = f->get_decl_kind();
if (k == OP_EQ) {
SASSERT(num == 2);
fid = m().get_sort(args[0])->get_family_id();
}
else if (k == OP_ITE) {
SASSERT(num == 3);
fid = m().get_sort(args[1])->get_family_id();
}
}
app_ref tmp(m());
tmp = m().mk_app(f, num, args);
m().trace_stream() << "[inst-discovered] theory-solving " << static_cast<void *>(nullptr) << " " << m().get_family_name(fid) << "# ; #" << tmp->get_id() << "\n";
tmp = m().mk_eq(tmp, result);
m().trace_stream() << "[instance] " << static_cast<void *>(nullptr) << " #" << tmp->get_id() << "\n";
m().trace_stream() << "[attach-enode] #" << tmp->get_id() << " 0\n";
m().trace_stream() << "[end-of-instance]\n";
}
if (st != BR_DONE && st != BR_FAILED) {
CTRACE("th_rewriter_step", st != BR_FAILED,
tout << f->get_name() << "\n";

View file

@ -400,7 +400,7 @@ void seq_decl_plugin::match_right_assoc(psig& sig, unsigned dsz, sort *const* do
std::ostringstream strm;
strm << "Unexpected number of arguments to '" << sig.m_name << "' ";
strm << "at least one argument expected " << dsz << " given";
m.raise_exception(strm.str().c_str());
m.raise_exception(strm.str());
}
bool is_match = true;
for (unsigned i = 0; is_match && i < dsz; ++i) {
@ -420,7 +420,7 @@ void seq_decl_plugin::match_right_assoc(psig& sig, unsigned dsz, sort *const* do
if (range) {
strm << " and range: " << mk_pp(range, m);
}
m.raise_exception(strm.str().c_str());
m.raise_exception(strm.str());
}
range_out = apply_binding(binding, sig.m_range);
SASSERT(range_out);
@ -434,7 +434,7 @@ void seq_decl_plugin::match(psig& sig, unsigned dsz, sort *const* dom, sort* ran
std::ostringstream strm;
strm << "Unexpected number of arguments to '" << sig.m_name << "' ";
strm << sig.m_dom.size() << " arguments expected " << dsz << " given";
m.raise_exception(strm.str().c_str());
m.raise_exception(strm.str());
}
bool is_match = true;
for (unsigned i = 0; is_match && i < dsz; ++i) {
@ -459,13 +459,13 @@ void seq_decl_plugin::match(psig& sig, unsigned dsz, sort *const* dom, sort* ran
strm << mk_pp(sig.m_dom[i].get(), m) << " ";
}
m.raise_exception(strm.str().c_str());
m.raise_exception(strm.str());
}
if (!range && dsz == 0) {
std::ostringstream strm;
strm << "Sort of polymorphic function '" << sig.m_name << "' ";
strm << "is ambiguous. Function takes no arguments and sort of range has not been constrained";
m.raise_exception(strm.str().c_str());
m.raise_exception(strm.str());
}
range_out = apply_binding(m_binding, sig.m_range);
SASSERT(range_out);