mirror of
https://github.com/Z3Prover/z3
synced 2025-08-09 04:31:24 +00:00
enable nested ADT and sequences
add API to define forward reference to recursively defined datatype. The forward reference should be used only when passed to constructor declarations that are used in a datatype definition (Z3_mk_datatypes). The call to Z3_mk_datatypes ensures that the forward reference can be resolved with respect to constructors.
This commit is contained in:
parent
8e2f09b517
commit
81d97a81af
10 changed files with 232 additions and 92 deletions
|
@ -19,6 +19,7 @@ Revision History:
|
|||
|
||||
#include "util/warning.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
|
@ -462,28 +463,27 @@ namespace datatype {
|
|||
}
|
||||
for (symbol const& s : m_def_block) {
|
||||
def& d = *m_defs[s];
|
||||
for (constructor* c : d) {
|
||||
for (accessor* a : *c) {
|
||||
for (constructor* c : d)
|
||||
for (accessor* a : *c)
|
||||
a->fix_range(sorts);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!u().is_well_founded(sorts.size(), sorts.data())) {
|
||||
if (!u().is_well_founded(sorts.size(), sorts.data()))
|
||||
m_manager->raise_exception("datatype is not well-founded");
|
||||
}
|
||||
if (!u().is_covariant(sorts.size(), sorts.data())) {
|
||||
if (!u().is_covariant(sorts.size(), sorts.data()))
|
||||
m_manager->raise_exception("datatype is not co-variant");
|
||||
}
|
||||
|
||||
|
||||
array_util autil(m);
|
||||
seq_util sutil(m);
|
||||
sort* sr;
|
||||
for (sort* s : sorts) {
|
||||
for (constructor const* c : get_def(s)) {
|
||||
for (accessor const* a : *c) {
|
||||
if (autil.is_array(a->range())) {
|
||||
if (sorts.contains(get_array_range(a->range()))) {
|
||||
m_has_nested_arrays = true;
|
||||
}
|
||||
}
|
||||
if (autil.is_array(a->range()) && sorts.contains(get_array_range(a->range())))
|
||||
m_has_nested_rec = true;
|
||||
else if (sutil.is_seq(a->range(), sr) && sorts.contains(sr))
|
||||
m_has_nested_rec = true;
|
||||
else if (sutil.is_re(a->range(), sr) && sorts.contains(sr))
|
||||
m_has_nested_rec = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1103,12 +1103,19 @@ namespace datatype {
|
|||
return r;
|
||||
}
|
||||
|
||||
bool util::is_recursive_array(sort* a) {
|
||||
bool util::is_recursive_nested(sort* a) {
|
||||
array_util autil(m);
|
||||
if (!autil.is_array(a))
|
||||
return false;
|
||||
a = autil.get_array_range_rec(a);
|
||||
return is_datatype(a) && is_recursive(a);
|
||||
seq_util sutil(m);
|
||||
sort* sr;
|
||||
if (autil.is_array(a)) {
|
||||
a = autil.get_array_range_rec(a);
|
||||
return is_datatype(a) && is_recursive(a);
|
||||
}
|
||||
if (sutil.is_seq(a, sr))
|
||||
return is_datatype(sr) && is_recursive(sr);
|
||||
if (sutil.is_re(a, sr))
|
||||
return is_datatype(sr) && is_recursive(sr);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool util::is_enum_sort(sort* s) {
|
||||
|
@ -1273,14 +1280,22 @@ namespace datatype {
|
|||
*/
|
||||
bool util::are_siblings(sort * s1, sort * s2) {
|
||||
array_util autil(m);
|
||||
s1 = autil.get_array_range_rec(s1);
|
||||
s2 = autil.get_array_range_rec(s2);
|
||||
if (!is_datatype(s1) || !is_datatype(s2)) {
|
||||
seq_util sutil(m);
|
||||
auto get_nested = [&](sort* s) {
|
||||
while (true) {
|
||||
if (autil.is_array(s))
|
||||
s = get_array_range(s);
|
||||
else if (!sutil.is_seq(s, s))
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
s1 = get_nested(s1);
|
||||
s2 = get_nested(s2);
|
||||
if (!is_datatype(s1) || !is_datatype(s2))
|
||||
return s1 == s2;
|
||||
}
|
||||
else {
|
||||
else
|
||||
return get_def(s1).id() == get_def(s2).id();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned util::get_datatype_num_constructors(sort * ty) {
|
||||
|
|
|
@ -207,14 +207,14 @@ namespace datatype {
|
|||
unsigned m_id_counter;
|
||||
svector<symbol> m_def_block;
|
||||
unsigned m_class_id;
|
||||
mutable bool m_has_nested_arrays;
|
||||
mutable bool m_has_nested_rec;
|
||||
|
||||
void inherit(decl_plugin* other_p, ast_translation& tr) override;
|
||||
|
||||
void log_axiom_definitions(symbol const& s, sort * new_sort);
|
||||
|
||||
public:
|
||||
plugin(): m_id_counter(0), m_class_id(0), m_has_nested_arrays(false) {}
|
||||
plugin(): m_id_counter(0), m_class_id(0), m_has_nested_rec(false) {}
|
||||
~plugin() override;
|
||||
|
||||
void finalize() override;
|
||||
|
@ -254,7 +254,7 @@ namespace datatype {
|
|||
unsigned get_axiom_base_id(symbol const& s) { return m_axiom_bases[s]; }
|
||||
util & u() const;
|
||||
|
||||
bool has_nested_arrays() const { return m_has_nested_arrays; }
|
||||
bool has_nested_rec() const { return m_has_nested_rec; }
|
||||
|
||||
private:
|
||||
bool is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const;
|
||||
|
@ -334,7 +334,7 @@ namespace datatype {
|
|||
bool is_datatype(sort const* s) const { return is_sort_of(s, fid(), DATATYPE_SORT); }
|
||||
bool is_enum_sort(sort* s);
|
||||
bool is_recursive(sort * ty);
|
||||
bool is_recursive_array(sort * ty);
|
||||
bool is_recursive_nested(sort * ty);
|
||||
bool is_constructor(func_decl * f) const { return is_decl_of(f, fid(), OP_DT_CONSTRUCTOR); }
|
||||
bool is_recognizer(func_decl * f) const { return is_recognizer0(f) || is_is(f); }
|
||||
bool is_recognizer0(func_decl * f) const { return is_decl_of(f, fid(), OP_DT_RECOGNISER); }
|
||||
|
@ -365,7 +365,7 @@ namespace datatype {
|
|||
func_decl * get_accessor_constructor(func_decl * accessor);
|
||||
func_decl * get_recognizer_constructor(func_decl * recognizer) const;
|
||||
func_decl * get_update_accessor(func_decl * update) const;
|
||||
bool has_nested_arrays() const { return plugin().has_nested_arrays(); }
|
||||
bool has_nested_rec() const { return plugin().has_nested_rec(); }
|
||||
family_id get_family_id() const { return fid(); }
|
||||
decl::plugin& plugin() const;
|
||||
bool are_siblings(sort * s1, sort * s2);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue