diff --git a/src/ast/recfun_decl_plugin.cpp b/src/ast/recfun_decl_plugin.cpp index ba1b4f171..b920eaa89 100644 --- a/src/ast/recfun_decl_plugin.cpp +++ b/src/ast/recfun_decl_plugin.cpp @@ -64,17 +64,30 @@ namespace recfun { m_decl = m.mk_func_decl(s, arity, domain, range, info); } + bool def::contains_def(util& u, expr * e) { + struct def_find_p : public i_expr_pred { + util& u; + def_find_p(util& u): u(u) {} + bool operator()(expr* a) override { return is_app(a) && u.is_defined(to_app(a)->get_decl()); } + }; + def_find_p p(u); + check_pred cp(p, m, false); + return cp(e); + } + // does `e` contain any `ite` construct? - bool def::contains_ite(expr * e) { + bool def::contains_ite(util& u, expr * e) { struct ite_find_p : public i_expr_pred { ast_manager & m; - ite_find_p(ast_manager & m) : m(m) {} - bool operator()(expr * e) override { return m.is_ite(e); } + def& d; + util& u; + ite_find_p(ast_manager & m, def& d, util& u) : m(m), d(d), u(u) {} + bool operator()(expr * e) override { return m.is_ite(e) && d.contains_def(u, e); } }; // ignore ites under quantifiers. // this is redundant as the code // that unfolds ites uses quantifier-free portion. - ite_find_p p(m); + ite_find_p p(m, *this, u); check_pred cp(p, m, false); return cp(e); } @@ -189,7 +202,8 @@ namespace recfun { // Compute a set of cases, given the RHS - void def::compute_cases(replace& subst, + void def::compute_cases(util& u, + replace& subst, is_immediate_pred & is_i, unsigned n_vars, var *const * vars, expr* rhs) { @@ -209,7 +223,7 @@ namespace recfun { expr_ref_vector conditions(m); // is the function a macro (unconditional body)? - if (n_vars == 0 || !contains_ite(rhs)) { + if (n_vars == 0 || !contains_ite(u, rhs)) { // constant function or trivial control flow, only one (dummy) case add_case(name, 0, conditions, rhs); return; @@ -248,7 +262,7 @@ namespace recfun { else if (is_app(e)) { // explore arguments for (expr * arg : *to_app(e)) { - if (contains_ite(arg)) { + if (contains_ite(u, arg)) { stack.push_back(arg); } } @@ -361,7 +375,7 @@ namespace recfun { SASSERT(n_vars == d->get_arity()); is_imm_pred is_i(*u); - d->compute_cases(r, is_i, n_vars, vars, rhs); + d->compute_cases(*u, r, is_i, n_vars, vars, rhs); } namespace decl { diff --git a/src/ast/recfun_decl_plugin.h b/src/ast/recfun_decl_plugin.h index 786ea9dd2..90de7e0a0 100644 --- a/src/ast/recfun_decl_plugin.h +++ b/src/ast/recfun_decl_plugin.h @@ -111,10 +111,11 @@ namespace recfun { def(ast_manager &m, family_id fid, symbol const & s, unsigned arity, sort *const * domain, sort* range, bool is_generated); // compute cases for a function, given its RHS (possibly containing `ite`). - void compute_cases(replace& subst, is_immediate_pred &, + void compute_cases(util& u, replace& subst, is_immediate_pred &, unsigned n_vars, var *const * vars, expr* rhs); void add_case(std::string & name, unsigned case_index, expr_ref_vector const& conditions, expr* rhs, bool is_imm = false); - bool contains_ite(expr* e); // expression contains a test? + bool contains_ite(util& u, expr* e); // expression contains a test? + bool contains_def(util& u, expr* e); // expression contains a def public: symbol const & get_name() const { return m_name; } vars const & get_vars() const { return m_vars; }