mirror of
https://github.com/Z3Prover/z3
synced 2025-10-04 15:03:57 +00:00
Adding field update feature
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
a296023823
commit
129e048a1b
10 changed files with 221 additions and 24 deletions
|
@ -422,8 +422,55 @@ static sort * get_type(ast_manager & m, family_id datatype_fid, sort * source_da
|
|||
}
|
||||
}
|
||||
|
||||
func_decl * datatype_decl_plugin::mk_update_field(
|
||||
unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
decl_kind k = OP_DT_UPDATE_FIELD;
|
||||
ast_manager& m = *m_manager;
|
||||
|
||||
if (num_parameters != 1 || !parameters[0].is_ast()) {
|
||||
m.raise_exception("invalid parameters for datatype field update");
|
||||
return 0;
|
||||
}
|
||||
if (arity != 2) {
|
||||
m.raise_exception("invalid number of arguments for datatype field update");
|
||||
return 0;
|
||||
}
|
||||
func_decl* acc = 0;
|
||||
if (is_func_decl(parameters[0].get_ast())) {
|
||||
acc = to_func_decl(parameters[0].get_ast());
|
||||
}
|
||||
if (acc && !get_util().is_accessor(acc)) {
|
||||
acc = 0;
|
||||
}
|
||||
if (!acc) {
|
||||
m.raise_exception("datatype field update requires a datatype accessor as the second argument");
|
||||
return 0;
|
||||
}
|
||||
sort* dom = acc->get_domain(0);
|
||||
sort* rng = acc->get_range();
|
||||
if (dom != domain[0]) {
|
||||
m.raise_exception("first argument to field update should be a data-type");
|
||||
return 0;
|
||||
}
|
||||
if (rng != domain[1]) {
|
||||
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());
|
||||
return 0;
|
||||
}
|
||||
range = domain[0];
|
||||
func_decl_info info(m_family_id, k, num_parameters, parameters);
|
||||
return m.mk_func_decl(symbol("update_field"), arity, domain, range, info);
|
||||
}
|
||||
|
||||
func_decl * datatype_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
|
||||
if (k == OP_DT_UPDATE_FIELD) {
|
||||
return mk_update_field(num_parameters, parameters, arity, domain, range);
|
||||
}
|
||||
if (num_parameters < 2 || !parameters[0].is_ast() || !is_sort(parameters[0].get_ast())) {
|
||||
m_manager->raise_exception("invalid parameters for datatype operator");
|
||||
return 0;
|
||||
|
@ -521,20 +568,9 @@ func_decl * datatype_decl_plugin::mk_func_decl(decl_kind k, unsigned num_paramet
|
|||
return m_manager->mk_func_decl(a_name, arity, domain, a_type, info);
|
||||
}
|
||||
break;
|
||||
case OP_DT_UPDATE_FIELD:
|
||||
if (num_parameters != 2 || arity != 2 || domain[0] != datatype) {
|
||||
m_manager->raise_exception("invalid parameters for datatype field update");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
symbol con_name = parameters[0].get_symbol();
|
||||
symbol acc_name = parameters[1].get_symbol();
|
||||
func_decl_info info(m_family_id, k, num_parameters, parameters);
|
||||
info.m_private_parameters = true;
|
||||
SASSERT(info.private_parameters());
|
||||
return m_manager->mk_func_decl(symbol("update_field"), arity, domain, datatype, info);
|
||||
}
|
||||
|
||||
case OP_DT_UPDATE_FIELD:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
default:
|
||||
m_manager->raise_exception("invalid datatype operator kind");
|
||||
return 0;
|
||||
|
@ -687,12 +723,9 @@ bool datatype_decl_plugin::is_value(app * e) const {
|
|||
}
|
||||
|
||||
void datatype_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
|
||||
#if 0
|
||||
// disabled
|
||||
if (logic == symbol::null) {
|
||||
op_names.push_back(builtin_name("update_field", OP_DT_UPDATE_FIELD));
|
||||
op_names.push_back(builtin_name("update-field", OP_DT_UPDATE_FIELD));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -154,6 +154,10 @@ public:
|
|||
|
||||
private:
|
||||
bool is_value_visit(expr * arg, ptr_buffer<app> & todo) const;
|
||||
|
||||
func_decl * mk_update_field(
|
||||
unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
};
|
||||
|
||||
class datatype_util {
|
||||
|
@ -184,9 +188,11 @@ public:
|
|||
bool is_constructor(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_CONSTRUCTOR); }
|
||||
bool is_recognizer(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_RECOGNISER); }
|
||||
bool is_accessor(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_ACCESSOR); }
|
||||
bool is_update_field(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_UPDATE_FIELD); }
|
||||
bool is_constructor(app * f) const { return is_app_of(f, m_family_id, OP_DT_CONSTRUCTOR); }
|
||||
bool is_recognizer(app * f) const { return is_app_of(f, m_family_id, OP_DT_RECOGNISER); }
|
||||
bool is_accessor(app * f) const { return is_app_of(f, m_family_id, OP_DT_ACCESSOR); }
|
||||
bool is_update_field(app * f) const { return is_app_of(f, m_family_id, OP_DT_UPDATE_FIELD); }
|
||||
ptr_vector<func_decl> const * get_datatype_constructors(sort * ty);
|
||||
unsigned get_datatype_num_constructors(sort * ty) { return get_datatype_constructors(ty)->size(); }
|
||||
unsigned get_constructor_idx(func_decl * f) const { SASSERT(is_constructor(f)); return f->get_parameter(1).get_int(); }
|
||||
|
|
|
@ -60,6 +60,32 @@ br_status datatype_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr
|
|||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
case OP_DT_UPDATE_FIELD: {
|
||||
SASSERT(num_args == 2);
|
||||
if (!is_app(args[0]) || !m_util.is_constructor(to_app(args[0])))
|
||||
return BR_FAILED;
|
||||
app * a = to_app(args[0]);
|
||||
func_decl * c_decl = a->get_decl();
|
||||
if (c_decl != m_util.get_accessor_constructor(f)) {
|
||||
result = a;
|
||||
return BR_DONE;
|
||||
}
|
||||
ptr_vector<func_decl> const * acc = m_util.get_constructor_accessors(c_decl);
|
||||
SASSERT(acc && acc->size() == a->get_num_args());
|
||||
unsigned num = acc->size();
|
||||
ptr_buffer<expr> new_args;
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
|
||||
if (f == (*acc)[i]) {
|
||||
new_args.push_back(args[1]);
|
||||
}
|
||||
else {
|
||||
new_args.push_back(a->get_arg(i));
|
||||
}
|
||||
}
|
||||
result = m().mk_app(c_decl, num, new_args.c_ptr());
|
||||
return BR_DONE;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
|
|
@ -81,6 +81,8 @@ bool datatype_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr *
|
|||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
case OP_DT_UPDATE_FIELD:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue