use std::marker::PhantomData;
use crate::analysis::pcode_store::PcodeOpRef;
use crate::analysis::cpa::{ConfigurableProgramAnalysis, state::AbstractState};
pub trait Residue<S> {
type Output;
fn new_state(&mut self, _state: &S, _dest_state: &S, _op: &Option<PcodeOpRef<'_>>) {}
fn merged_state(
&mut self,
_curr_state: &S,
_original_merged_state: &S,
_merged_state: &S,
_op: &Option<PcodeOpRef<'_>>,
) {
}
fn new() -> Self;
fn finalize(self) -> Self::Output;
}
pub struct EmptyResidue<T>(PhantomData<T>);
impl<T: AbstractState> Residue<T> for EmptyResidue<T> {
type Output = ();
fn new() -> Self {
Self(Default::default())
}
fn finalize(self) -> Self::Output {}
}
pub struct ResidueWrapper<A: ConfigurableProgramAnalysis, R: Residue<A::State>> {
a: A,
_phantom: PhantomData<R>,
}
impl<A: ConfigurableProgramAnalysis, R: Residue<A::State>> ResidueWrapper<A, R> {
pub fn wrap(a: A, _r: R) -> Self {
Self {
a,
_phantom: Default::default(),
}
}
}
impl<A: ConfigurableProgramAnalysis, R: Residue<A::State>> ConfigurableProgramAnalysis
for ResidueWrapper<A, R>
{
type State = A::State;
type Reducer = R;
}
impl<T, A, R> crate::analysis::cpa::IntoState<ResidueWrapper<A, R>> for T
where
A: crate::analysis::cpa::ConfigurableProgramAnalysis,
R: Residue<A::State>,
T: crate::analysis::cpa::IntoState<A> + Clone,
{
fn into_state(
self,
c: &ResidueWrapper<A, R>,
) -> <ResidueWrapper<A, R> as crate::analysis::cpa::ConfigurableProgramAnalysis>::State {
self.into_state(&c.a)
}
}