extract traceable

This commit is contained in:
AF 2023-04-23 22:01:43 +00:00
parent dd5f8ccaf4
commit d9942857bc
6 changed files with 109 additions and 45 deletions

View File

@ -205,12 +205,13 @@ where
mod tests { mod tests {
use std::rc::Rc; use std::rc::Rc;
use crate::std::{
atomic::{atomic_object::*, plain::*},
tracing::*,
};
use crate::testing::{counted::*, traced::*, *};
use super::*; use super::*;
use crate::std::atomic::atomic_object::*;
use crate::std::atomic::plain::*;
use crate::testing::counted::*;
use crate::testing::traced::*;
use crate::testing::*;
type T<Ctx> = Stack<'static, Ctx, AtomicObject<Plain>>; type T<Ctx> = Stack<'static, Ctx, AtomicObject<Plain>>;

View File

@ -1,6 +1,9 @@
//! Structures for tracing the execution flow of [Monad]s.
mod rendered; mod rendered;
mod rendered_display; mod rendered_display;
mod trace; mod trace;
mod traceable;
mod traced; mod traced;
use crate::core::*; use crate::core::*;
@ -9,10 +12,16 @@ use super::*;
pub use self::rendered::*; pub use self::rendered::*;
use self::trace::*; use self::trace::*;
pub use self::traceable::*;
pub use self::traced::*; pub use self::traced::*;
/// [`Diagnostic`] for [Traced] objects.
///
/// [`Diagnostic::after`]/[`Diagnostic::before`] are represented in [`RenderedCommon::Event`].
/// [`Diagnostic::wrapped`] is represented in [`RenderedCommon::Action`].
pub struct TracedDiagnostic; pub struct TracedDiagnostic;
/// Implementation of [`Monad`] for [Traced] objects.
pub struct TracedClass; pub struct TracedClass;
trait WithTrace: Sized { trait WithTrace: Sized {

View File

@ -1,34 +1,77 @@
use std::cmp::max; use std::cmp::max;
#[cfg(doc)]
use crate::core::*;
#[cfg(doc)]
use crate::func::*;
#[cfg(doc)]
use super::*;
/// Represents width (concurrency/throughput) and length (time/latency).
/// Use [`WithLengthAndWidth::length`] and [`WithLengthAndWidth::width`] to access them.
pub struct WithLengthAndWidth<T> { pub struct WithLengthAndWidth<T> {
length: usize, length: usize,
width: usize, width: usize,
value: T, value: T,
} }
/// Rendered trace that can be broken down neither in width nor in length.
pub enum RenderedCommon { pub enum RenderedCommon {
/// No resolutions are involved in getting the value.
///
/// Usually, a result of [`Applicative::pure`].
///
/// Represented as 0x0 by default.
///
/// Normally, is either at the root of the trace or wrapped into [`RenderedCommon::Action`].
Empty, Empty,
/// Exactly one resolution is involved in getting the value.
///
/// Usually, a result of [`Traceable::trace`].
///
/// Represented as 1x1 by default.
Resolution, Resolution,
/// Arbitrary event for [Diagnostic]s.
///
/// Usually, a result of [`Diagnostic::after`]/[`Diagnostic::before`].
///
/// Represented as 0x0 by default.
Event(String), Event(String),
/// Named action for [Diagnostic]s.
///
/// Usually, a result of [`Diagnostic::wrapped`].
///
/// Represented with the same dimensions as the wrapped trace by default.
Action { Action {
name: String, name: String,
rendered: Box<WithLengthAndWidth<RenderedAny>>, rendered: Box<WithLengthAndWidth<RenderedAny>>,
}, },
} }
/// Rendered trace that cannot be broken down in length.
pub enum RenderedWide { pub enum RenderedWide {
/// See [`RenderedCommon`].
Common(RenderedCommon), Common(RenderedCommon),
/// Trace can be broken down in width.
Wide(Vec<WithLengthAndWidth<RenderedLong>>), Wide(Vec<WithLengthAndWidth<RenderedLong>>),
} }
/// Rendered trace that cannot be broken down in width.
pub enum RenderedLong { pub enum RenderedLong {
/// See [`RenderedCommon`].
Common(RenderedCommon), Common(RenderedCommon),
/// Trace can be broken down in length.
Long(Vec<WithLengthAndWidth<RenderedWide>>), Long(Vec<WithLengthAndWidth<RenderedWide>>),
} }
/// Represents an arbitrary rendered trace.
pub enum RenderedAny { pub enum RenderedAny {
/// See [`RenderedCommon`].
Common(RenderedCommon), Common(RenderedCommon),
/// Trace can be broken down in width.
Wide(Vec<WithLengthAndWidth<RenderedLong>>), Wide(Vec<WithLengthAndWidth<RenderedLong>>),
/// Trace can be broken down in length.
Long(Vec<WithLengthAndWidth<RenderedWide>>), Long(Vec<WithLengthAndWidth<RenderedWide>>),
} }

View File

@ -0,0 +1,47 @@
use crate::std::cast::*;
use super::*;
struct TracedResolver<'a, Ctx: 'a + Context> {
resolver: Rc<dyn Resolver<'a, Ctx>>,
}
impl<'a, Ctx: 'a + Context<T = TracedClass>> TracedResolver<'a, Ctx> {
fn wrap(resolver: Rc<dyn Resolver<'a, Ctx>>) -> Rc<dyn Resolver<'a, Ctx>> {
Rc::new(Self { resolver })
}
}
impl<'a, Ctx: 'a + Context<T = TracedClass>> Resolver<'a, Ctx> for TracedResolver<'a, Ctx> {
fn resolve(self: Rc<Self>, address: Address) -> HashResolution<'a, Ctx> {
TracedClass::fmap(
|resolved| {
let (src, resolver) = resolved?;
let delayed: Rc<dyn Resolver<'a, Ctx>> = Rc::new(TracedResolver { resolver });
Ok((src, delayed))
},
self.resolver.clone().resolve(address),
)
.after_resolution()
}
}
/// Extension trait to trace the evaluation flow.
pub trait Traceable<'a, Ctx: 'a + Context<T = TracedClass>>: Mentionable<'a, Ctx> + Sized {
/// Re-cast the value, adding an extra[^extra]
/// note ([`RenderedCommon::Resolution`]) to the trace on each resolution.
///
/// [^extra]: applying [`Traceable::trace`] multiple times
/// might affect the trace in undesireable ways
fn trace(self: Rc<Self>) -> CastResult<'a, Ctx, Self>;
}
impl<'a, Ctx: 'a + Context<T = TracedClass>, A: Mentionable<'a, Ctx>> Traceable<'a, Ctx> for A
where
Ctx::LookupError<'a>: From<CastError<'a>>,
{
fn trace(self: Rc<Self>) -> CastResult<'a, Ctx, Self> {
let factory = self.factory();
TypelessMentionable::from_typed(self).cast_full(factory, TracedResolver::wrap)
}
}

View File

@ -1,5 +1,8 @@
use super::trace::*; use super::*;
/// Wrapper containing the value and the corresponding execution trace.
///
/// For what the trace contains, see its rendered form, [`RenderedAny`].
pub struct Traced<A> { pub struct Traced<A> {
pub a: A, pub a: A,
pub t: TraceBox, pub t: TraceBox,

View File

@ -1,5 +1,4 @@
use crate::core::*; use crate::core::*;
use crate::func::*;
use crate::std::tracing::*; use crate::std::tracing::*;
use super::*; use super::*;
@ -17,41 +16,3 @@ impl Context for TestContextTraced {
TestContextPlain::hash(s) TestContextPlain::hash(s)
} }
} }
struct TracedResolver<'a> {
resolver: Rc<dyn Resolver<'a, TestContextTraced>>,
}
impl<'a> TracedResolver<'a> {
fn new(
resolver: Rc<dyn Resolver<'a, TestContextTraced>>,
) -> Rc<dyn Resolver<'a, TestContextTraced>> {
Rc::new(Self { resolver })
}
}
impl<'a> Resolver<'a, TestContextTraced> for TracedResolver<'a> {
fn resolve(self: Rc<Self>, address: Address) -> HashResolution<'a, TestContextTraced> {
TracedClass::fmap(
|resolved| {
let (src, resolver) = resolved?;
let delayed: Rc<dyn Resolver<'a, TestContextTraced>> =
Rc::new(TracedResolver { resolver });
Ok((src, delayed))
},
self.resolver.clone().resolve(address),
)
.after_resolution()
}
}
pub trait Traceable<'a>: Mentionable<'a, TestContextTraced> + Sized {
fn trace(self: Rc<Self>) -> CastResult<'a, TestContextTraced, Self>;
}
impl<'a, A: Mentionable<'a, TestContextTraced>> Traceable<'a> for A {
fn trace(self: Rc<Self>) -> CastResult<'a, TestContextTraced, Self> {
let factory = self.factory();
TypelessMentionable::from_typed(self).cast_full(factory, TracedResolver::new)
}
}