/*++ Copyright (c) 2017 Microsoft Corporation, Simon Cruanes Module Name: recfun_decl_plugin.h Abstract: Declaration and definition of (potentially recursive) functions Author: Simon Cruanes 2017-11 Revision History: --*/ #pragma once #include "ast/ast.h" #include "util/obj_hashtable.h" namespace recfun { class case_def; // const & args) const { ast_manager& m = m_pred.get_manager(); return app_ref(m.mk_app(m_pred, args.size(), args.c_ptr()), m); } def * get_def() const { return m_def; } expr_ref_vector const & get_guards() const { return m_guards; } expr * get_guards_c_ptr() const { return *m_guards.c_ptr(); } expr * get_guard(unsigned i) const { return m_guards[i]; } expr * get_rhs() const { return m_rhs; } unsigned num_guards() const { return m_guards.size(); } bool is_immediate() const { return m_immediate; }; void set_is_immediate(bool b) { m_immediate = b; } }; // closure for computing whether a `rhs` expression is immediate struct is_immediate_pred { virtual bool operator()(expr * rhs) = 0; }; class def { friend class util; friend class promise_def; typedef vector cases; ast_manager & m; symbol m_name; // def_map; typedef obj_map case_def_map; mutable scoped_ptr m_util; def_map m_defs; // function->def case_def_map m_case_defs; // case_pred->def ast_manager & m() { return *m_manager; } public: plugin(); ~plugin() override; void finalize() override; util & u() const; // build or return util bool is_fully_interp(sort * s) const override { return false; } // might depend on unin sorts decl_plugin * mk_fresh() override { return alloc(plugin); } sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override { UNREACHABLE(); return nullptr; } func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) override; promise_def mk_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated = false); promise_def ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated = false); void set_definition(replace& r, promise_def & d, unsigned n_vars, var * const * vars, expr * rhs); def* mk_def(replace& subst, symbol const& name, unsigned n, sort ** params, sort * range, unsigned n_vars, var ** vars, expr * rhs); bool has_def(func_decl* f) const { return m_defs.contains(f); } bool has_defs() const; def const& get_def(func_decl* f) const { return *(m_defs[f]); } promise_def get_promise_def(func_decl* f) const { return promise_def(&u(), m_defs[f]); } def& get_def(func_decl* f) { return *(m_defs[f]); } bool has_case_def(func_decl* f) const { return m_case_defs.contains(f); } case_def& get_case_def(func_decl* f) { SASSERT(has_case_def(f)); return *(m_case_defs[f]); } func_decl_ref_vector get_rec_funs() { func_decl_ref_vector result(m()); for (auto& kv : m_defs) result.push_back(kv.m_key); return result; } }; } // Various utils for recursive functions class util { friend class decl::plugin; ast_manager & m_manager; family_id m_fid; decl::plugin * m_plugin; bool compute_is_immediate(expr * rhs); void set_definition(replace& r, promise_def & d, unsigned n_vars, var * const * vars, expr * rhs); public: util(ast_manager &m); ~util(); ast_manager & m() { return m_manager; } decl::plugin& get_plugin() { return *m_plugin; } bool is_case_pred(expr * e) const { return is_app_of(e, m_fid, OP_FUN_CASE_PRED); } bool is_defined(expr * e) const { return is_app_of(e, m_fid, OP_FUN_DEFINED); } bool is_defined(func_decl* f) const { return is_decl_of(f, m_fid, OP_FUN_DEFINED); } bool is_generated(func_decl* f) const { return is_defined(f) && f->get_parameter(0).get_int() == 1; } bool is_depth_limit(expr * e) const { return is_app_of(e, m_fid, OP_DEPTH_LIMIT); } bool owns_app(app * e) const { return e->get_family_id() == m_fid; } //has_defs(); } //has_def(f)); return m_plugin->get_def(f); } case_def& get_case_def(expr* e) { SASSERT(is_case_pred(e)); return m_plugin->get_case_def(to_app(e)->get_decl()); } app* mk_fun_defined(def const & d, unsigned n_args, expr * const * args) { return m().mk_app(d.get_decl(), n_args, args); } app* mk_fun_defined(def const & d, ptr_vector const & args) { return mk_fun_defined(d, args.size(), args.c_ptr()); } func_decl_ref_vector get_rec_funs() { return m_plugin->get_rec_funs(); } app_ref mk_depth_limit_pred(unsigned d); }; }