ssa_traits/
op.rs

1use either::Either;
2
3use crate::{Func, HasValues};
4
5pub trait OpValue<F: Func, O>: Sized {
6    type Residue;
7    type Capture: HasValues<F>;
8    type Spit;
9    fn disasm(self, f: &mut F) -> Result<(O, Self::Capture, Self::Spit), Self::Residue>;
10    fn of(f: &mut F, o: O, c: Self::Capture, s: Self::Spit) -> Option<Self>;
11    fn lift(f: &mut F, r: Self::Residue) -> Option<Self>;
12}
13
14impl<F: Func, A, B, T: OpValue<F, A, Residue: OpValue<F, B>>> OpValue<F, Either<A, B>> for T {
15    type Residue = <T::Residue as OpValue<F, B>>::Residue;
16
17    type Capture = Either<T::Capture, <T::Residue as OpValue<F, B>>::Capture>;
18
19    type Spit = Either<T::Spit, <T::Residue as OpValue<F, B>>::Spit>;
20
21    fn disasm(self, f: &mut F) -> Result<(Either<A, B>, Self::Capture, Self::Spit), Self::Residue> {
22        match self.disasm(f) {
23            Ok((a, b, c)) => Ok((Either::Left(a), Either::Left(b), Either::Left(c))),
24            Err(d) => match d.disasm(f) {
25                Err(e) => Err(e),
26                Ok((a, b, c)) => Ok((Either::Right(a), Either::Right(b), Either::Right(c))),
27            },
28        }
29    }
30
31    fn of(f: &mut F, o: Either<A, B>, c: Self::Capture, s: Self::Spit) -> Option<T> {
32        match (o, c, s) {
33            (Either::Left(o), Either::Left(c), Either::Left(s)) => {
34                <T as OpValue<F, A>>::of(f, o, c, s)
35            }
36            (Either::Right(o), Either::Right(c), Either::Right(s)) => {
37                <T::Residue as OpValue<F, B>>::of(f, o, c, s)
38                    .and_then(|b| <T as OpValue<F, A>>::lift(f, b))
39            }
40            _ => None,
41        }
42    }
43
44    fn lift(f: &mut F, r: Self::Residue) -> Option<T> {
45        <T::Residue as OpValue<F, B>>::lift(f, r).and_then(|b| <T as OpValue<F, A>>::lift(f, b))
46    }
47}