From dd5f8ccaf4ef3cf2382969b6186e21f034b8037f Mon Sep 17 00:00:00 2001 From: timofey Date: Sun, 23 Apr 2023 20:59:36 +0000 Subject: [PATCH] trace render --- src/std/collections/stack.rs | 15 ++++ src/std/tracing.rs | 3 + src/std/tracing/rendered.rs | 120 ++++++++++++++++++++++++++++ src/std/tracing/rendered_display.rs | 78 ++++++++++++++++++ src/std/tracing/trace.rs | 10 ++- src/std/tracing/trace/render.rs | 118 +++++++++++++++++++++++++++ 6 files changed, 340 insertions(+), 4 deletions(-) create mode 100644 src/std/tracing/rendered.rs create mode 100644 src/std/tracing/rendered_display.rs create mode 100644 src/std/tracing/trace/render.rs diff --git a/src/std/collections/stack.rs b/src/std/collections/stack.rs index 775e4c7..6b6f191 100644 --- a/src/std/collections/stack.rs +++ b/src/std/collections/stack.rs @@ -279,4 +279,19 @@ mod tests { assert_eq!(format!("{}", traced.t), "( ? -> ? -> ? )"); Ok(()) } + + #[test] + fn test_rendered() -> Result<(), point::PointParseError> { + let stack: T = make_stack(); + let rendered = stack.clone().vec().render(); + assert_eq!(rendered.length(), 0); + assert_eq!(rendered.width(), 0); + assert_eq!(format!("{}", rendered), "."); + let stack: T = Rc::new(stack).trace()?; + let rendered = stack.clone().vec().render(); + assert_eq!(rendered.length(), 3); + assert_eq!(rendered.width(), 1); + assert_eq!(format!("{}", rendered), "( ? -> ? -> ? )"); + Ok(()) + } } diff --git a/src/std/tracing.rs b/src/std/tracing.rs index 7b0dcec..facc3bd 100644 --- a/src/std/tracing.rs +++ b/src/std/tracing.rs @@ -1,3 +1,5 @@ +mod rendered; +mod rendered_display; mod trace; mod traced; @@ -5,6 +7,7 @@ use crate::core::*; use super::*; +pub use self::rendered::*; use self::trace::*; pub use self::traced::*; diff --git a/src/std/tracing/rendered.rs b/src/std/tracing/rendered.rs new file mode 100644 index 0000000..5c58c5f --- /dev/null +++ b/src/std/tracing/rendered.rs @@ -0,0 +1,120 @@ +use std::cmp::max; + +pub struct WithLengthAndWidth { + length: usize, + width: usize, + value: T, +} + +pub enum RenderedCommon { + Empty, + Resolution, + Event(String), + Action { + name: String, + rendered: Box>, + }, +} + +pub enum RenderedWide { + Common(RenderedCommon), + Wide(Vec>), +} + +pub enum RenderedLong { + Common(RenderedCommon), + Long(Vec>), +} + +pub enum RenderedAny { + Common(RenderedCommon), + Wide(Vec>), + Long(Vec>), +} + +impl WithLengthAndWidth { + pub fn push_into(self, vec: &mut WithLengthAndWidth>>) { + vec.length += self.length; + vec.width = max(vec.width, self.width); + vec.value.push(self); + } +} + +impl WithLengthAndWidth { + pub fn push_into(self, vec: &mut WithLengthAndWidth>>) { + vec.width += self.width; + vec.length = max(vec.length, self.length); + vec.value.push(self); + } +} + +impl WithLengthAndWidth { + pub fn map(self, f: impl FnOnce(A) -> B) -> WithLengthAndWidth { + WithLengthAndWidth { + length: self.length, + width: self.width, + value: f(self.value), + } + } + + pub fn length(&self) -> usize { + self.length + } + + pub fn width(&self) -> usize { + self.width + } + + pub fn value(&self) -> &A { + &self.value + } +} + +impl Default for WithLengthAndWidth { + fn default() -> Self { + Self { + length: 0, + width: 0, + value: Default::default(), + } + } +} + +impl WithLengthAndWidth { + pub fn wrap(self, name: &str) -> WithLengthAndWidth { + WithLengthAndWidth { + length: self.length, + width: self.width, + value: RenderedCommon::Action { + name: name.into(), + rendered: self.into(), + }, + } + } +} + +impl RenderedCommon { + pub fn empty() -> WithLengthAndWidth { + WithLengthAndWidth { + length: 0, + width: 0, + value: RenderedCommon::Empty, + } + } + + pub fn resolution() -> WithLengthAndWidth { + WithLengthAndWidth { + length: 1, + width: 1, + value: RenderedCommon::Resolution, + } + } + + pub fn event(event: &str) -> WithLengthAndWidth { + WithLengthAndWidth { + length: 0, + width: 0, + value: RenderedCommon::Event(event.into()), + } + } +} diff --git a/src/std/tracing/rendered_display.rs b/src/std/tracing/rendered_display.rs new file mode 100644 index 0000000..fe2a97d --- /dev/null +++ b/src/std/tracing/rendered_display.rs @@ -0,0 +1,78 @@ +use std::fmt::Display; + +use super::*; + +impl Display for WithLengthAndWidth { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("{}", self.value())) + } +} + +impl Display for RenderedAny { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RenderedAny::Common(common) => f.write_fmt(format_args!("{}", common)), + RenderedAny::Wide(vec) => f.write_fmt(format_args!("( {} )", RenderVec(vec))), + RenderedAny::Long(vec) => f.write_fmt(format_args!("( {} )", RenderVec(vec))), + } + } +} + +impl Display for RenderedCommon { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RenderedCommon::Empty => f.write_fmt(format_args!(".")), + RenderedCommon::Resolution => f.write_fmt(format_args!("?")), + RenderedCommon::Event(event) => f.write_fmt(format_args!("{}", event)), + RenderedCommon::Action { name, rendered } => { + f.write_fmt(format_args!("{} @ {}", name, rendered)) + } + } + } +} + +struct RenderVec(T); + +impl Display for RenderVec<&Vec>> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut delimiter = ""; + let mut tail = "~"; + for rendered in self.0 { + f.write_fmt(format_args!("{}{}", delimiter, rendered))?; + delimiter = " -> "; + tail = ""; + } + f.write_fmt(format_args!("{}", tail)) + } +} + +impl Display for RenderVec<&Vec>> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut delimiter = ""; + let mut tail = "~"; + for rendered in self.0 { + f.write_fmt(format_args!("{}{}", delimiter, rendered))?; + delimiter = " | "; + tail = ""; + } + f.write_fmt(format_args!("{}", tail)) + } +} + +impl Display for RenderedLong { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RenderedLong::Common(common) => f.write_fmt(format_args!("{}", common)), + RenderedLong::Long(vec) => f.write_fmt(format_args!("( {} )", RenderVec(vec))), + } + } +} + +impl Display for RenderedWide { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RenderedWide::Common(common) => f.write_fmt(format_args!("{}", common)), + RenderedWide::Wide(vec) => f.write_fmt(format_args!("( {} )", RenderVec(vec))), + } + } +} diff --git a/src/std/tracing/trace.rs b/src/std/tracing/trace.rs index e36dcae..46d8268 100644 --- a/src/std/tracing/trace.rs +++ b/src/std/tracing/trace.rs @@ -1,3 +1,5 @@ +pub mod render; + use std::{cmp::max, fmt::Display}; #[derive(Debug)] @@ -5,9 +7,9 @@ enum Trace { Pure, InvolvesOneResolution, Event(String), + Wrapped { name: String, trace: TraceBox }, Parallel(TraceBox, TraceBox), Sequential { first: TraceBox, second: TraceBox }, - Wrapped { name: String, trace: TraceBox }, } #[derive(Debug)] @@ -59,6 +61,7 @@ impl Display for Trace { Trace::Pure => f.write_fmt(format_args!(".")), Trace::InvolvesOneResolution => f.write_fmt(format_args!("?")), Trace::Event(event) => f.write_fmt(format_args!("{}", event)), + Trace::Wrapped { name, trace } => f.write_fmt(format_args!("{} @ {}", name, trace)), Trace::Parallel(a, b) => { f.write_fmt(format_args!("( {} | {} )", ParallelBox(a), ParallelBox(b))) } @@ -67,7 +70,6 @@ impl Display for Trace { SequentialBox(first), SequentialBox(second) )), - Trace::Wrapped { name, trace } => f.write_fmt(format_args!("{} @ {}", name, trace)), } } } @@ -109,9 +111,9 @@ impl Trace { Self::Pure => 0, Self::InvolvesOneResolution => 1, Self::Event(_) => 0, + Self::Wrapped { trace, .. } => trace.length(), Self::Parallel(a, b) => max(a.length(), b.length()), Self::Sequential { first, second } => first.length() + second.length(), - Self::Wrapped { trace, .. } => trace.length(), } } @@ -120,9 +122,9 @@ impl Trace { Self::Pure => 0, Self::InvolvesOneResolution => 1, Self::Event(_) => 0, + Self::Wrapped { trace, .. } => trace.width(), Self::Parallel(a, b) => a.width() + b.width(), Self::Sequential { first, second } => max(first.width(), second.width()), - Self::Wrapped { trace, .. } => trace.width(), } } diff --git a/src/std/tracing/trace/render.rs b/src/std/tracing/trace/render.rs new file mode 100644 index 0000000..1767f16 --- /dev/null +++ b/src/std/tracing/trace/render.rs @@ -0,0 +1,118 @@ +use crate::std::tracing::{rendered::*, *}; + +use super::*; + +enum TraceCommon<'a> { + Pure, + InvolvesOneResolution, + Event(&'a str), + Wrapped { name: &'a str, trace: &'a Trace }, +} + +enum TraceAny<'a> { + Common(TraceCommon<'a>), + Parallel(&'a Trace, &'a Trace), + Sequential { first: &'a Trace, second: &'a Trace }, +} + +impl Trace { + fn any(&self) -> TraceAny<'_> { + match self { + Trace::Pure => TraceAny::Common(TraceCommon::Pure), + Trace::InvolvesOneResolution => TraceAny::Common(TraceCommon::InvolvesOneResolution), + Trace::Event(event) => TraceAny::Common(TraceCommon::Event(event)), + Trace::Wrapped { name, trace } => TraceAny::Common(TraceCommon::Wrapped { + name, + trace: &trace.trace, + }), + Trace::Parallel(a, b) => TraceAny::Parallel(&a.trace, &b.trace), + Trace::Sequential { first, second } => TraceAny::Sequential { + first: &first.trace, + second: &second.trace, + }, + } + } + + fn render(&self) -> WithLengthAndWidth { + self.any().render() + } +} + +impl Traced { + pub fn render(&self) -> WithLengthAndWidth { + self.t.trace.render() + } +} + +fn from_sequential( + first: &Trace, + second: &Trace, +) -> WithLengthAndWidth>> { + let mut vec = WithLengthAndWidth::default(); + first.any().render_into_long(&mut vec); + second.any().render_into_long(&mut vec); + vec +} + +fn from_parallel( + a: &Trace, + b: &Trace, +) -> WithLengthAndWidth>> { + let mut vec = WithLengthAndWidth::default(); + a.any().render_into_wide(&mut vec); + b.any().render_into_wide(&mut vec); + vec +} + +impl<'a> TraceAny<'a> { + fn render(&'a self) -> WithLengthAndWidth { + match self { + TraceAny::Common(common) => common.render().map(RenderedAny::Common), + TraceAny::Parallel(a, b) => from_parallel(a, b).map(RenderedAny::Wide), + TraceAny::Sequential { first, second } => { + from_sequential(first, second).map(RenderedAny::Long) + } + } + } + + fn render_into_long( + &'a self, + vec: &mut WithLengthAndWidth>>, + ) { + match self { + TraceAny::Common(common) => common.render().map(RenderedWide::Common).push_into(vec), + TraceAny::Parallel(a, b) => from_parallel(a, b).map(RenderedWide::Wide).push_into(vec), + TraceAny::Sequential { first, second } => { + first.any().render_into_long(vec); + second.any().render_into_long(vec); + } + } + } + + fn render_into_wide( + &'a self, + vec: &mut WithLengthAndWidth>>, + ) { + match self { + TraceAny::Common(common) => common.render().map(RenderedLong::Common).push_into(vec), + TraceAny::Parallel(a, b) => { + a.any().render_into_wide(vec); + b.any().render_into_wide(vec); + } + TraceAny::Sequential { first, second } => from_sequential(first, second) + .map(RenderedLong::Long) + .push_into(vec), + } + } +} + +impl<'a> TraceCommon<'a> { + fn render(&'a self) -> WithLengthAndWidth { + match self { + TraceCommon::Pure => RenderedCommon::empty(), + TraceCommon::InvolvesOneResolution => RenderedCommon::resolution(), + TraceCommon::Event(event) => RenderedCommon::event(event), + TraceCommon::Wrapped { name, trace } => trace.any().render().wrap(name), + } + } +}