use std::cmp::max; use crate::func::*; use crate::rcore::*; use crate::rstd::typeless::*; use super::*; pub struct TestContextCounted; impl Context for TestContextCounted { type T = CountedClass; type Fallible = classes::result::ResultFailOver; type D = NoDiagnostic; type LookupError<'a> = TestLookupError<'a>; fn hash(s: &[u8]) -> Hash { TestContextPlain::hash(s) } } pub type CountedClass = classes::effect::EffectClass; impl classes::effect::Effect for usize { fn e_pure() -> Self { 0 } fn e_seq(lhs: Self, rhs: Self) -> Self { max(lhs, rhs) } fn e_after(self, effect: Self) -> Self { self + effect } } pub type Counted = classes::effect::WithEffect; impl Counted { fn add(self, n: usize) -> Self { Counted { value: self.value, effect: self.effect + n, } } pub fn count(&self) -> usize { self.effect } } struct CountedResolver<'a> { resolver: Rc>, } impl<'a> CountedResolver<'a> { fn new( resolver: Rc>, ) -> Rc> { Rc::new(Self { resolver }) } } impl<'a> Resolver<'a, TestContextCounted> for CountedResolver<'a> { fn resolve(self: Rc, address: Address) -> HashResolution<'a, TestContextCounted> { CountedClass::fmap( |resolved| { let (src, resolver) = resolved?; let delayed: Rc> = Rc::new(CountedResolver { resolver }); Ok((src, delayed)) }, self.resolver.clone().resolve(address), ) .add(1) } } pub trait Delayable<'a>: Mentionable<'a, TestContextCounted> + Sized { fn delay(self: Rc) -> CastResult<'a, TestContextCounted, Self>; } impl<'a, A: Mentionable<'a, TestContextCounted>> Delayable<'a> for A { fn delay(self: Rc) -> CastResult<'a, TestContextCounted, Self> { let factory = self.factory(); TypelessMentionable::from_typed(self).cast_full(factory, CountedResolver::new) } }