3
0
Fork 0
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:
Nikolaj Bjorner 2015-01-03 01:27:52 -08:00
parent a296023823
commit 129e048a1b
10 changed files with 221 additions and 24 deletions

View file

@ -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
}

View file

@ -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(); }

View file

@ -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();
}

View file

@ -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();
}