#pragma once
#include "ast/rewriter/rewriter.h"
#include "ast/used_vars.h"
#include "util/params.h"
typedef var_shifter shift_vars;
class var_subst {
beta_reducer m_reducer;
bool m_std_order;
public:
var_subst(ast_manager & m, bool std_order = true):m_reducer(m), m_std_order(std_order) {}
bool std_order() const { return m_std_order; }
expr_ref operator()(expr * n, unsigned num_args, expr * const * args);
inline expr_ref operator()(expr* n, expr* arg) { return (*this)(n, 1, &arg); }
inline expr_ref operator()(expr * n, expr_ref_vector const& args) { return (*this)(n, args.size(), args.data()); }
inline expr_ref operator()(expr * n, var_ref_vector const& args) { return (*this)(n, args.size(), (expr*const*)args.data()); }
inline expr_ref operator()(expr * n, app_ref_vector const& args) { return (*this)(n, args.size(), (expr*const*)args.data()); }
inline expr_ref operator()(expr * n, ptr_vector<expr> const& args) { return (*this)(n, args.size(), args.data()); }
void reset() { m_reducer.reset(); }
};
class unused_vars_eliminator {
ast_manager & m;
var_subst m_subst;
used_vars m_used;
params_ref m_params;
bool m_ignore_patterns_on_ground_qbody;
public:
unused_vars_eliminator(ast_manager & m, params_ref const & params);
expr_ref operator()(quantifier* q);
};
expr_ref elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params);
expr_ref instantiate(ast_manager & m, quantifier * q, expr * const * exprs);
class expr_free_vars {
expr_sparse_mark m_mark;
ptr_vector<sort> m_sorts;
ptr_vector<expr> m_todo;
public:
expr_free_vars() = default;
expr_free_vars(expr* e) { (*this)(e); }
void reset();
void operator()(expr* e);
void accumulate(expr* e);
bool empty() const { return m_sorts.empty(); }
unsigned size() const { return m_sorts.size(); }
sort* operator[](unsigned idx) const { return m_sorts[idx]; }
bool contains(unsigned idx) const { return idx < m_sorts.size() && m_sorts[idx] != 0; }
void set_default_sort(sort* s);
void reverse() { m_sorts.reverse(); }
sort*const* data() const { return m_sorts.data(); }
};