mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 17:44:08 +00:00
362 lines
15 KiB
C++
362 lines
15 KiB
C++
/*++
|
|
Copyright (c) 2011 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pdecl.h
|
|
|
|
Abstract:
|
|
|
|
Parametric declarations for SMT-LIB 2.0 + inductive data-types.
|
|
|
|
Author:
|
|
|
|
Leonardo de Moura (leonardo) 2011-03-02.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#pragma once
|
|
|
|
#include "ast/ast.h"
|
|
#include "util/obj_hashtable.h"
|
|
#include "util/dictionary.h"
|
|
#include "ast/format.h"
|
|
#include "ast/datatype_decl_plugin.h"
|
|
|
|
class pdecl_manager;
|
|
|
|
class pdecl {
|
|
protected:
|
|
friend class pdecl_manager;
|
|
unsigned m_id;
|
|
unsigned m_num_params;
|
|
unsigned m_ref_count;
|
|
void inc_ref() { m_ref_count++; }
|
|
void dec_ref() { SASSERT(m_ref_count > 0); --m_ref_count; }
|
|
virtual bool is_psort() const { return false; }
|
|
virtual size_t obj_size() const { UNREACHABLE(); return sizeof(*this); }
|
|
pdecl(unsigned id, unsigned num_params):m_id(id), m_num_params(num_params), m_ref_count(0) {}
|
|
virtual void finalize(pdecl_manager & m) {}
|
|
virtual ~pdecl() {}
|
|
public:
|
|
virtual bool check_num_params(pdecl * other) const { return m_num_params == other->m_num_params; }
|
|
unsigned get_num_params() const { return m_num_params; }
|
|
unsigned get_id() const { return m_id; }
|
|
unsigned get_ref_count() const { return m_ref_count; }
|
|
unsigned hash() const { return m_id; }
|
|
virtual void display(std::ostream & out) const {}
|
|
virtual void reset_cache(pdecl_manager& m) {}
|
|
};
|
|
|
|
class psort_inst_cache;
|
|
|
|
#if defined(__APPLE__) && defined(__MACH__)
|
|
// CMW: for some unknown reason, llvm on macOS does not like the name `psort'
|
|
#define psort Z3_psort
|
|
#endif
|
|
|
|
/**
|
|
\brief Parametric sorts.
|
|
*/
|
|
class psort : public pdecl {
|
|
protected:
|
|
psort_inst_cache * m_inst_cache;
|
|
friend class pdecl_manager;
|
|
psort(unsigned id, unsigned num_params):pdecl(id, num_params), m_inst_cache(nullptr) {}
|
|
bool is_psort() const override { return true; }
|
|
void finalize(pdecl_manager & m) override;
|
|
~psort() override {}
|
|
virtual void cache(pdecl_manager & m, sort * const * s, sort * r);
|
|
virtual sort * find(sort * const * s) const;
|
|
public:
|
|
virtual bool is_sort_wrapper() const { return false; }
|
|
virtual sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) { return nullptr; }
|
|
// we use hash-consing for psorts.
|
|
virtual char const * hcons_kind() const { UNREACHABLE(); return nullptr; }
|
|
virtual unsigned hcons_hash() const { UNREACHABLE(); return 0; }
|
|
virtual bool hcons_eq(psort const * other) const { UNREACHABLE(); return false; }
|
|
void reset_cache(pdecl_manager& m) override;
|
|
};
|
|
|
|
// for hash consing
|
|
struct psort_hash_proc { unsigned operator()(psort * p) const { return p->hcons_hash(); } };
|
|
struct psort_eq_proc { bool operator()(psort * p1, psort * p2) const { return p1->hcons_eq(p2); } };
|
|
typedef ptr_hashtable<psort, psort_hash_proc, psort_eq_proc> psort_table;
|
|
|
|
#define PSORT_DECL_VAR_PARAMS UINT_MAX
|
|
|
|
typedef enum { PSORT_BASE = 0, PSORT_USER, PSORT_BUILTIN, PSORT_DT } psort_decl_kind;
|
|
|
|
class psort_decl : public pdecl {
|
|
protected:
|
|
friend class pdecl_manager;
|
|
symbol m_name;
|
|
psort_decl_kind m_psort_kind;
|
|
psort_inst_cache * m_inst_cache;
|
|
void cache(pdecl_manager & m, sort * const * s, sort * r);
|
|
sort * find(sort * const * s);
|
|
psort_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n);
|
|
void finalize(pdecl_manager & m) override;
|
|
~psort_decl() override {}
|
|
public:
|
|
virtual sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) = 0;
|
|
virtual sort * instantiate(pdecl_manager & m, unsigned n, unsigned const * s) { return nullptr; }
|
|
virtual sort * instantiate(pdecl_manager & m) { return instantiate(m, 0, static_cast<sort*const*>(nullptr)); }
|
|
// return true if the declaration accepts a variable number of parameters.
|
|
// Only builtin declarations can have a variable number of parameters.
|
|
bool has_var_params() const { return m_num_params == PSORT_DECL_VAR_PARAMS; }
|
|
symbol const & get_name() const { return m_name; }
|
|
void reset_cache(pdecl_manager& m) override;
|
|
bool is_user_decl() const { return m_psort_kind == PSORT_USER; }
|
|
bool is_builtin_decl() const { return m_psort_kind == PSORT_BUILTIN; }
|
|
bool is_dt_decl() const { return m_psort_kind == PSORT_DT; }
|
|
};
|
|
|
|
class psort_user_decl : public psort_decl {
|
|
protected:
|
|
friend class pdecl_manager;
|
|
psort * m_def;
|
|
psort_user_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, psort * p);
|
|
size_t obj_size() const override { return sizeof(psort_user_decl); }
|
|
void finalize(pdecl_manager & m) override;
|
|
~psort_user_decl() override {}
|
|
public:
|
|
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
|
void display(std::ostream & out) const override;
|
|
};
|
|
|
|
class psort_builtin_decl : public psort_decl {
|
|
protected:
|
|
friend class pdecl_manager;
|
|
family_id m_fid;
|
|
decl_kind m_kind;
|
|
psort_builtin_decl(unsigned id, pdecl_manager & m, symbol const & n, family_id fid, decl_kind k);
|
|
size_t obj_size() const override { return sizeof(psort_builtin_decl); }
|
|
~psort_builtin_decl() override {}
|
|
public:
|
|
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
|
sort * instantiate(pdecl_manager & m, unsigned n, unsigned const * s) override;
|
|
void display(std::ostream & out) const override;
|
|
};
|
|
|
|
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);
|
|
size_t obj_size() const override { return sizeof(psort_dt_decl); }
|
|
~psort_dt_decl() override {}
|
|
public:
|
|
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
|
void display(std::ostream & out) const override;
|
|
};
|
|
|
|
|
|
class pdatatypes_decl;
|
|
class pdatatype_decl;
|
|
class pconstructor_decl;
|
|
class paccessor_decl;
|
|
|
|
enum class ptype_kind {
|
|
PTR_PSORT, // psort
|
|
PTR_REC_REF, // recursive reference
|
|
PTR_MISSING_REF // a symbol, it is useful for building parsers.
|
|
};
|
|
|
|
class ptype {
|
|
ptype_kind m_kind;
|
|
union {
|
|
psort * m_sort;
|
|
int m_idx;
|
|
};
|
|
symbol m_missing_ref;
|
|
public:
|
|
ptype():m_kind(ptype_kind::PTR_PSORT), m_sort(nullptr) {}
|
|
ptype(int idx):m_kind(ptype_kind::PTR_REC_REF), m_idx(idx) {}
|
|
ptype(psort * s):m_kind(ptype_kind::PTR_PSORT), m_sort(s) {}
|
|
ptype(symbol const & s):m_kind(ptype_kind::PTR_MISSING_REF), m_sort(nullptr), m_missing_ref(s) {}
|
|
ptype_kind kind() const { return m_kind; }
|
|
psort * get_psort() const { SASSERT(kind() == ptype_kind::PTR_PSORT); return m_sort; }
|
|
int get_idx() const { SASSERT(kind() == ptype_kind::PTR_REC_REF); return m_idx; }
|
|
symbol const & get_missing_ref() const { SASSERT(kind() == ptype_kind::PTR_MISSING_REF); return m_missing_ref; }
|
|
void display(std::ostream & out, pdatatype_decl const * const * dts) const;
|
|
};
|
|
|
|
class paccessor_decl : public pdecl {
|
|
friend class pdecl_manager;
|
|
friend class pconstructor_decl;
|
|
friend class pdatatype_decl;
|
|
symbol m_name;
|
|
ptype m_type;
|
|
paccessor_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, ptype const & r);
|
|
void finalize(pdecl_manager & m) override;
|
|
size_t obj_size() const override { return sizeof(paccessor_decl); }
|
|
bool has_missing_refs(symbol & missing) const;
|
|
bool fix_missing_refs(dictionary<int> const & symbol2idx, symbol & missing);
|
|
accessor_decl * instantiate_decl(pdecl_manager & m, unsigned n, sort * const * s);
|
|
symbol const & get_name() const { return m_name; }
|
|
ptype const & get_type() const { return m_type; }
|
|
~paccessor_decl() override {}
|
|
public:
|
|
void display(std::ostream & out) const override { pdecl::display(out); }
|
|
void display(std::ostream & out, pdatatype_decl const * const * dts) const;
|
|
};
|
|
|
|
class pconstructor_decl : public pdecl {
|
|
friend class pdecl_manager;
|
|
friend class pdatatype_decl;
|
|
symbol m_name;
|
|
symbol m_recogniser_name;
|
|
ptr_vector<paccessor_decl> m_accessors;
|
|
pconstructor_decl(unsigned id, unsigned num_params, pdecl_manager & m,
|
|
symbol const & n, symbol const & r, unsigned num_accessors, paccessor_decl * const * accessors);
|
|
void finalize(pdecl_manager & m) override;
|
|
size_t obj_size() const override { return sizeof(pconstructor_decl); }
|
|
bool has_missing_refs(symbol & missing) const;
|
|
bool fix_missing_refs(dictionary<int> const & symbol2idx, symbol & missing);
|
|
symbol const & get_name() const { return m_name; }
|
|
symbol const & get_recognizer_name() const { return m_recogniser_name; }
|
|
constructor_decl * instantiate_decl(pdecl_manager & m, unsigned n, sort * const * s);
|
|
~pconstructor_decl() override {}
|
|
public:
|
|
void display(std::ostream & out) const override { pdecl::display(out); }
|
|
void display(std::ostream & out, pdatatype_decl const * const * dts) const;
|
|
};
|
|
|
|
class pdatatype_decl : public psort_decl {
|
|
friend class pdecl_manager;
|
|
friend class pdatatypes_decl;
|
|
ptr_vector<pconstructor_decl> m_constructors;
|
|
pdatatypes_decl * m_parent;
|
|
pdatatype_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n,
|
|
unsigned num_constructors, pconstructor_decl * const * constructors);
|
|
void finalize(pdecl_manager & m) override;
|
|
size_t obj_size() const override { return sizeof(pdatatype_decl); }
|
|
bool fix_missing_refs(dictionary<int> const & symbol2idx, symbol & missing);
|
|
datatype_decl * instantiate_decl(pdecl_manager & m, unsigned n, sort * const * s);
|
|
~pdatatype_decl() override {}
|
|
public:
|
|
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
|
void display(std::ostream & out) const override;
|
|
bool has_missing_refs(symbol & missing) const;
|
|
bool has_duplicate_accessors(symbol & repeated) const;
|
|
bool commit(pdecl_manager& m);
|
|
};
|
|
|
|
/**
|
|
\brief Represents a set of parametric mutually recursive inductive data-types.
|
|
*/
|
|
class pdatatypes_decl : public pdecl {
|
|
friend class pdecl_manager;
|
|
friend class pdatatype_decl;
|
|
ptr_vector<pdatatype_decl> m_datatypes;
|
|
pdatatypes_decl(unsigned id, unsigned num_params, pdecl_manager & m, unsigned num_datatypes, pdatatype_decl * const * dts);
|
|
void finalize(pdecl_manager & m) override;
|
|
size_t obj_size() const override { return sizeof(pdatatypes_decl); }
|
|
bool fix_missing_refs(symbol & missing);
|
|
bool instantiate(pdecl_manager & m, sort * const * s);
|
|
~pdatatypes_decl() override {}
|
|
public:
|
|
pdatatype_decl const * const * children() const { return m_datatypes.data(); }
|
|
pdatatype_decl * const * begin() const { return m_datatypes.begin(); }
|
|
pdatatype_decl * const * end() const { return m_datatypes.end(); }
|
|
// commit declaration
|
|
bool commit(pdecl_manager& m);
|
|
};
|
|
|
|
class new_datatype_eh {
|
|
public:
|
|
virtual ~new_datatype_eh() {}
|
|
virtual void operator()(sort * dt, pdecl* pd) = 0;
|
|
};
|
|
|
|
class pdecl_manager {
|
|
ast_manager & m_manager;
|
|
small_object_allocator & m_allocator;
|
|
id_gen m_id_gen;
|
|
obj_map<sort, psort *> m_sort2psort;
|
|
psort_table m_table;
|
|
ptr_vector<pdecl> m_to_delete;
|
|
pdatatype_decl * m_list;
|
|
family_id m_datatype_fid;
|
|
new_datatype_eh * m_new_dt_eh;
|
|
|
|
struct sort_info;
|
|
struct app_sort_info;
|
|
struct indexed_sort_info;
|
|
|
|
obj_map<sort, sort_info *> m_sort2info; // for pretty printing sorts
|
|
obj_hashtable<sort> m_notified;
|
|
ptr_vector<sort> m_notified_trail;
|
|
unsigned_vector m_notified_lim;
|
|
|
|
void init_list();
|
|
void del_decl_core(pdecl * p);
|
|
void del_decl(pdecl * p);
|
|
void del_decls();
|
|
psort * register_psort(psort * n);
|
|
void reset_sort_info();
|
|
public:
|
|
pdecl_manager(ast_manager & m);
|
|
~pdecl_manager();
|
|
ast_manager & m() const { return m_manager; }
|
|
small_object_allocator & a() const { return m_allocator; }
|
|
family_id get_datatype_fid() const { return m_datatype_fid; }
|
|
void set_new_datatype_eh(new_datatype_eh * eh) { m_new_dt_eh = eh; }
|
|
psort * mk_psort_cnst(sort * s);
|
|
psort * mk_psort_var(unsigned num_params, unsigned vidx);
|
|
psort * mk_psort_app(unsigned num_params, psort_decl * d, unsigned num_args, psort * const * args);
|
|
psort * mk_psort_app(psort_decl * d);
|
|
psort_decl * mk_psort_dt_decl(unsigned num_params, symbol const & n);
|
|
psort_decl * mk_psort_user_decl(unsigned num_params, symbol const & n, psort * def);
|
|
psort_decl * mk_psort_builtin_decl(symbol const & n, family_id fid, decl_kind k);
|
|
paccessor_decl * mk_paccessor_decl(unsigned num_params, symbol const & s, ptype const & p);
|
|
pconstructor_decl * mk_pconstructor_decl(unsigned num_params, symbol const & s, symbol const & r, unsigned num, paccessor_decl * const * as);
|
|
pdatatype_decl * mk_pdatatype_decl(unsigned num_params, symbol const & s, unsigned num, pconstructor_decl * const * cs);
|
|
pdatatypes_decl * mk_pdatatypes_decl(unsigned num_params, unsigned num, pdatatype_decl * const * dts);
|
|
pdatatype_decl * mk_plist_decl() { if (!m_list) init_list(); return m_list; }
|
|
bool fix_missing_refs(pdatatypes_decl * s, symbol & missing) { return s->fix_missing_refs(missing); }
|
|
sort * instantiate_datatype(psort_decl* p, symbol const& name, unsigned n, sort * const* s);
|
|
sort * instantiate(psort * s, unsigned num, sort * const * args);
|
|
void notify_datatype(sort *r, psort_decl* p, unsigned n, sort* const* s);
|
|
void push();
|
|
void pop(unsigned n);
|
|
|
|
void lazy_dec_ref(pdecl * p) { p->dec_ref(); if (p->get_ref_count() == 0) m_to_delete.push_back(p); }
|
|
template<typename T>
|
|
void lazy_dec_ref(unsigned num, T * const * ps) { for (unsigned i = 0; i < num; i++) lazy_dec_ref(ps[i]); }
|
|
void inc_ref(pdecl * p) { if (p) { p->inc_ref(); } }
|
|
void dec_ref(pdecl * p) { if (p) { lazy_dec_ref(p); del_decls(); } }
|
|
template<typename T>
|
|
void inc_ref(unsigned num, T * const * ps) { for (unsigned i = 0; i < num; i++) inc_ref(ps[i]); }
|
|
template<typename T>
|
|
void dec_ref(unsigned num, T * const * ps) { lazy_dec_ref(num, ps); del_decls(); }
|
|
psort_inst_cache * mk_inst_cache(unsigned num_params);
|
|
void del_inst_cache(psort_inst_cache * c);
|
|
void notify_new_dt(sort * dt, pdecl* pd) { if (m_new_dt_eh) (*m_new_dt_eh)(dt, pd); }
|
|
datatype_decl_plugin * get_dt_plugin() const;
|
|
|
|
void save_info(sort * s, psort_decl * d, unsigned num_args, sort * const * args);
|
|
void save_info(sort * s, psort_decl * d, unsigned num_indices, unsigned const * indices);
|
|
void display(std::ostream & out, sort * s) const;
|
|
format_ns::format * pp(sort * s) const;
|
|
};
|
|
|
|
|
|
typedef obj_ref<pdecl, pdecl_manager> pdecl_ref;
|
|
typedef obj_ref<psort, pdecl_manager> psort_ref;
|
|
typedef obj_ref<paccessor_decl, pdecl_manager> paccessor_decl_ref;
|
|
typedef obj_ref<pconstructor_decl, pdecl_manager> pconstructor_decl_ref;
|
|
typedef obj_ref<pdatatype_decl, pdecl_manager> pdatatype_decl_ref;
|
|
typedef obj_ref<pdatatypes_decl, pdecl_manager> pdatatypes_decl_ref;
|
|
|
|
typedef ref_vector<pdecl, pdecl_manager> pdecl_ref_vector;
|
|
typedef ref_vector<psort_decl, pdecl_manager> psort_decl_ref_vector;
|
|
typedef ref_vector<psort, pdecl_manager> psort_ref_vector;
|
|
|
|
typedef ref_buffer<paccessor_decl, pdecl_manager> paccessor_decl_ref_buffer;
|
|
typedef ref_buffer<pconstructor_decl, pdecl_manager> pconstructor_decl_ref_buffer;
|
|
typedef ref_buffer<pdatatype_decl, pdecl_manager> pdatatype_decl_ref_buffer;
|
|
typedef ref_buffer<pdatatypes_decl, pdecl_manager> pdatatypes_decl_ref_buffer;
|
|
|