use core::any::type_name; use crate::any::type_name::{Lowered, Raised}; use crate::any::{BorrowedStatic, MutAnyUnsized, OwnedStatic}; use crate::protocol::DynWalker; use effectful::effective::Canonical; use effectful::{DynBind, Effective, Environment, SendSync}; use crate::protocol::visitor::{request_hint, visit_value, RequestHint, Value, VisitResult}; use crate::trait_by_id; use crate::{ any::AnyTrait, build::BuilderTypes, hkt::Marker, protocol::{AsVisitor, DynVisitor}, Builder, }; #[derive(SendSync)] pub struct Tracer { inner: B, _env: Marker, } impl BuilderTypes for Tracer where B: BuilderTypes, { type Seed = B::Seed; type Error = B::Error; type Output = B::Output; type Value = B::Value; fn unwrap_output(output: Self::Output) -> Self::Value { println!("Unwrapped output value"); B::unwrap_output(output) } } impl<'src, B, E: Environment> Builder<'src, E> for Tracer where B: Builder<'src, E>, { fn from_seed<'u>(seed: Self::Seed) -> effectful::effective::Canonical<'u, Self, E> where Self: 'u, { println!("Created builder from seed value: {}", type_name::()); B::from_seed(seed) .map((), |_, b| Self { inner: b, _env: Marker::NEW, }) .cast() } fn build<'u>(self) -> effectful::effective::Canonical<'u, Result, E> where Self: 'u, { println!("Built value"); self.inner.build() } } impl<'src, B, E: Environment> AsVisitor<'src, E> for Tracer where Self: DynBind + AnyTrait<'src>, { fn as_visitor(&mut self) -> crate::protocol::DynVisitor<'_, 'src, E> { println!("Converted builder to visitor"); DynVisitor::new(self) } } impl<'src, B, E: Environment> AnyTrait<'src> for Tracer where B: AsVisitor<'src, E>, Self: Value<'src, OwnedStatic, E> + Value<'src, Raised<'src, 'src, BorrowedStatic<'src, i32>>, E> + RequestHint<'src, E>, { fn upcast_by_id_mut( &mut self, id: crate::any::WithLtTypeId<'src>, ) -> Option> { if self .inner .as_visitor() .upcast_by_id_mut(id) .is_some() { trait_by_id!(&mut self, id, { type Impls = ( dyn Value<'_, OwnedStatic, E>, dyn Value<'_, Raised<'_, '_, BorrowedStatic<'_, i32>>, E>, dyn RequestHint<'_, E>, ); }); println!("Unknown protocol for Tracer: {:?}", id); self.inner .as_visitor() .into_inner() .as_any_trait_mut() .upcast_by_id_mut(id) } else { println!("Unknown protocol for builder: {:?}", id); None } } } impl<'src, B, E: Environment> Value<'src, OwnedStatic, E> for Tracer where B: AsVisitor<'src, E> + DynBind, { fn visit<'r>( &'r mut self, value: OwnedStatic, ) -> Canonical<'r, VisitResult>, E> where 'src: 'r, Lowered<'r, 'src, OwnedStatic>: Sized + DynBind, { println!("Visited i32: {}", value.0); visit_value(self.inner.as_visitor(), value) } } impl<'src, B, E: Environment> Value<'src, Raised<'src, 'src, BorrowedStatic<'src, i32>>, E> for Tracer where B: AsVisitor<'src, E> + DynBind, { fn visit<'r>( &'r mut self, value: BorrowedStatic<'src, i32>, ) -> Canonical<'r, VisitResult>, E> where 'src: 'r, Lowered<'r, 'src, OwnedStatic>: Sized + DynBind, { println!("Visited 'src borrow of i32: {}", value.0); visit_value(self.inner.as_visitor(), value) } } impl<'src, B, E: Environment> RequestHint<'src, E> for Tracer where B: AsVisitor<'src, E> + DynBind, { fn request_hint<'r>( &'r mut self, walker: DynWalker<'r, 'src, E>, ) -> Canonical<'r, VisitResult, E> { println!("Walker requested hint"); let walker = WalkerTracer:: { inner: walker }; E::value((self, walker)).update_map((), |_, (this, walker)| { request_hint(this.inner.as_visitor(), DynWalker::new(walker)).map((), |_, x| x.unit_skipped()).cast() }).map((), |_, (_, result)| result).cast() } } #[derive(SendSync)] struct WalkerTracer<'r, 'src, E: Environment> { inner: DynWalker<'r, 'src, E>, } impl<'r, 'src, E: Environment> AnyTrait<'src> for WalkerTracer<'r, 'src, E> { fn upcast_by_id_mut( &mut self, id: crate::any::WithLtTypeId<'src>, ) -> Option> { if self .inner .upcast_by_id_mut(id) .is_some() { trait_by_id!(&mut self, id, { type Impls = ( ); }); println!("Unknown walker protocol for Tracer: {:?}", id); self.inner .upcast_by_id_mut(id) } else { println!("Unknown protocol for walker: {:?}", id); None } } }