extract traceable
This commit is contained in:
parent
dd5f8ccaf4
commit
d9942857bc
@ -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>>;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 struct Traced<A> {
|
||||||
pub a: A,
|
pub a: A,
|
||||||
pub t: TraceBox,
|
pub t: TraceBox,
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user