use std::collections::HashSet;
use std::marker::PhantomData;
use crate::analysis::cpa::residue::Residue;
use crate::analysis::cpa::state::AbstractState;
pub struct TerminatingReducer<S>
where
S: AbstractState,
{
terminating_indices: HashSet<usize>,
_phantom: PhantomData<S>,
}
impl<S> Default for TerminatingReducer<S>
where
S: AbstractState,
{
fn default() -> Self {
Self {
terminating_indices: HashSet::new(),
_phantom: Default::default(),
}
}
}
impl<'a, S> Residue<'a, S> for TerminatingReducer<S>
where
S: AbstractState,
{
type Output = Vec<S>;
fn new_state(
&mut self,
source_idx: usize,
dest_idx: usize,
_op: &Option<crate::analysis::pcode_store::PcodeOpRef<'a>>,
) {
self.terminating_indices.remove(&source_idx);
self.terminating_indices.insert(dest_idx);
}
fn merged_state(
&mut self,
source_idx: usize,
_merged_idx: usize,
_op: &Option<crate::analysis::pcode_store::PcodeOpRef<'a>>,
) {
self.terminating_indices.remove(&source_idx);
}
fn new() -> Self {
Self::default()
}
fn finalize(self, reached: Vec<S>) -> Self::Output {
self.terminating_indices
.into_iter()
.map(|idx| reached[idx].clone())
.collect()
}
}
#[derive(Debug, Clone, Copy)]
pub struct TerminatingReducerFactory;
impl TerminatingReducerFactory {
pub const fn new() -> Self {
TerminatingReducerFactory
}
}
impl Default for TerminatingReducerFactory {
fn default() -> Self {
Self::new()
}
}
pub const TERMINATING: TerminatingReducerFactory = TerminatingReducerFactory;
impl<A> crate::analysis::cpa::residue::ReducerFactoryForState<A> for TerminatingReducerFactory
where
A: crate::analysis::cpa::ConfigurableProgramAnalysis,
A::State: crate::analysis::cpa::state::AbstractState,
{
type Reducer<'op> = TerminatingReducer<A::State>;
fn make<'op>(&self) -> Self::Reducer<'op> {
TerminatingReducer::default()
}
}