#pragma once
#include <optional>
#include "ast/ast.h"
#include "util/map.h"
#include "util/uint_set.h"
#include "ast/rewriter/var_subst.h"
class counter {
protected:
typedef u_map<int> map_impl;
map_impl m_data;
public:
typedef map_impl::iterator iterator;
void reset() { m_data.reset(); }
iterator begin() const { return m_data.begin(); }
iterator end() const { return m_data.end(); }
void update(unsigned el, int delta);
int & get(unsigned el);
counter & count(unsigned sz, const unsigned * els, int delta = 1);
counter & count(const unsigned_vector & els, int delta = 1) {
return count(els.size(), els.data(), delta);
}
void collect_positive(uint_set & acc) const;
unsigned get_positive_count() const;
std::optional<unsigned> get_max_positive() const;
unsigned get_max_positive_or_zero() const;
int get_max_counter_value() const;
};
class var_counter : public counter {
protected:
expr_fast_mark1 m_visited;
expr_free_vars m_fv;
ptr_vector<expr> m_todo;
unsigned_vector m_scopes;
unsigned get_max_var(bool & has_var);
public:
void count_vars(const app * t, int coef = 1);
unsigned get_max_var(expr* e);
unsigned get_next_var(expr* e);
};
class ast_counter {
typedef obj_map<ast, int> map_impl;
map_impl m_data;
public:
typedef map_impl::iterator iterator;
iterator begin() const { return m_data.begin(); }
iterator end() const { return m_data.end(); }
int & get(ast * el) {
return m_data.insert_if_not_there(el, 0);
}
void update(ast * el, int delta){
get(el) += delta;
}
void inc(ast * el) { update(el, 1); }
void dec(ast * el) { update(el, -1); }
};