use crate::flow::comparator::*; use crate::func::context::*; use super::{binary::*, *}; #[derive(Clone)] struct Bounds { l: Option, r: Option, } pub enum BoundsError { BoundsViolated { l: A, r: A }, CannotJoin(A), } pub enum BoundError { Avl(AvlError), Bounds(BoundsError), } impl From> for BoundError { fn from(value: AvlError) -> Self { Self::Avl(value) } } impl From> for BoundError { fn from(value: BoundsError) -> Self { Self::Bounds(value) } } pub type BoundErrorA<'a, Ctx, A> = BoundError>>; pub type BoundResult<'a, Ctx, A, T> = Result>; pub type BoundNodeResult<'a, Ctx, A> = BoundResult<'a, Ctx, A, BoundNode<'a, Ctx, A>>; pub type BoundTreeResult<'a, Ctx, A> = BoundResult<'a, Ctx, A, BoundTree<'a, Ctx, A>>; pub struct BoundTree<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { tree: AvlTree<'a, Ctx, A>, bounds: Bounds, } pub struct BoundNode<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { l: BoundTree<'a, Ctx, A>, r: BoundTree<'a, Ctx, A>, key: A, bounds: Bounds, } pub struct BoundReference<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { reference: AvlReference<'a, Ctx, A>, bounds: Bounds, } impl Bounds { fn unbound() -> Self { Bounds { l: None, r: None } } fn ordered(l: &A, r: &A, comparator: &impl Comparator) -> Result<(), BoundsError> { if let Comparison::R = comparator.pick_smaller(l, r) { Err(BoundsError::BoundsViolated { l: l.clone(), r: r.clone(), }) } else { Ok(()) } } fn new( l: Option, r: Option, comparator: &impl Comparator, ) -> Result> { if let (Some(kl), Some(kr)) = (&l, &r) { Self::ordered(kl, kr, comparator)? } Ok(Bounds { l, r }) } fn split( self, key: &A, comparator: &impl Comparator, ) -> Result<(Self, Self), BoundsError> { Ok(( Self::new(self.l, Some(key.clone()), comparator)?, Self::new(Some(key.clone()), self.r, comparator)?, )) } fn join( l: Self, r: Self, key: &A, comparator: &impl Comparator, ) -> Result> { if let Some(lr) = &l.r { Self::ordered(lr, key, comparator)? } else { Err(BoundsError::CannotJoin(key.clone()))? } if let Some(rl) = &r.l { Self::ordered(key, rl, comparator)? } else { Err(BoundsError::CannotJoin(key.clone()))? } Self::new(l.l, r.r, comparator) } pub fn equal_bound(l: &Option, r: &Option, comparator: &impl Comparator) -> bool { match (l, r) { (None, None) => true, (Some(kl), Some(kr)) => matches!(comparator.pick_smaller(kl, kr), Comparison::E), _ => false, } } pub fn equal(bl: &Self, br: &Self, comparator: &impl Comparator) -> bool { Self::equal_bound(&bl.l, &br.l, comparator) && Self::equal_bound(&bl.r, &br.r, comparator) } } pub type BoundSplit<'a, Ctx, A> = (BoundTree<'a, Ctx, A>, BoundTree<'a, Ctx, A>, A); impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone> BoundNode<'a, Ctx, A> { pub fn into_tree(self) -> BoundTreeResult<'a, Ctx, A> { let tree = AvlNode::new(self.l.tree, self.r.tree, self.key)?.into_tree()?; let bounds = self.bounds; Ok(BoundTree { tree, bounds }) } pub fn into_tree_resolution(self) -> BrTree<'a, Ctx, A> { match self.into_tree() { Ok(tree) => Ctx::pure(Ok(tree)), Err(e) => Ctx::pure(Err(ResolutionError::Parse(e))), } } pub fn new( l: BoundTree<'a, Ctx, A>, r: BoundTree<'a, Ctx, A>, key: A, comparator: &impl Comparator, ) -> BoundNodeResult<'a, Ctx, A> { let bounds = Bounds::join(l.bounds.clone(), r.bounds.clone(), &key, comparator)?; Ok(Self { l, r, key, bounds }) } pub fn split(&self) -> BoundSplit<'a, Ctx, A> { (self.l.clone(), self.r.clone(), self.key.clone()) } } pub type BoundKeySplit<'a, Ctx, A> = (BoundTree<'a, Ctx, A>, BoundTree<'a, Ctx, A>); impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone> BoundTree<'a, Ctx, A> { pub fn height(&self) -> u64 { self.tree.height } pub fn empty(factory: Fctr<'a, Ctx, A>) -> Self { Self { tree: AvlTree::empty(factory), bounds: Bounds::unbound(), } } fn empty_bound(factory: Fctr<'a, Ctx, A>, bounds: Bounds) -> Self { Self { tree: AvlTree::empty(factory), bounds, } } pub fn reference(&self) -> Option> { let reference = self.tree.reference()?; let bounds = self.bounds.clone(); Some(BoundReference { reference, bounds }) } fn split_empty( bounds: Bounds, key: &A, factory: &Fctr<'a, Ctx, A>, comparator: &impl Comparator, ) -> Result<(Self, Self), BoundsError> { let (bl, br) = bounds.split(key, comparator)?; Ok(( Self::empty_bound(factory.clone(), bl), Self::empty_bound(factory.clone(), br), )) } pub fn split_empty_res( self, key: A, factory: Fctr<'a, Ctx, A>, comparator: Rc>, ) -> BrKeySplit<'a, Ctx, A> { Ctx::pure( Self::split_empty(self.bounds, &key, &factory, comparator.as_ref()) .map_err(BoundError::Bounds) .map_err(ResolutionError::Parse), ) } } impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone> Clone for BoundTree<'a, Ctx, A> { fn clone(&self) -> Self { Self { tree: self.tree.clone(), bounds: self.bounds.clone(), } } } pub type BoundResolutionError<'a, Ctx, A> = ResolutionError<>::LookupError, BoundErrorA<'a, Ctx, A>>; pub type BoundResolutionResult<'a, Ctx, A, T> = Result>; pub type BoundResolution<'a, Ctx, A, T> = Wrapped<'a, Ctx, BoundResolutionResult<'a, Ctx, A, T>>; pub type BrNode<'a, Ctx, A> = BoundResolution<'a, Ctx, A, BoundNode<'a, Ctx, A>>; pub type BrTree<'a, Ctx, A> = BoundResolution<'a, Ctx, A, BoundTree<'a, Ctx, A>>; pub type BrKeySplit<'a, Ctx, A> = BoundResolution<'a, Ctx, A, BoundKeySplit<'a, Ctx, A>>; impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone> BoundReference<'a, Ctx, A> { pub fn resolve(&self, comparator: Rc>) -> BrNode<'a, Ctx, A> { let bounds = self.bounds.clone(); Ctx::fmap(self.reference.resolve(), move |resolved| { let node = resolved .map_err(|e| e.map_parse(BoundError::Avl))? .as_ref() .clone(); let (bl, br) = bounds .clone() .split(&node.key, comparator.as_ref()) .map_err(BoundError::Bounds) .map_err(ResolutionError::Parse)?; Ok(BoundNode { l: BoundTree { tree: node.l, bounds: bl, }, r: BoundTree { tree: node.r, bounds: br, }, key: node.key, bounds, }) }) } pub fn equal(rl: &Self, rr: &Self, comparator: &impl Comparator) -> bool { rl.reference == rr.reference && Bounds::equal(&rl.bounds, &rr.bounds, comparator) } }