use crate::expr::{Context, ExprMap, ExprRef, ForEachChild, SparseExprMap, traversal};
use rustc_hash::FxHashSet;
pub type UseCountInt = u16;
pub fn count_expr_uses(ctx: &Context, roots: Vec<ExprRef>) -> impl ExprMap<UseCountInt> {
let mut use_count = SparseExprMap::default();
let mut todo = roots;
for expr in todo.iter() {
use_count[*expr] = 1;
}
while let Some(expr) = todo.pop() {
update_expr_child_uses(ctx, expr, &mut use_count, &mut todo);
}
use_count
}
pub fn find_symbols(ctx: &Context, e: ExprRef) -> FxHashSet<ExprRef> {
let mut out = FxHashSet::default();
traversal::bottom_up(ctx, e, |ctx, e, _| {
if ctx[e].is_symbol() {
out.insert(e);
}
});
out
}
#[inline]
pub fn update_expr_child_uses(
ctx: &Context,
expr: ExprRef,
use_count: &mut impl ExprMap<UseCountInt>,
todo: &mut Vec<ExprRef>,
) {
ctx[expr].for_each_child(|child| {
let count = use_count[*child];
let is_first_use = count == 0;
use_count[*child] = count.saturating_add(1);
if is_first_use {
todo.push(*child);
}
});
}