/*++ 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 "ast/rewriter/th_rewriter.h" namespace recfun { class case_def; // cases; ast_manager & m_manager; symbol m_name; // 0); m_refcount --; } public: depth_limit_pred(ast_manager & m, family_id fid, unsigned d); unsigned get_depth() const { return m_depth; } symbol const & get_name() const { return m_name; } func_decl * get_decl() const { return m_decl.get(); } }; // A reference to `depth_limit_pred` typedef obj_ref depth_limit_pred_ref; namespace decl { class plugin : public decl_plugin { typedef map def_map; typedef map case_def_map; mutable scoped_ptr m_util; def_map m_defs; // function->def case_def_map m_case_defs; // case_pred->def svector m_def_block; ast_manager & m() { return *m_manager; } public: plugin(); virtual ~plugin() override; virtual void finalize() override; util & u() const; // build or return util virtual bool is_fully_interp(sort * s) const override { return false; } // might depend on unin sorts virtual decl_plugin * mk_fresh() override { return alloc(plugin); } virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override { UNREACHABLE(); return 0; } virtual 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); void set_definition(promise_def & d, unsigned n_vars, var * const * vars, expr * rhs); def* mk_def(symbol const& name, unsigned n, sort ** params, sort * range, unsigned n_vars, var ** vars, expr * rhs); bool has_def(const symbol& s) const { return m_defs.contains(s); } def const& get_def(const symbol& s) const { return *(m_defs[s]); } promise_def get_promise_def(const symbol &s) const { return promise_def(&u(), m_defs[s]); } def& get_def(symbol const& s) { return *(m_defs[s]); } bool has_case_def(const symbol& s) const { return m_case_defs.contains(s); } case_def& get_case_def(symbol const& s) { SASSERT(has_case_def(s)); return *(m_case_defs[s]); } bool is_declared(symbol const& s) const { return m_defs.contains(s); } private: func_decl * mk_fun_pred_decl(unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_fun_defined_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); }; } // Varus utils for recursive functions class util { friend class decl::plugin; typedef map> depth_limit_map; ast_manager & m_manager; family_id m_family_id; th_rewriter m_th_rw; decl::plugin * m_plugin; depth_limit_map m_dlimit_map; bool compute_is_immediate(expr * rhs); void set_definition(promise_def & d, unsigned n_vars, var * const * vars, expr * rhs); public: util(ast_manager &m, family_id); virtual ~util(); ast_manager & m() { return m_manager; } th_rewriter & get_th_rewriter() { return m_th_rw; } bool is_case_pred(app * e) const { return is_app_of(e, m_family_id, OP_FUN_CASE_PRED); } bool is_defined(app * e) const { return is_app_of(e, m_family_id, OP_FUN_DEFINED); } bool is_depth_limit(app * e) const { return is_app_of(e, m_family_id, OP_DEPTH_LIMIT); } bool owns_app(app * e) const { return e->get_family_id() == m_family_id; } //has_def(s)); return m_plugin->get_def(s); } case_def& get_case_def(symbol const & s) { SASSERT(m_plugin->has_case_def(s)); return m_plugin->get_case_def(s); } 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()); } app* mk_case_pred(case_pred const & p, ptr_vector const & args) { return m().mk_app(p.get_decl(), args.size(), args.c_ptr()); } void inc_ref(depth_limit_pred * p) { p->inc_ref(); } void dec_ref(depth_limit_pred * p) { p->dec_ref(); if (p->m_refcount == 0) { m_dlimit_map.remove(p->m_depth); dealloc(p); } } depth_limit_pred_ref get_depth_limit_pred(unsigned d); app_ref mk_depth_limit_pred(unsigned d); }; } typedef recfun::def recfun_def; typedef recfun::case_def recfun_case_def; typedef recfun::depth_limit_pred recfun_depth_limit_pred; typedef recfun::decl::plugin recfun_decl_plugin; typedef recfun::util recfun_util;