diff --git a/src/ast/datatype_decl_plugin2.cpp b/src/ast/datatype_decl_plugin2.cpp index 4e60abcce..0030af609 100644 --- a/src/ast/datatype_decl_plugin2.cpp +++ b/src/ast/datatype_decl_plugin2.cpp @@ -15,14 +15,13 @@ Author: Revision History: - // compute sort sizes and insert them. - // have a notion of pre-sort or just attach sort size after declaration. - --*/ -#include "ast/datatype_decl_plugin2.h" #include "util/warning.h" +#include "ast/datatype_decl_plugin2.h" +#include "ast/array_decl_plugin.h" #include "ast/ast_smt2_pp.h" + namespace datatype { func_decl_ref accessor::instantiate(sort_ref_vector const& ps) const { @@ -78,6 +77,32 @@ namespace datatype { BLACK }; + namespace param_size { + size* size::mk_offset(sort_size const& s) { return alloc(offset, s); } + size* size::mk_param(sort_ref& p) { return alloc(sparam, p); } + size* size::mk_plus(size* a1, size* a2) { return alloc(plus, a1, a2); } + size* size::mk_times(size* a1, size* a2) { return alloc(times, a1, a2); } + size* size::mk_times(ptr_vector& szs) { + if (szs.empty()) return mk_offset(sort_size(1)); + if (szs.size() == 1) return szs[0]; + size* r = szs[0]; + for (unsigned i = 1; i < szs.size(); ++i) { + r = mk_times(r, szs[i]); + } + return r; + } + size* size::mk_plus(ptr_vector& szs) { + if (szs.empty()) return mk_offset(sort_size(0)); + if (szs.size() == 1) return szs[0]; + size* r = szs[0]; + for (unsigned i = 1; i < szs.size(); ++i) { + r = mk_plus(r, szs[i]); + } + return r; + } + size* size::mk_power(size* a1, size* a2) { return alloc(power, a1, a2); } + } + namespace decl { plugin::~plugin() { @@ -125,9 +150,16 @@ namespace datatype { sort* s = m_manager->mk_sort(name.get_symbol(), sort_info(m_family_id, k, num_parameters, parameters, true)); - // compute datatype size - sort_size ts = u().get_datatype_size(s); - s->set_num_elements(ts); + def* d = 0; + if (m_defs.find(s->get_name(), d) && d->sort_size()) { + obj_map S; + for (unsigned i = 1; i < num_parameters; ++i) { + sort* r = to_sort(parameters[i].get_ast()); + S.insert(d->params()[i], r->get_num_elements()); + } + sort_size ts = d->sort_size()->fold(S); + s->set_num_elements(ts); + } return s; } catch (invalid_datatype) { @@ -256,6 +288,7 @@ namespace datatype { if (!u().is_well_founded(sorts.size(), sorts.c_ptr())) { m_manager->raise_exception("datatype is not well-founded"); } + u().compute_datatype_size_functions(m_def_block); } void plugin::del(symbol const& s) { @@ -418,84 +451,111 @@ namespace datatype { } return false; } + + unsigned util::get_datatype_num_parameter_sorts(sort * ty) { + SASSERT(ty->get_num_parameters() >= 1); + return ty->get_num_parameters() - 1; + } + + sort* util::get_datatype_parameter_sort(sort * ty, unsigned idx) { + SASSERT(idx < get_datatype_num_parameter_sorts(ty)); + return to_sort(ty->get_parameter(idx+1).get_ast()); + } + + param_size::size* util::get_sort_size(sort_ref_vector const& params, sort* s) { + if (params.empty()) { + return param_size::size::mk_offset(s->get_num_elements()); + } + if (is_datatype(s)) { + param_size::size* sz; + obj_map S; + unsigned n = get_datatype_num_parameter_sorts(s); + for (unsigned i = 0; i < n; ++i) { + sort* ps = get_datatype_parameter_sort(s, i); + sz = get_sort_size(params, ps); + sz->inc_ref(); + S.insert(ps, sz); + } + def & d = get_def(s->get_name()); + sz = d.sort_size()->subst(S); + for (auto & kv : S) { + kv.m_value->dec_ref(); + } + return sz; + } + array_util autil(m); + if (autil.is_array(s)) { + unsigned n = get_array_arity(s); + ptr_vector szs; + for (unsigned i = 0; i < n; ++i) { + szs.push_back(get_sort_size(params, get_array_domain(s, i))); + } + param_size::size* sz1 = param_size::size::mk_times(szs); + param_size::size* sz2 = get_sort_size(params, get_array_range(s)); + return param_size::size::mk_power(sz2, sz1); + } + for (sort* p : params) { + if (s == p) return param_size::size::mk_param(sort_ref(s, m)); + } + return param_size::size::mk_offset(s->get_num_elements()); + } - /** - \brief Return the size of the inductive datatype. - Pre-condition: The given argument constains the parameters of an inductive datatype. - */ - sort_size util::get_datatype_size(sort* s0) { - obj_map already_found; - obj_map szs; - ptr_vector todo; - todo.push_back(s0); + void util::compute_datatype_size_functions(svector const& names) { + map already_found; + map szs; + + svector todo(names); status st; while (!todo.empty()) { - sort* s = todo.back(); + symbol s = todo.back(); if (already_found.find(s, st) && st == BLACK) { todo.pop_back(); continue; } already_found.insert(s, GRAY); - bool is_very_big = false; - bool can_process = true; - def const& d = get_def(s); + bool is_infinite = false; + bool can_process = true; + def& d = get_def(s); for (constructor const& c : d) { for (accessor const& a : c) { - func_decl_ref ac = a.instantiate(s); - sort* r = ac->get_range(); + sort* r = a.range(); if (is_datatype(r)) { - if (already_found.find(r, st)) { + symbol s2 = r->get_name(); + if (already_found.find(s2, st)) { // type is infinite - if (st == GRAY) return sort_size(); + if (st == GRAY) { + is_infinite = true; + } } - else { - todo.push_back(r); + else if (names.contains(s2)) { + todo.push_back(s2); can_process = false; } } - else if (r->is_infinite()) { - // type is infinite - return sort_size(); - } - else if (r->is_very_big()) { - is_very_big = true; - } } } + if (!can_process) { + continue; + } + todo.pop_back(); + already_found.insert(s, BLACK); + if (is_infinite) { + d.set_sort_size(param_size::size::mk_offset(sort_size::mk_infinite())); + continue; + } - if (can_process) { - todo.pop_back(); - already_found.insert(s, BLACK); - if (is_very_big) { - szs.insert(s, sort_size::mk_very_big()); - } - else { - // the type is not infinite nor the number of elements is infinite... - // computing the number of elements - rational num; - def const& d = get_def(s); - for (constructor const& c : d) { - rational c_num(1); - for (accessor const& a : c) { - func_decl_ref ac = a.instantiate(s); - sort* r = ac->get_range(); - if (szs.contains(r)) { - c_num *= rational(szs[r].size(), rational::ui64()); - } - else { - SASSERT(!r->is_infinite() && !r->is_very_big()); - c_num *= rational(r->get_num_elements().size(), rational::ui64()); - } - } - num += c_num; - } - szs.insert(s, sort_size(num)); + ptr_vector s_add; + for (constructor const& c : d) { + ptr_vector s_mul; + for (accessor const& a : c) { + s_mul.push_back(get_sort_size(d.params(), a.range())); } + s_add.push_back(param_size::size::mk_times(s_mul)); } + d.set_sort_size(param_size::size::mk_plus(s_add)); } - return szs[s0]; } - + /** \brief Return true if the inductive datatype is well-founded. diff --git a/src/ast/datatype_decl_plugin2.h b/src/ast/datatype_decl_plugin2.h index fad7ff174..a4a76f346 100644 --- a/src/ast/datatype_decl_plugin2.h +++ b/src/ast/datatype_decl_plugin2.h @@ -85,11 +85,100 @@ namespace datatype { util& u() const; }; + namespace param_size { + class size { + unsigned m_ref; + public: + size(): m_ref(0) {} + virtual ~size() {} + void inc_ref() { ++m_ref; } + void dec_ref() { --m_ref; if (m_ref == 0) dealloc(this); } + static size* mk_offset(sort_size const& s); + static size* mk_param(sort_ref& p); + static size* mk_plus(size* a1, size* a2); + static size* mk_times(size* a1, size* a2); + static size* mk_plus(ptr_vector& szs); + static size* mk_times(ptr_vector& szs); + static size* mk_power(size* a1, size* a2); + + virtual size* subst(obj_map& S) = 0; + virtual sort_size fold(obj_map const& S) = 0; + + }; + struct offset : public size { + sort_size m_offset; + offset(sort_size const& s): m_offset(s) {} + virtual ~offset() {} + virtual size* subst(obj_map& S) { return this; } + virtual sort_size fold(obj_map const& S) { return m_offset; } + }; + struct plus : public size { + size* m_arg1, *m_arg2; + plus(size* a1, size* a2): m_arg1(a1), m_arg2(a2) { a1->inc_ref(); a2->inc_ref();} + virtual ~plus() { m_arg1->dec_ref(); m_arg2->dec_ref(); } + virtual size* subst(obj_map& S) { return mk_plus(m_arg1->subst(S), m_arg2->subst(S)); } + virtual sort_size fold(obj_map const& S) { + sort_size s1 = m_arg1->fold(S); + sort_size s2 = m_arg2->fold(S); + if (s1.is_infinite()) return s1; + if (s2.is_infinite()) return s2; + if (s1.is_very_big()) return s1; + if (s2.is_very_big()) return s2; + rational r = rational(s1.size(), rational::ui64()) + rational(s2.size(), rational::ui64()); + return sort_size(r); + } + }; + struct times : public size { + size* m_arg1, *m_arg2; + times(size* a1, size* a2): m_arg1(a1), m_arg2(a2) { a1->inc_ref(); a2->inc_ref(); } + virtual ~times() { m_arg1->dec_ref(); m_arg2->dec_ref(); } + virtual size* subst(obj_map& S) { return mk_times(m_arg1->subst(S), m_arg2->subst(S)); } + virtual sort_size fold(obj_map const& S) { + sort_size s1 = m_arg1->fold(S); + sort_size s2 = m_arg2->fold(S); + if (s1.is_infinite()) return s1; + if (s2.is_infinite()) return s2; + if (s1.is_very_big()) return s1; + if (s2.is_very_big()) return s2; + rational r = rational(s1.size(), rational::ui64()) * rational(s2.size(), rational::ui64()); + return sort_size(r); + } + }; + struct power : public size { + size* m_arg1, *m_arg2; + power(size* a1, size* a2): m_arg1(a1), m_arg2(a2) { a1->inc_ref(); a2->inc_ref(); } + virtual ~power() { m_arg1->dec_ref(); m_arg2->dec_ref(); } + virtual size* subst(obj_map& S) { return mk_power(m_arg1->subst(S), m_arg2->subst(S)); } + virtual sort_size fold(obj_map const& S) { + sort_size s1 = m_arg1->fold(S); + sort_size s2 = m_arg2->fold(S); + // s1^s2 + if (s1.is_infinite()) return s1; + if (s2.is_infinite()) return s2; + if (s1.is_very_big()) return s1; + if (s2.is_very_big()) return s2; + if (s1.size() == 1) return s1; + if (s2.size() == 1) return s1; + if (s1.size() > (2 << 20) || s2.size() > 10) return sort_size::mk_very_big(); + rational r = ::power(rational(s1.size(), rational::ui64()), static_cast(s2.size())); + return sort_size(r); + } + }; + struct sparam : public size { + sort_ref m_param; + sparam(sort_ref& p): m_param(p) {} + virtual ~sparam() {} + virtual size* subst(obj_map& S) { return S[m_param]; } + virtual sort_size fold(obj_map const& S) { return S[m_param]; } + }; + }; + class def { ast_manager& m; util& m_util; symbol m_name; unsigned m_class_id; + param_size::size* m_sort_size; sort_ref_vector m_params; mutable sort_ref m_sort; vector m_constructors; @@ -99,9 +188,13 @@ namespace datatype { m_util(u), m_name(n), m_class_id(class_id), + m_sort_size(0), m_params(m, num_params, params), m_sort(m) {} + ~def() { + if (m_sort_size) m_sort_size->dec_ref(); + } void add(constructor& c) { m_constructors.push_back(c); c.attach(this); @@ -114,6 +207,8 @@ namespace datatype { vector::const_iterator end() const { return m_constructors.end(); } sort_ref_vector const& params() const { return m_params; } util& u() const { return m_util; } + param_size::size* sort_size() { return m_sort_size; } + void set_sort_size(param_size::size* p) { m_sort_size = p; p->inc_ref(); } }; namespace decl { @@ -155,7 +250,8 @@ namespace datatype { void del(symbol const& d); - def const& get_def(sort* s) const { def* d = 0; VERIFY(m_defs.find(datatype_name(s), d)); return *d; } + def const& get_def(sort* s) const { return *(m_defs[datatype_name(s)]); } + def& get_def(symbol const& s) { return *(m_defs[s]); } private: bool is_value_visit(expr * arg, ptr_buffer & todo) const; @@ -213,8 +309,11 @@ namespace datatype { bool is_recursive_core(sort * s) const; sort_size get_datatype_size(sort* s0); + void compute_datatype_size_functions(svector const& names); + param_size::size* get_sort_size(sort_ref_vector const& params, sort* s); bool is_well_founded(unsigned num_types, sort* const* sorts); def const& get_def(sort* s) const; + def& get_def(symbol const& s) { return m_plugin->get_def(s); } void get_subsorts(sort* s, ptr_vector& sorts) const; public: diff --git a/src/cmd_context/pdecl.cpp b/src/cmd_context/pdecl.cpp index 983dbbc78..88ab9f8b8 100644 --- a/src/cmd_context/pdecl.cpp +++ b/src/cmd_context/pdecl.cpp @@ -39,15 +39,13 @@ public: } else { SASSERT(m_const == 0); - obj_map::iterator it = m_map.begin(); - obj_map::iterator end = m_map.end(); - for (; it != end; ++it) { - m.m().dec_ref((*it).m_key); + for (auto kv : m_map) { + m.m().dec_ref(kv.m_key); if (m_num_params == 1) { - m.m().dec_ref(static_cast((*it).m_value)); + m.m().dec_ref(static_cast(kv.m_value)); } else { - psort_inst_cache * child = static_cast((*it).m_value); + psort_inst_cache * child = static_cast(kv.m_value); child->finalize(m); child->~psort_inst_cache(); m.a().deallocate(sizeof(psort_inst_cache), child); @@ -485,20 +483,16 @@ void pconstructor_decl::finalize(pdecl_manager & m) { } bool pconstructor_decl::has_missing_refs(symbol & missing) const { - ptr_vector::const_iterator it = m_accessors.begin(); - ptr_vector::const_iterator end = m_accessors.end(); - for (; it != end; ++it) { - if ((*it)->has_missing_refs(missing)) + 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) { - ptr_vector::iterator it = m_accessors.begin(); - ptr_vector::iterator end = m_accessors.end(); - for (; it != end; ++it) { - if (!(*it)->fix_missing_refs(symbol2idx, missing)) + for (paccessor_decl* a : m_accessors) { + if (!a->fix_missing_refs(symbol2idx, missing)) return false; } return true; @@ -506,20 +500,16 @@ bool pconstructor_decl::fix_missing_refs(dictionary const & symbol2idx, sym constructor_decl * pconstructor_decl::instantiate_decl(pdecl_manager & m, sort * const * s) { ptr_buffer as; - ptr_vector::iterator it = m_accessors.begin(); - ptr_vector::iterator end = m_accessors.end(); - for (; it != end; ++it) - as.push_back((*it)->instantiate_decl(m, s)); + for (paccessor_decl* a : m_accessors) + as.push_back(a->instantiate_decl(m, s)); return mk_constructor_decl(m_name, m_recogniser_name, as.size(), as.c_ptr()); } void pconstructor_decl::display(std::ostream & out, pdatatype_decl const * const * dts) const { out << "(" << m_name; - ptr_vector::const_iterator it = m_accessors.begin(); - ptr_vector::const_iterator end = m_accessors.end(); - for (; it != end; ++it) { + for (paccessor_decl* a : m_accessors) { out << " "; - (*it)->display(out, dts); + a->display(out, dts); } out << ")"; } @@ -538,23 +528,17 @@ void pdatatype_decl::finalize(pdecl_manager & m) { } bool pdatatype_decl::has_missing_refs(symbol & missing) const { - ptr_vector::const_iterator it = m_constructors.begin(); - ptr_vector::const_iterator end = m_constructors.end(); - for (; it != end; ++it) { - if ((*it)->has_missing_refs(missing)) + 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; - ptr_vector::const_iterator it = m_constructors.begin(); - ptr_vector::const_iterator end = m_constructors.end(); - for (; it != end; ++it) { - ptr_vector const& acc = (*it)->m_accessors; - for (unsigned i = 0; i < acc.size(); ++i) { - symbol const& name = acc[i]->get_name(); + 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; @@ -567,10 +551,8 @@ bool pdatatype_decl::has_duplicate_accessors(symbol & duplicated) const { bool pdatatype_decl::fix_missing_refs(dictionary const & symbol2idx, symbol & missing) { - ptr_vector::iterator it = m_constructors.begin(); - ptr_vector::iterator end = m_constructors.end(); - for (; it != end; ++it) { - if (!(*it)->fix_missing_refs(symbol2idx, missing)) + for (auto c : m_constructors) { + if (!c->fix_missing_refs(symbol2idx, missing)) return false; } return true; @@ -578,10 +560,8 @@ bool pdatatype_decl::fix_missing_refs(dictionary const & symbol2idx, symbol datatype_decl * pdatatype_decl::instantiate_decl(pdecl_manager & m, sort * const * s) { ptr_buffer cs; - ptr_vector::iterator it = m_constructors.begin(); - ptr_vector::iterator end = m_constructors.end(); - for (; it != end; ++it) { - cs.push_back((*it)->instantiate_decl(m, s)); + for (auto c : m_constructors) { + cs.push_back(c->instantiate_decl(m, s)); } return mk_datatype_decl(m_name, cs.size(), cs.c_ptr()); } @@ -624,17 +604,16 @@ sort * pdatatype_decl::instantiate(pdecl_manager & m, unsigned n, sort * const * void pdatatype_decl::display(std::ostream & out) const { out << "(declare-datatype " << m_name; display_sort_args(out, m_num_params); - ptr_vector::const_iterator it = m_constructors.begin(); - ptr_vector::const_iterator end = m_constructors.end(); - for (bool first = true; it != end; ++it) { + bool first = true; + for (auto c : m_constructors) { if (!first) out << " "; if (m_parent) { - (*it)->display(out, m_parent->children()); + c->display(out, m_parent->children()); } else { pdatatype_decl const * dts[1] = { this }; - (*it)->display(out, dts); + c->display(out, dts); } first = false; } @@ -647,11 +626,9 @@ pdatatypes_decl::pdatatypes_decl(unsigned id, unsigned num_params, pdecl_manager m_datatypes(num_datatypes, dts) { m.inc_ref(num_datatypes, dts); - ptr_vector::iterator it = m_datatypes.begin(); - ptr_vector::iterator end = m_datatypes.end(); - for (; it != end; ++it) { - SASSERT((*it)->m_parent == 0); - (*it)->m_parent = this; + for (auto d : m_datatypes) { + SASSERT(d->m_parent == 0); + d->m_parent = this; } } @@ -662,36 +639,30 @@ void pdatatypes_decl::finalize(pdecl_manager & m) { bool pdatatypes_decl::fix_missing_refs(symbol & missing) { TRACE("fix_missing_refs", tout << "pdatatypes_decl::fix_missing_refs\n";); dictionary symbol2idx; - ptr_vector::iterator it = m_datatypes.begin(); - ptr_vector::iterator end = m_datatypes.end(); - for (unsigned idx = 0; it != end; ++it, ++idx) - symbol2idx.insert((*it)->get_name(), idx); - - it = m_datatypes.begin(); - for (unsigned idx = 0; it != end; ++it, ++idx) { - if (!(*it)->fix_missing_refs(symbol2idx, missing)) + 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; } bool pdatatypes_decl::instantiate(pdecl_manager & m, sort * const * s) { datatype_decl_buffer dts; - ptr_vector::iterator it = m_datatypes.begin(); - ptr_vector::iterator end = m_datatypes.end(); - for (; it != end; ++it) { - dts.m_buffer.push_back((*it)->instantiate_decl(m, s)); + for (auto d : m_datatypes) { + dts.m_buffer.push_back(d->instantiate_decl(m, s)); } sort_ref_vector sorts(m.m()); bool is_ok = m.get_dt_plugin()->mk_datatypes(dts.m_buffer.size(), dts.m_buffer.c_ptr(), m_num_params, s, sorts); if (!is_ok) return false; - it = m_datatypes.begin(); - for (unsigned i = 0; it != end; ++it, ++i) { - sort * new_dt = sorts.get(i); - (*it)->cache(m, s, new_dt); - m.save_info(new_dt, *it, m_num_params, s); - m.notify_new_dt(new_dt, *it); + unsigned i = 0; + for (auto d : m_datatypes) { + sort * new_dt = sorts.get(i++); + d->cache(m, s, new_dt); + m.save_info(new_dt, d, m_num_params, s); + m.notify_new_dt(new_dt, d); } return true; } @@ -965,11 +936,9 @@ void pdecl_manager::save_info(sort * s, psort_decl * d, unsigned num_indices, un } void pdecl_manager::reset_sort_info() { - obj_map::iterator it = m_sort2info.begin(); - obj_map::iterator end = m_sort2info.end(); - for (; it != end; ++it) { - sort * s = (*it).m_key; - sort_info * info = (*it).m_value; + 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); diff --git a/src/cmd_context/pdecl.h b/src/cmd_context/pdecl.h index 2dfbb93ae..1d7203197 100644 --- a/src/cmd_context/pdecl.h +++ b/src/cmd_context/pdecl.h @@ -134,20 +134,6 @@ public: virtual void display(std::ostream & out) const; }; -#if 0 -class psort_dt_decl : public psort_decl { -protected: - friend class pdecl_manager; - psort_dt_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n); - virtual size_t obj_size() const { return sizeof(psort_dt_decl); } - virtual void finalize(pdecl_manager & m); - virtual ~psort_dt_decl() {} -public: - virtual sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s); - virtual void display(std::ostream & out) const; -}; -#endif - class datatype_decl_plugin; class datatype_decl; class constructor_decl;