extract traceable
This commit is contained in:
parent
dd5f8ccaf4
commit
d9942857bc
@ -205,12 +205,13 @@ where
|
||||
mod tests {
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::std::{
|
||||
atomic::{atomic_object::*, plain::*},
|
||||
tracing::*,
|
||||
};
|
||||
use crate::testing::{counted::*, traced::*, *};
|
||||
|
||||
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>>;
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
//! Structures for tracing the execution flow of [Monad]s.
|
||||
|
||||
mod rendered;
|
||||
mod rendered_display;
|
||||
mod trace;
|
||||
mod traceable;
|
||||
mod traced;
|
||||
|
||||
use crate::core::*;
|
||||
@ -9,10 +12,16 @@ use super::*;
|
||||
|
||||
pub use self::rendered::*;
|
||||
use self::trace::*;
|
||||
pub use self::traceable::*;
|
||||
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;
|
||||
|
||||
/// Implementation of [`Monad`] for [Traced] objects.
|
||||
pub struct TracedClass;
|
||||
|
||||
trait WithTrace: Sized {
|
||||
|
@ -1,34 +1,77 @@
|
||||
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> {
|
||||
length: usize,
|
||||
width: usize,
|
||||
value: T,
|
||||
}
|
||||
|
||||
/// Rendered trace that can be broken down neither in width nor in length.
|
||||
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,
|
||||
/// Exactly one resolution is involved in getting the value.
|
||||
///
|
||||
/// Usually, a result of [`Traceable::trace`].
|
||||
///
|
||||
/// Represented as 1x1 by default.
|
||||
Resolution,
|
||||
/// Arbitrary event for [Diagnostic]s.
|
||||
///
|
||||
/// Usually, a result of [`Diagnostic::after`]/[`Diagnostic::before`].
|
||||
///
|
||||
/// Represented as 0x0 by default.
|
||||
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 {
|
||||
name: String,
|
||||
rendered: Box<WithLengthAndWidth<RenderedAny>>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Rendered trace that cannot be broken down in length.
|
||||
pub enum RenderedWide {
|
||||
/// See [`RenderedCommon`].
|
||||
Common(RenderedCommon),
|
||||
/// Trace can be broken down in width.
|
||||
Wide(Vec<WithLengthAndWidth<RenderedLong>>),
|
||||
}
|
||||
|
||||
/// Rendered trace that cannot be broken down in width.
|
||||
pub enum RenderedLong {
|
||||
/// See [`RenderedCommon`].
|
||||
Common(RenderedCommon),
|
||||
/// Trace can be broken down in length.
|
||||
Long(Vec<WithLengthAndWidth<RenderedWide>>),
|
||||
}
|
||||
|
||||
/// Represents an arbitrary rendered trace.
|
||||
pub enum RenderedAny {
|
||||
/// See [`RenderedCommon`].
|
||||
Common(RenderedCommon),
|
||||
/// Trace can be broken down in width.
|
||||
Wide(Vec<WithLengthAndWidth<RenderedLong>>),
|
||||
/// Trace can be broken down in length.
|
||||
Long(Vec<WithLengthAndWidth<RenderedWide>>),
|
||||
}
|
||||
|
||||
|
47
src/std/tracing/traceable.rs
Normal file
47
src/std/tracing/traceable.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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 a: A,
|
||||
pub t: TraceBox,
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::core::*;
|
||||
use crate::func::*;
|
||||
use crate::std::tracing::*;
|
||||
|
||||
use super::*;
|
||||
@ -17,41 +16,3 @@ impl Context for TestContextTraced {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user