radn-rs/src/testing/counted.rs
2023-05-30 13:51:26 +00:00

88 lines
2.1 KiB
Rust

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