use std::rc::Rc; use crate::core::*; use crate::func::*; struct WrappedOrigin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> { w_factory: A::Fctr, w_resolve: Box Resolution<'a, Ctx, A>>, } pub fn wrapped_origin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>>( factory: A::Fctr, resolve: impl 'a + Fn() -> Resolution<'a, Ctx, A>, ) -> Rc> { Rc::new(WrappedOrigin { w_factory: factory, w_resolve: Box::new(resolve), }) } trait MappableOrigin<'a, Ctx: 'a + Context>: Origin<'a, Ctx> { fn map>( self: Rc, map_ok: impl 'a + Clone + Fn(Rc) -> B, map_err: impl 'a + Clone + Fn( <>::Fctr as Factory<'a, Ctx>>::ParseError, ) -> >::ParseError, map_factory: impl 'a + FnOnce(>::Fctr) -> B::Fctr, ) -> WrappedOrigin<'a, Ctx, B>; } fn map_resolve<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>, B: Mentionable<'a, Ctx>>( resolve: impl 'a + Fn() -> Resolution<'a, Ctx, A>, map_ok: impl 'a + Fn(Rc) -> B, map_err: impl 'a + Fn(>::ParseError) -> >::ParseError, ) -> Resolution<'a, Ctx, B> { Ctx::T::fmap( move |resolved| match resolved { Ok(mentionable) => Ok(Rc::new(map_ok(mentionable))), Err(ResolutionError::Parse(parse_error)) => { Err(ResolutionError::Parse(map_err(parse_error))) } Err(ResolutionError::Lookup(lookup_error)) => { Err(ResolutionError::Lookup(lookup_error)) } }, resolve(), ) } impl<'a, Ctx: 'a + Context, O: ?Sized + Origin<'a, Ctx>> MappableOrigin<'a, Ctx> for O { fn map>( self: Rc, map_ok: impl 'a + Clone + Fn(Rc) -> B, map_err: impl 'a + Clone + Fn( <>::Fctr as Factory<'a, Ctx>>::ParseError, ) -> >::ParseError, map_factory: impl 'a + FnOnce(>::Fctr) -> B::Fctr, ) -> WrappedOrigin<'a, Ctx, B> { let origin = self.clone(); WrappedOrigin { w_factory: map_factory(self.factory()), w_resolve: Box::new(move || { let origin = origin.clone(); let map_ok = map_ok.clone(); let map_err = map_err.clone(); map_resolve(move || origin.clone().resolve(), map_ok, map_err) }), } } } impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for WrappedOrigin<'a, Ctx, A> { type Mtbl = A; fn factory(&self) -> >::Fctr { self.w_factory.clone() } fn resolve(self: Rc) -> Resolution<'a, Ctx, A> { (self.w_resolve)() } } impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { /// Typeless version of the point. Useful for [Mentionable::points] implementaion. pub fn typeless(&self) -> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> { Point { point: self.point, origin: Rc::new(self.origin.clone().map( TypelessMentionable::from_typed, TypelessError::from_typed, TypelessFactory::from_typed, )), } } }