3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-24 20:16:00 +00:00
z3/src/ast/rewriter/recfun_rewriter.cpp
Nikolaj Bjorner b502126ebc fix #7634
2025-04-27 23:57:57 -07:00

81 lines
2.7 KiB
C++

/*++
Copyright (c) 2018 Microsoft Corporation
Module Name:
recfun_rewriter.cpp
Abstract:
Rewriter recursive function applications to values
Author:
Nikolaj Bjorner (nbjorner) 2020-04-26
--*/
#include "ast/rewriter/recfun_rewriter.h"
#include "ast/rewriter/var_subst.h"
#include "ast/datatype_decl_plugin.h"
#include "ast/for_each_expr.h"
br_status recfun_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
if (m_rec.is_defined(f) && num_args > 0) {
if (!m_rec.has_def(f))
return BR_FAILED;
recfun::def const& d = m_rec.get_def(f);
if (!d.get_rhs())
return BR_FAILED;
auto r = d.get_rhs();
bool safe_to_subst = true;
for (unsigned i = 0; i < num_args; ++i)
if (!m.is_value(args[i]))
safe_to_subst = false;
// check if there is an argument that is a constructor
// such that the recursive function can be partially evaluated.
// at most one kind of accessor is allowed to prevent recursive
// patterns that reconstruct the argument indirectly.
// This can be relaxed to omitting at least one accessor, and probably other patterns.
if (!safe_to_subst && !has_quantifiers(r)) {
datatype::util u(m);
auto is_decreasing = [&](unsigned i) {
bool is_dec = true;
unsigned idx = num_args - i - 1;
func_decl* dec_fun = nullptr;
for (auto t : subterms::all(expr_ref(r, m))) {
if (is_app(t) && any_of(*to_app(t), [&](expr* e) { return is_var(e) && to_var(e)->get_idx() == idx; })) {
if (!u.is_accessor(t) && !u.is_is(t) && !u.is_recognizer(t))
is_dec = false;
else if (u.is_accessor(t) && dec_fun && to_app(t)->get_decl() != dec_fun)
is_dec = false;
else if (u.is_accessor(t))
dec_fun = to_app(t)->get_decl();
}
}
return is_dec;
};
for (unsigned i = 0; i < num_args; ++i) {
auto arg = args[i];
if (u.is_constructor(arg) && is_decreasing(i)) {
safe_to_subst = true;
break;
}
}
}
if (safe_to_subst) {
var_subst sub(m);
result = sub(d.get_rhs(), num_args, args);
return BR_REWRITE_FULL;
}
return BR_FAILED;
}
else
return BR_FAILED;
}