use std::fmt;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum ReductionKind {
Beta,
Delta,
Zeta,
Iota,
Eta,
Level,
}
impl fmt::Display for ReductionKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ReductionKind::Beta => write!(f, "beta"),
ReductionKind::Delta => write!(f, "delta"),
ReductionKind::Zeta => write!(f, "zeta"),
ReductionKind::Iota => write!(f, "iota"),
ReductionKind::Eta => write!(f, "eta"),
ReductionKind::Level => write!(f, "level"),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct ReductionStats {
pub beta_count: u64,
pub delta_count: u64,
pub zeta_count: u64,
pub iota_count: u64,
pub eta_count: u64,
pub level_count: u64,
pub total_steps: u64,
pub max_depth: u64,
current_depth: u64,
}
impl ReductionStats {
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn increment_beta(&mut self) {
self.beta_count += 1;
self.total_steps += 1;
}
#[inline]
pub fn increment_delta(&mut self) {
self.delta_count += 1;
self.total_steps += 1;
}
#[inline]
pub fn increment_zeta(&mut self) {
self.zeta_count += 1;
self.total_steps += 1;
}
#[inline]
pub fn increment_iota(&mut self) {
self.iota_count += 1;
self.total_steps += 1;
}
#[inline]
pub fn increment_eta(&mut self) {
self.eta_count += 1;
self.total_steps += 1;
}
#[inline]
pub fn increment_level(&mut self) {
self.level_count += 1;
self.total_steps += 1;
}
#[inline]
pub fn increment(&mut self, kind: ReductionKind) {
match kind {
ReductionKind::Beta => self.increment_beta(),
ReductionKind::Delta => self.increment_delta(),
ReductionKind::Zeta => self.increment_zeta(),
ReductionKind::Iota => self.increment_iota(),
ReductionKind::Eta => self.increment_eta(),
ReductionKind::Level => self.increment_level(),
}
}
#[inline]
pub fn push_depth(&mut self) {
self.current_depth += 1;
if self.current_depth > self.max_depth {
self.max_depth = self.current_depth;
}
}
#[inline]
pub fn pop_depth(&mut self) {
self.current_depth = self.current_depth.saturating_sub(1);
}
#[inline]
pub fn current_depth(&self) -> u64 {
self.current_depth
}
#[inline]
pub fn total(&self) -> u64 {
self.total_steps
}
pub fn count_for(&self, kind: ReductionKind) -> u64 {
match kind {
ReductionKind::Beta => self.beta_count,
ReductionKind::Delta => self.delta_count,
ReductionKind::Zeta => self.zeta_count,
ReductionKind::Iota => self.iota_count,
ReductionKind::Eta => self.eta_count,
ReductionKind::Level => self.level_count,
}
}
pub fn is_empty(&self) -> bool {
self.total_steps == 0
}
pub fn merge(&mut self, other: &ReductionStats) {
self.beta_count += other.beta_count;
self.delta_count += other.delta_count;
self.zeta_count += other.zeta_count;
self.iota_count += other.iota_count;
self.eta_count += other.eta_count;
self.level_count += other.level_count;
self.total_steps += other.total_steps;
if other.max_depth > self.max_depth {
self.max_depth = other.max_depth;
}
}
pub fn reset(&mut self) {
*self = Self::default();
}
pub fn snapshot(&self) -> ReductionStats {
self.clone()
}
pub fn delta_from(&self, snapshot: &ReductionStats) -> ReductionStats {
ReductionStats {
beta_count: self.beta_count.saturating_sub(snapshot.beta_count),
delta_count: self.delta_count.saturating_sub(snapshot.delta_count),
zeta_count: self.zeta_count.saturating_sub(snapshot.zeta_count),
iota_count: self.iota_count.saturating_sub(snapshot.iota_count),
eta_count: self.eta_count.saturating_sub(snapshot.eta_count),
level_count: self.level_count.saturating_sub(snapshot.level_count),
total_steps: self.total_steps.saturating_sub(snapshot.total_steps),
max_depth: self.max_depth,
current_depth: 0,
}
}
}
impl fmt::Display for ReductionStats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ReductionStats {{ total: {}, beta: {}, delta: {}, zeta: {}, iota: {}, eta: {}, level: {}, max_depth: {} }}",
self.total_steps,
self.beta_count,
self.delta_count,
self.zeta_count,
self.iota_count,
self.eta_count,
self.level_count,
self.max_depth,
)
}
}
pub struct ReductionSession {
snapshot: ReductionStats,
}
impl ReductionSession {
pub fn begin(stats: &ReductionStats) -> Self {
Self {
snapshot: stats.snapshot(),
}
}
pub fn finish(self, current: &ReductionStats) -> ReductionStats {
current.delta_from(&self.snapshot)
}
}
pub struct DepthGuard<'a> {
stats: &'a mut ReductionStats,
}
impl<'a> DepthGuard<'a> {
pub fn new(stats: &'a mut ReductionStats) -> Self {
stats.push_depth();
Self { stats }
}
}
impl Drop for DepthGuard<'_> {
fn drop(&mut self) {
self.stats.pop_depth();
}
}