#pragma once
#include <optional>
#include <string>
#include "ast/ast.h"
#include "util/map.h"
#include "util/vector.h"
namespace spacer {
class sym_mux {
private:
class sym_mux_entry {
public:
func_decl_ref m_main;
func_decl_ref_vector m_variants;
sym_mux_entry(ast_manager &m) : m_main(m), m_variants(m) {}
};
typedef obj_map<func_decl, sym_mux_entry*> decl2entry_map;
typedef obj_map<func_decl, std::pair<sym_mux_entry*, unsigned> > mux2entry_map;
ast_manager &m;
mutable decl2entry_map m_entries;
mutable mux2entry_map m_muxes;
func_decl_ref mk_variant(func_decl *fdecl, unsigned i) const;
void ensure_capacity(sym_mux_entry &entry, unsigned sz) const;
public:
sym_mux(ast_manager & m);
~sym_mux();
ast_manager & get_manager() const { return m; }
void register_decl(func_decl *fdecl);
std::optional<unsigned> find_idx(func_decl * sym) const;
bool has_index(func_decl * sym, unsigned idx) const
{auto v = find_idx(sym); return v && *v == idx;}
bool is_muxed(func_decl *fdecl) const {return m_muxes.contains(fdecl);}
func_decl * find_by_decl(func_decl* fdecl, unsigned idx) const;
bool is_homogenous_formula(expr * e, unsigned idx) const;
func_decl * shift_decl(func_decl * sym, unsigned src_idx, unsigned tgt_idx) const;
void shift_expr(expr * f, unsigned src_idx, unsigned tgt_idx,
expr_ref & res, bool homogenous = true) const;
};
}