z3-z3-4.13.0.src.cmd_context.pdecl.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
pdecl.cpp
Abstract:
Parametric declarations for SMT-LIB 2.0 + inductive data-types.
Author:
Leonardo de Moura (leonardo) 2011-03-02.
Revision History:
--*/
#include "cmd_context/pdecl.h"
#include "ast/datatype_decl_plugin.h"
#include "ast/ast_pp.h"
#include
using namespace format_ns;
class psort_inst_cache {
unsigned m_num_params;
sort * m_const;
obj_map m_map; // if m_num_params == 1 value is a sort, otherwise it is a reference to another inst_cache
public:
psort_inst_cache(unsigned num_params):m_num_params(num_params), m_const(nullptr) {
}
~psort_inst_cache() { SASSERT(m_map.empty()); SASSERT(m_const == 0); }
void finalize(pdecl_manager & m) {
if (m_num_params == 0) {
SASSERT(m_map.empty());
if (m_const)
m.m().dec_ref(m_const);
m_const = nullptr;
}
else {
SASSERT(m_const == 0);
for (auto kv : m_map) {
m.m().dec_ref(kv.m_key);
if (m_num_params == 1) {
m.m().dec_ref(static_cast(kv.m_value));
}
else {
psort_inst_cache * child = static_cast(kv.m_value);
child->finalize(m);
child->~psort_inst_cache();
m.a().deallocate(sizeof(psort_inst_cache), child);
}
}
m_map.reset();
}
}
void insert(pdecl_manager & m, sort * const * s, sort * r) {
if (m_num_params == 0) {
SASSERT(m_const == 0);
m.m().inc_ref(r);
m_const = r;
return;
}
psort_inst_cache * curr = this;
while (true) {
if (curr->m_num_params == 1) {
SASSERT(!curr->m_map.contains(*s));
curr->m_map.insert(*s, r);
m.m().inc_ref(*s);
m.m().inc_ref(r);
return;
}
void * next = nullptr;
if (!curr->m_map.find(*s, next)) {
next = new (m.a().allocate(sizeof(psort_inst_cache))) psort_inst_cache(curr->m_num_params-1);
curr->m_map.insert(*s, next);
m.m().inc_ref(*s);
}
SASSERT(next != 0);
SASSERT(curr->m_num_params == static_cast(next)->m_num_params + 1);
s++;
curr = static_cast(next);
}
}
sort * find(sort * const * s) const {
if (m_num_params == 0)
return m_const;
psort_inst_cache const * curr = this;
while (true) {
if (curr->m_num_params == 1) {
void * r = nullptr;
curr->m_map.find(*s, r);
return static_cast(r);
}
else {
void * next = nullptr;
curr->m_map.find(*s, next);
if (next == nullptr)
return nullptr;
s++;
curr = static_cast(next);
}
}
}
bool empty() const { return m_num_params == 0 ? m_const == nullptr : m_map.empty(); }
};
void psort::cache(pdecl_manager & m, sort * const * s, sort * r) {
if (!m_inst_cache)
m_inst_cache = m.mk_inst_cache(m_num_params);
m_inst_cache->insert(m, s, r);
}
sort * psort::find(sort * const * s) const {
if (!m_inst_cache)
return nullptr;
return m_inst_cache->find(s);
}
void psort::finalize(pdecl_manager & m) {
reset_cache(m);
}
void psort::reset_cache(pdecl_manager& m) {
m.del_inst_cache(m_inst_cache);
m_inst_cache = nullptr;
}
/**
\brief wrapper for sorts.
*/
class psort_sort : public psort {
friend class pdecl_manager;
sort * m_sort;
psort_sort(unsigned id, pdecl_manager & m, sort * s):psort(id, 0), m_sort(s) { m.m().inc_ref(m_sort); }
void finalize(pdecl_manager & m) override {
m.m().dec_ref(m_sort);
psort::finalize(m);
}
bool check_num_params(pdecl * other) const override { return true; }
size_t obj_size() const override { return sizeof(psort_sort); }
sort * get_sort() const { return m_sort; }
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override { return m_sort; }
public:
bool is_sort_wrapper() const override { return true; }
char const * hcons_kind() const override { return "psort_sort"; }
unsigned hcons_hash() const override { return m_sort->get_id(); }
bool hcons_eq(psort const * other) const override {
if (other->hcons_kind() != hcons_kind())
return false;
return m_sort == static_cast(other)->m_sort;
}
std::ostream& display(std::ostream & out) const override {
return out << m_sort->get_name();
}
};
class psort_var : public psort {
friend class pdecl_manager;
unsigned m_idx;
psort_var(unsigned id, unsigned num_params, unsigned idx):psort(id, num_params), m_idx(idx) { SASSERT(idx < num_params); }
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override {
if (n <= m_idx) throw default_exception("type parameter was not declared");
return s[m_idx];
}
size_t obj_size() const override { return sizeof(psort_var); }
public:
char const * hcons_kind() const override { return "psort_var"; }
unsigned hcons_hash() const override { return hash_u_u(m_num_params, m_idx); }
bool hcons_eq(psort const * other) const override {
return
other->hcons_kind() == hcons_kind() &&
get_num_params() == other->get_num_params() &&
m_idx == static_cast(other)->m_idx;
}
std::ostream& display(std::ostream & out) const override {
return out << "s_" << m_idx;
}
unsigned idx() const { return m_idx; }
};
class psort_app : public psort {
friend class pdecl_manager;
psort_decl * m_decl;
ptr_vector m_args;
psort_app(unsigned id, unsigned num_params, pdecl_manager & m, psort_decl * d, unsigned num_args, psort * const * args):
psort(id, num_params),
m_decl(d),
m_args(num_args, args) {
m.inc_ref(d);
m.inc_ref(num_args, args);
SASSERT(num_args == m_decl->get_num_params() || m_decl->has_var_params());
DEBUG_CODE(if (num_args == num_params) { for (unsigned i = 0; i < num_params; i++) args[i]->check_num_params(this); });
}
void finalize(pdecl_manager & m) override {
m.lazy_dec_ref(m_decl);
m.lazy_dec_ref(m_args.size(), m_args.data());
psort::finalize(m);
}
size_t obj_size() const override { return sizeof(psort_app); }
struct khasher {
unsigned operator()(psort_app const * d) const { return d->m_decl->hash(); }
};
struct chasher {
unsigned operator()(psort_app const * d, unsigned idx) const { return d->m_args[idx]->hash(); }
};
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override {
sort * r = find(s);
if (r)
return r;
sort_ref_buffer args_i(m.m());
unsigned sz = m_args.size();
for (unsigned i = 0; i < sz; ++i) {
sort * a = m_args[i]->instantiate(m, n, s);
args_i.push_back(a);
}
r = m_decl->instantiate(m, args_i.size(), args_i.data());
cache(m, s, r);
return r;
}
public:
char const * hcons_kind() const override { return "psort_app"; }
unsigned hcons_hash() const override {
return get_composite_hash(const_cast(this), m_args.size());
}
bool hcons_eq(psort const * other) const override {
if (other->hcons_kind() != hcons_kind())
return false;
if (get_num_params() != other->get_num_params())
return false;
psort_app const * _other = static_cast(other);
if (m_decl != _other->m_decl)
return false;
SASSERT(m_args.size() == _other->m_args.size());
unsigned sz = m_args.size();
for (unsigned i = 0; i < sz; i++) {
if (m_args[i] != _other->m_args[i])
return false;
}
return true;
}
std::ostream& display(std::ostream & out) const override {
if (m_args.empty()) {
out << m_decl->get_name();
}
else {
out << "(" << m_decl->get_name();
unsigned sz = m_args.size();
for (unsigned i = 0; i < sz; i++) {
out << " ";
m_args[i]->display(out);
}
out << ")";
}
return out;
}
};
psort_decl::psort_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n):
pdecl(id, num_params),
m_name(n),
m_psort_kind(PSORT_BASE),
m_inst_cache(nullptr) {
}
void psort_decl::finalize(pdecl_manager & m) {
reset_cache(m);
}
void psort_decl::reset_cache(pdecl_manager& m) {
m.del_inst_cache(m_inst_cache);
m_inst_cache = nullptr;
}
void psort_decl::cache(pdecl_manager & m, sort * const * s, sort * r) {
if (!m_inst_cache)
m_inst_cache = m.mk_inst_cache(m_num_params);
m_inst_cache->insert(m, s, r);
}
sort * psort_decl::find(sort * const * s) {
if (!m_inst_cache)
return nullptr;
return m_inst_cache->find(s);
}
psort_user_decl::psort_user_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, psort * p) :
psort_decl(id, num_params, m, n),
m_def(p) {
m_psort_kind = PSORT_USER;
m.inc_ref(p);
// SASSERT(p == 0 || num_params == p->get_num_params());
}
void psort_user_decl::finalize(pdecl_manager & m) {
m.dec_ref(m_def);
m_def = nullptr;
psort_decl::finalize(m);
}
sort * psort_user_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) {
SASSERT(n == m_num_params);
sort * r = find(s);
if (r)
return r;
if (m_def == nullptr) {
buffer ps;
for (unsigned i = 0; i < n; i++)
ps.push_back(parameter(s[i]));
r = m.m().mk_uninterpreted_sort(m_name, ps.size(), ps.data());
}
else {
r = m_def->instantiate(m, n, s);
}
cache(m, s, r);
m.save_info(r, this, n, s);
return r;
}
void display_sort_args(std::ostream & out, unsigned num_params) {
if (num_params > 0)
out << " (";
for (unsigned i = 0; i < num_params; i++) {
if (i > 0) out << " ";
out << "s_" << i;
}
if (num_params > 0)
out << ") ";
}
std::ostream& psort_user_decl::display(std::ostream & out) const {
out << "(declare-sort " << m_name;
display_sort_args(out, m_num_params);
if (m_def)
m_def->display(out);
return out << ")";
}
// -------------------
// psort_type_var_decl
psort_type_var_decl::psort_type_var_decl(unsigned id, pdecl_manager & m, symbol const & n):
psort_decl(id, 0, m, n) {
m_psort_kind = PSORT_TV;
}
void psort_type_var_decl::finalize(pdecl_manager & m) {
psort_decl::finalize(m);
}
sort * psort_type_var_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) {
return m.m().mk_type_var(m_name);
}
std::ostream& psort_type_var_decl::display(std::ostream & out) const {
return out << "(declare-type-var " << m_name << ")";
}
// -------------------
// psort_dt_decl
psort_dt_decl::psort_dt_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n) :
psort_decl(id, num_params, m, n) {
m_psort_kind = PSORT_DT;
}
sort * psort_dt_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) {
SASSERT(n == m_num_params);
return m.instantiate_datatype(this, m_name, n, s);
}
std::ostream& psort_dt_decl::display(std::ostream & out) const {
return out << "(datatype-sort " << m_name << ")";
}
// -------------------
// psort_builtin_decl
psort_builtin_decl::psort_builtin_decl(unsigned id, pdecl_manager & m, symbol const & n, family_id fid, decl_kind k):
psort_decl(id, PSORT_DECL_VAR_PARAMS, m, n),
m_fid(fid),
m_kind(k) {
m_psort_kind = PSORT_BUILTIN;
}
sort * psort_builtin_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) {
if (n == 0) {
sort * r = m.m().mk_sort(m_fid, m_kind);
m.save_info(r, this, 0, s);
return r;
}
else {
buffer params;
for (unsigned i = 0; i < n; i++)
params.push_back(parameter(s[i]));
sort * r = m.m().mk_sort(m_fid, m_kind, n, params.data());
m.save_info(r, this, n, s);
return r;
}
}
sort * psort_builtin_decl::instantiate(pdecl_manager & m, unsigned n, unsigned const * s) {
if (n == 0) {
sort * r = m.m().mk_sort(m_fid, m_kind);
m.save_info(r, this, 0, s);
return r;
}
else {
buffer params;
for (unsigned i = 0; i < n; i++)
params.push_back(parameter(s[i]));
sort * r = m.m().mk_sort(m_fid, m_kind, n, params.data());
m.save_info(r, this, n, s);
return r;
}
}
std::ostream& psort_builtin_decl::display(std::ostream & out) const {
return out << "(declare-builtin-sort " << m_name << ")";
}
void ptype::display(std::ostream & out, pdatatype_decl const * const * dts) const {
switch (kind()) {
case ptype_kind::PTR_PSORT: get_psort()->display(out); break;
case ptype_kind::PTR_REC_REF: out << dts[get_idx()]->get_name(); break;
case ptype_kind::PTR_MISSING_REF: out << get_missing_ref(); break;
}
}
paccessor_decl::paccessor_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, ptype const & r):
pdecl(id, num_params),
m_name(n),
m_type(r) {
if (m_type.kind() == ptype_kind::PTR_PSORT) {
m.inc_ref(r.get_psort());
}
}
void paccessor_decl::finalize(pdecl_manager & m) {
if (m_type.kind() == ptype_kind::PTR_PSORT) {
m.lazy_dec_ref(m_type.get_psort());
}
}
bool paccessor_decl::has_missing_refs(symbol & missing) const {
if (m_type.kind() == ptype_kind::PTR_MISSING_REF) {
missing = m_type.get_missing_ref();
return true;
}
return false;
}
bool paccessor_decl::fix_missing_refs(dictionary const & symbol2idx, symbol & missing) {
TRACE("fix_missing_refs", tout << "m_type.kind(): " << (int)m_type.kind() << "\n";
if (m_type.kind() == ptype_kind::PTR_MISSING_REF) tout << m_type.get_missing_ref() << "\n";);
if (m_type.kind() != ptype_kind::PTR_MISSING_REF)
return true;
int idx;
if (symbol2idx.find(m_type.get_missing_ref(), idx)) {
m_type = ptype(idx);
SASSERT(m_type.kind() == ptype_kind::PTR_REC_REF);
return true;
}
missing = m_type.get_missing_ref();
return false;
}
accessor_decl * paccessor_decl::instantiate_decl(pdecl_manager & m, unsigned n, sort * const * s) {
switch (m_type.kind()) {
case ptype_kind::PTR_REC_REF: return mk_accessor_decl(m.m(), m_name, type_ref(m_type.get_idx()));
case ptype_kind::PTR_PSORT: return mk_accessor_decl(m.m(), m_name, type_ref(m_type.get_psort()->instantiate(m, n, s)));
default:
// missing refs must have been eliminated.
UNREACHABLE();
return nullptr;
}
}
void paccessor_decl::display(std::ostream & out, pdatatype_decl const * const * dts) const {
out << "(" << m_name << " ";
m_type.display(out, dts);
out << ")";
}
pconstructor_decl::pconstructor_decl(unsigned id, unsigned num_params, pdecl_manager & m,
symbol const & n, symbol const & r, unsigned num_accessors, paccessor_decl * const * accessors):
pdecl(id, num_params),
m_name(n),
m_recogniser_name(r),
m_accessors(num_accessors, accessors) {
m.inc_ref(num_accessors, accessors);
TRACE("pconstructor_decl", tout << "name: " << n << ", recognizer: " << r << "\n";);
}
void pconstructor_decl::finalize(pdecl_manager & m) {
m.lazy_dec_ref(m_accessors.size(), m_accessors.data());
}
bool pconstructor_decl::has_missing_refs(symbol & missing) const {
for (paccessor_decl* a : m_accessors)
if (a->has_missing_refs(missing))
return true;
return false;
}
bool pconstructor_decl::fix_missing_refs(dictionary const & symbol2idx, symbol & missing) {
for (paccessor_decl* a : m_accessors)
if (!a->fix_missing_refs(symbol2idx, missing))
return false;
return true;
}
constructor_decl * pconstructor_decl::instantiate_decl(pdecl_manager & m, unsigned n, sort * const * s) {
ptr_buffer as;
for (paccessor_decl* a : m_accessors)
as.push_back(a->instantiate_decl(m, n, s));
return mk_constructor_decl(m_name, m_recogniser_name, as.size(), as.data());
}
void pconstructor_decl::display(std::ostream & out, pdatatype_decl const * const * dts) const {
out << "(" << m_name;
for (paccessor_decl* a : m_accessors) {
out << " ";
a->display(out, dts);
}
out << ")";
}
pdatatype_decl::pdatatype_decl(unsigned id, unsigned num_params, pdecl_manager & m,
symbol const & n, unsigned num_constructors, pconstructor_decl * const * constructors):
psort_decl(id, num_params, m, n),
m_constructors(num_constructors, constructors),
m_parent(nullptr) {
m.inc_ref(num_constructors, constructors);
}
void pdatatype_decl::finalize(pdecl_manager & m) {
m.lazy_dec_ref(m_constructors.size(), m_constructors.data());
psort_decl::finalize(m);
}
bool pdatatype_decl::has_missing_refs(symbol & missing) const {
for (auto c : m_constructors)
if (c->has_missing_refs(missing))
return true;
return false;
}
bool pdatatype_decl::has_duplicate_accessors(symbol & duplicated) const {
hashtable names;
for (auto c : m_constructors) {
for (auto a : c->m_accessors) {
symbol const& name = a->get_name();
if (names.contains(name)) {
duplicated = name;
return true;
}
names.insert(name);
}
}
return false;
}
bool pdatatype_decl::fix_missing_refs(dictionary const & symbol2idx, symbol & missing) {
for (auto c : m_constructors)
if (!c->fix_missing_refs(symbol2idx, missing))
return false;
return true;
}
datatype_decl * pdatatype_decl::instantiate_decl(pdecl_manager & m, unsigned n, sort * const * s) {
ptr_buffer cs;
for (auto c : m_constructors)
cs.push_back(c->instantiate_decl(m, n, s));
datatype_util util(m.m());
return mk_datatype_decl(util, m_name, m_num_params, s, cs.size(), cs.data());
}
struct datatype_decl_buffer {
ptr_buffer m_buffer;
~datatype_decl_buffer() { del_datatype_decls(m_buffer.size(), m_buffer.data()); }
};
sort * pdatatype_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * s) {
sort * r = m.instantiate_datatype(this, m_name, n, s);
datatype_util util(m.m());
if (r && n > 0 && util.is_declared(r)) {
ast_mark mark;
datatype::def const& d = util.get_def(r);
mark.mark(r, true);
sort_ref_vector params(m.m(), n, s);
for (datatype::constructor* c : d) {
for (datatype::accessor* a : *c) {
sort* rng = a->range();
if (util.is_datatype(rng) && !mark.is_marked(rng) && m_parent) {
mark.mark(rng, true);
// TBD: search over more than just parents
for (pdatatype_decl* p : *m_parent) {
if (p->get_name() == rng->get_name()) {
ptr_vector ps;
func_decl_ref acc = a->instantiate(params);
for (unsigned j = 0; j < util.get_datatype_num_parameter_sorts(rng); ++j) {
ps.push_back(util.get_datatype_parameter_sort(acc->get_range(), j));
}
m.instantiate_datatype(p, p->get_name(), ps.size(), ps.data());
break;
}
}
}
}
}
}
return r;
}
std::ostream& pdatatype_decl::display(std::ostream & out) const {
out << "(declare-datatype " << m_name;
display_sort_args(out, m_num_params);
bool first = true;
for (auto c : m_constructors) {
if (!first)
out << " ";
if (m_parent) {
c->display(out, m_parent->children());
}
else {
pdatatype_decl const * dts[1] = { this };
c->display(out, dts);
}
first = false;
}
return out << ")";
}
bool pdatatype_decl::commit(pdecl_manager& m) {
TRACE("datatype", tout << m_name << "\n";);
sort_ref_vector ps(m.m());
for (unsigned i = 0; i < m_num_params; ++i) {
ps.push_back(m.m().mk_uninterpreted_sort(symbol(i), 0, nullptr));
}
datatype_decl_buffer dts;
dts.m_buffer.push_back(instantiate_decl(m, ps.size(), ps.data()));
datatype_decl * d_ptr = dts.m_buffer[0];
sort_ref_vector sorts(m.m());
bool is_ok = m.get_dt_plugin()->mk_datatypes(1, &d_ptr, m_num_params, ps.data(), sorts);
m.notify_mk_datatype(m_name);
if (is_ok && m_num_params == 0)
m.notify_new_dt(sorts.get(0), this);
return is_ok;
}
pdatatypes_decl::pdatatypes_decl(unsigned id, unsigned num_params, pdecl_manager & m,
unsigned num_datatypes, pdatatype_decl * const * dts):
pdecl(id, num_params),
m_datatypes(num_datatypes, dts) {
m.inc_ref(num_datatypes, dts);
for (auto d : m_datatypes) {
SASSERT(d->m_parent == 0);
d->m_parent = this;
}
}
void pdatatypes_decl::finalize(pdecl_manager & m) {
m.lazy_dec_ref(m_datatypes.size(), m_datatypes.data());
}
bool pdatatypes_decl::fix_missing_refs(symbol & missing) {
TRACE("fix_missing_refs", tout << "pdatatypes_decl::fix_missing_refs\n";);
dictionary symbol2idx;
int idx = 0;
for (pdatatype_decl* d : m_datatypes)
symbol2idx.insert(d->get_name(), idx++);
for (pdatatype_decl* d : m_datatypes)
if (!d->fix_missing_refs(symbol2idx, missing))
return false;
return true;
}
sort* pdecl_manager::instantiate_datatype(psort_decl* p, symbol const& name, unsigned n, sort * const* s) {
TRACE("datatype", tout << name << " "; for (unsigned i = 0; i < n; ++i) tout << s[i]->get_name() << " "; tout << "\n";);
pdecl_manager& m = *this;
sort * r = p->find(s);
if (r) {
notify_datatype(r, p, n, s);
return r;
}
buffer ps;
ps.push_back(parameter(name));
for (unsigned i = 0; i < n; i++)
ps.push_back(parameter(s[i]));
datatype_util util(m.m());
r = m.m().mk_sort(util.get_family_id(), DATATYPE_SORT, ps.size(), ps.data());
p->cache(m, s, r);
m.save_info(r, p, n, s);
notify_datatype(r, p, n, s);
return r;
}
void pdecl_manager::notify_datatype(sort *r, psort_decl* p, unsigned n, sort* const* s) {
if (m_notified.contains(r) || n == 0)
return;
pdecl_manager& m = *this;
datatype_util util(m.m());
if (util.is_declared(r)) {
bool has_typevar = false;
// crude check ..
for (unsigned i = 0; !has_typevar && i < n; ++i) {
has_typevar = s[i]->get_name().is_numerical();
}
if (!has_typevar) {
m.notify_new_dt(r, p);
}
m_notified.insert(r);
m_notified_trail.push_back(r);
}
}
void pdecl_manager::push() {
m_notified_lim.push_back(m_notified_trail.size());
m_datatypes_lim.push_back(m_datatypes_trail.size());
}
void pdecl_manager::pop(unsigned n) {
SASSERT(n > 0);
unsigned new_sz = m_notified_lim[m_notified_lim.size() - n];
for (unsigned i = m_notified_trail.size(); i-- > new_sz; ) {
m_notified.erase(m_notified_trail[i]);
}
m_notified_trail.shrink(new_sz);
m_notified_lim.shrink(m_notified_lim.size() - n);
new_sz = m_datatypes_lim[m_datatypes_lim.size() - n];
if (new_sz != m_datatypes_trail.size()) {
datatype_util util(m());
for (unsigned i = m_datatypes_trail.size(); i-- > new_sz; )
util.plugin().remove(m_datatypes_trail[i]);
}
m_datatypes_trail.shrink(new_sz);
m_datatypes_lim.shrink(m_datatypes_lim.size() - n);
}
bool pdatatypes_decl::instantiate(pdecl_manager & m, sort * const * s) {
UNREACHABLE();
return false;
}
bool pdatatypes_decl::commit(pdecl_manager& m) {
datatype_decl_buffer dts;
for (pdatatype_decl* d : m_datatypes) {
sort_ref_vector ps(m.m());
for (unsigned i = 0; i < d->get_num_params(); ++i) {
ps.push_back(m.m().mk_uninterpreted_sort(symbol(i), 0, nullptr));
}
dts.m_buffer.push_back(d->instantiate_decl(m, ps.size(), ps.data()));
}
sort_ref_vector sorts(m.m());
bool is_ok = m.get_dt_plugin()->mk_datatypes(m_datatypes.size(), dts.m_buffer.data(), 0, nullptr, sorts);
if (is_ok) {
for (pdatatype_decl* d : m_datatypes) {
m.notify_mk_datatype(d->get_name());
}
for (unsigned i = 0; i < m_datatypes.size(); ++i) {
pdatatype_decl* d = m_datatypes[i];
if (d->get_num_params() == 0)
m.notify_new_dt(sorts.get(i), this);
}
}
return is_ok;
}
void pdecl_manager::notify_mk_datatype(symbol const& name) {
m_datatypes_trail.push_back(name);
}
struct pdecl_manager::sort_info {
psort_decl * m_decl;
sort_info(pdecl_manager & m, psort_decl * d):
m_decl(d) {
m.inc_ref(d);
}
virtual ~sort_info() = default;
virtual unsigned obj_size() const { return sizeof(sort_info); }
virtual void finalize(pdecl_manager & m) { m.dec_ref(m_decl); }
virtual void display(std::ostream & out, pdecl_manager const & m) const = 0;
virtual format * pp(smt2_pp_environment& env, pdecl_manager const & m) const = 0;
};
struct pdecl_manager::app_sort_info : public pdecl_manager::sort_info {
ptr_vector m_args;
app_sort_info(pdecl_manager & m, psort_decl * d, unsigned n, sort * const * s):
sort_info(m, d),
m_args(n, s) {
m.m().inc_array_ref(n, s);
}
unsigned obj_size() const override { return sizeof(app_sort_info); }
void finalize(pdecl_manager & m) override {
sort_info::finalize(m);
m.m().dec_array_ref(m_args.size(), m_args.data());
}
void display(std::ostream & out, pdecl_manager const & m) const override {
if (m_args.empty()) {
out << m_decl->get_name();
}
else {
out << "(" << m_decl->get_name();
for (auto arg : m_args) {
m.display(out << " ", arg);
}
out << ")";
}
}
format * pp(smt2_pp_environment& env, pdecl_manager const & m) const override {
symbol s = m_decl->get_name();
std::string name = s.str();
if (is_smt2_quoted_symbol(s))
name = mk_smt2_quoted_symbol(s);
if (m_args.empty()) {
return mk_string(m.m(), name);
}
else {
ptr_buffer b;
for (auto arg : m_args)
b.push_back(m.pp(env, arg));
return mk_seq1(m.m(), b.begin(), b.end(), f2f(), name);
}
}
};
struct pdecl_manager::indexed_sort_info : public pdecl_manager::sort_info {
svector m_indices;
indexed_sort_info(pdecl_manager & m, psort_decl * d, unsigned n, unsigned const * s):
sort_info(m, d),
m_indices(n, s) {
}
unsigned obj_size() const override { return sizeof(indexed_sort_info); }
void display(std::ostream & out, pdecl_manager const & m) const override {
if (m_indices.empty()) {
out << m_decl->get_name();
}
else {
out << "(_ " << m_decl->get_name();
for (auto idx : m_indices) {
out << " " << idx;
}
out << ")";
}
}
format * pp(smt2_pp_environment& env, pdecl_manager const & m) const override {
symbol s = m_decl->get_name();
std::string name = s.str();
if (is_smt2_quoted_symbol(s))
name = mk_smt2_quoted_symbol(s);
if (m_indices.empty()) {
return mk_string(m.m(), name);
}
else {
ptr_buffer b;
b.push_back(mk_string(m.m(), name));
for (auto idx : m_indices)
b.push_back(mk_unsigned(m.m(), idx));
return mk_seq1(m.m(), b.begin(), b.end(), f2f(), "_");
}
}
};
void pdecl_manager::init_list() {
SASSERT(m_list == 0);
psort * v = mk_psort_var(1, 0);
ptype T(v);
ptype ListT(0);
paccessor_decl * as[2] = { mk_paccessor_decl(1, symbol("head"), T),
mk_paccessor_decl(1, symbol("tail"), ListT) };
pconstructor_decl * cs[2] = { mk_pconstructor_decl(1, symbol("nil"), symbol("is-nil"), 0, nullptr),
mk_pconstructor_decl(1, symbol("insert"), symbol("is-insert"), 2, as) };
m_list = mk_pdatatype_decl(1, symbol("List"), 2, cs);
inc_ref(m_list);
m_list->commit(*this);
}
pdecl_manager::pdecl_manager(ast_manager & m):
m_manager(m),
m_allocator(m.get_allocator()),
m_new_dt_eh(nullptr) {
m_list = nullptr;
m_datatype_fid = m.mk_family_id("datatype");
}
pdecl_manager::~pdecl_manager() {
dec_ref(m_list);
reset_sort_info();
for (auto const& kv : m_sort2psort) {
del_decl_core(kv.m_value);
TRACE("pdecl_manager", tout << "orphan: " << mk_pp(kv.m_key, m()) << "\n";);
}
for (auto* p : m_table) {
del_decl_core(p);
}
m_sort2psort.reset();
m_table.reset();
SASSERT(m_sort2psort.empty());
SASSERT(m_table.empty());
}
psort * pdecl_manager::mk_psort_cnst(sort * s) {
psort * r = nullptr;
if (m_sort2psort.find(s, r))
return r;
r = new (a().allocate(sizeof(psort_sort))) psort_sort(m_id_gen.mk(), *this, s);
m_sort2psort.insert(s, r);
return r;
}
psort * pdecl_manager::register_psort(psort * n) {
psort * r = m_table.insert_if_not_there(n);
if (r != n) {
del_decl_core(n);
}
return r;
}
psort * pdecl_manager::mk_psort_var(unsigned num_params, unsigned vidx) {
psort_var * n = new (a().allocate(sizeof(psort_var))) psort_var(m_id_gen.mk(), num_params, vidx);
return register_psort(n);
}
paccessor_decl * pdecl_manager::mk_paccessor_decl(unsigned num_params, symbol const & s, ptype const & p) {
return new (a().allocate(sizeof(paccessor_decl))) paccessor_decl(m_id_gen.mk(), num_params, *this, s, p);
}
pconstructor_decl * pdecl_manager::mk_pconstructor_decl(unsigned num_params,
symbol const & s, symbol const & r, unsigned num, paccessor_decl * const * as) {
return new (a().allocate(sizeof(pconstructor_decl))) pconstructor_decl(m_id_gen.mk(), num_params, *this,
s, r, num, as);
}
pdatatype_decl * pdecl_manager::mk_pdatatype_decl(unsigned num_params, symbol const & s, unsigned num, pconstructor_decl * const * cs) {
TRACE("datatype", tout << s << " has " << num_params << " parameters\n";);
return new (a().allocate(sizeof(pdatatype_decl))) pdatatype_decl(m_id_gen.mk(), num_params, *this,
s, num, cs);
}
pdatatypes_decl * pdecl_manager::mk_pdatatypes_decl(unsigned num_params, unsigned num, pdatatype_decl * const * dts) {
return new (a().allocate(sizeof(pdatatypes_decl))) pdatatypes_decl(m_id_gen.mk(), num_params, *this,
num, dts);
}
psort * pdecl_manager::mk_psort_app(unsigned num_params, psort_decl * d, unsigned num_args, psort * const * args) {
psort * n = new (a().allocate(sizeof(psort_app))) psort_app(m_id_gen.mk(), num_params, *this, d, num_args, args);
return register_psort(n);
}
psort * pdecl_manager::mk_psort_app(psort_decl * d) {
SASSERT(d->get_num_params() == 0 || d->get_num_params() == PSORT_DECL_VAR_PARAMS);
sort * s = d->instantiate(*this, 0, static_cast(nullptr));
if (s == nullptr)
return nullptr;
return mk_psort_cnst(s);
}
psort_decl * pdecl_manager::mk_psort_user_decl(unsigned num_params, symbol const & n, psort * def) {
return new (a().allocate(sizeof(psort_user_decl))) psort_user_decl(m_id_gen.mk(), num_params, *this, n, def);
}
psort_decl * pdecl_manager::mk_psort_dt_decl(unsigned num_params, symbol const & n) {
return new (a().allocate(sizeof(psort_dt_decl))) psort_dt_decl(m_id_gen.mk(), num_params, *this, n);
}
psort_decl * pdecl_manager::mk_psort_type_var_decl(symbol const & n) {
return new (a().allocate(sizeof(psort_type_var_decl))) psort_type_var_decl(m_id_gen.mk(), *this, n);
}
psort_decl * pdecl_manager::mk_psort_builtin_decl(symbol const & n, family_id fid, decl_kind k) {
return new (a().allocate(sizeof(psort_builtin_decl))) psort_builtin_decl(m_id_gen.mk(), *this, n, fid, k);
}
sort * pdecl_manager::instantiate(psort * p, unsigned num, sort * const * args) {
// ignoring stack overflows... sorts are not deeply nested
return p->instantiate(*this, num, args);
}
void pdecl_manager::del_decl_core(pdecl * p) {
TRACE("pdecl_manager",
tout << "del_decl_core:\n";
if (p->is_psort()) static_cast(p)->display(tout);
else static_cast(p)->display(tout);
tout << "\n";);
size_t sz = p->obj_size();
m_id_gen.recycle(p->get_id());
p->finalize(*this);
p->~pdecl();
m_allocator.deallocate(sz, p);
}
void pdecl_manager::del_decl(pdecl * p) {
TRACE("pdecl_manager", tout << "del psort "; p->display(tout); tout << "\n";);
if (p->is_psort()) {
psort * _p = static_cast(p);
if (_p->is_sort_wrapper()) {
sort* s = static_cast(_p)->get_sort();
m_sort2psort.erase(s);
}
else {
m_table.erase(_p);
}
}
del_decl_core(p);
}
void pdecl_manager::del_decls() {
while (!m_to_delete.empty()) {
pdecl * p = m_to_delete.back();
m_to_delete.pop_back();
del_decl(p);
}
}
psort_inst_cache * pdecl_manager::mk_inst_cache(unsigned num_params) {
return new (a().allocate(sizeof(psort_inst_cache))) psort_inst_cache(num_params);
}
void pdecl_manager::del_inst_cache(psort_inst_cache * c) {
if (c) {
c->finalize(*this);
c->~psort_inst_cache();
a().deallocate(sizeof(psort_inst_cache), c);
}
}
datatype_decl_plugin * pdecl_manager::get_dt_plugin() const {
return static_cast(m().get_plugin(m_datatype_fid));
}
void pdecl_manager::save_info(sort * s, psort_decl * d, unsigned num_args, sort * const * args) {
if (m_sort2info.contains(s))
return;
sort_info * info = new (a().allocate(sizeof(app_sort_info))) app_sort_info(*this, d, num_args, args);
m().inc_ref(s);
m_sort2info.insert(s, info);
}
void pdecl_manager::save_info(sort * s, psort_decl * d, unsigned num_indices, unsigned const * indices) {
if (m_sort2info.contains(s))
return;
sort_info * info = new (a().allocate(sizeof(indexed_sort_info))) indexed_sort_info(*this, d, num_indices, indices);
m().inc_ref(s);
m_sort2info.insert(s, info);
}
void pdecl_manager::reset_sort_info() {
for (auto kv : m_sort2info) {
sort * s = kv.m_key;
sort_info * info = kv.m_value;
m().dec_ref(s);
unsigned sz = info->obj_size();
info->finalize(*this);
info->~sort_info();
m_allocator.deallocate(sz, info);
}
m_sort2info.reset();
}
void pdecl_manager::display(std::ostream & out, sort * s) const {
sort_info * info = nullptr;
if (m_sort2info.find(s, info)) {
info->display(out, *this);
return;
}
out << s->get_name();
}
format * pdecl_manager::pp(smt2_pp_environment& env, sort * s) const {
sort_info * info = nullptr;
if (m_sort2info.find(s, info))
return info->pp(env, *this);
else
return nullptr;
}