Removing Unnecessary structures for edge display in dot and graphml

This commit is contained in:
elvis
2025-07-27 14:59:35 +02:00
parent 9ee0c94e28
commit 7fcaa5c13b
3 changed files with 140 additions and 222 deletions

View File

@ -266,11 +266,11 @@ LiteralSeparatorNode: graph::NodeDisplayBase = {
}; };
/// Match for strings between edge formatters /// Match for strings between edge formatters
LiteralSeparatorEdge: presets::EdgeDisplay = { LiteralSeparatorEdge: graph::EdgeDisplayBase = {
PATH => PATH =>
presets::EdgeDisplay::Separator( graph::EdgeDisplayBase::String {
<>.trim_end_matches("\"").trim_start_matches("\"").to_string() string: <>.trim_end_matches("\"").trim_start_matches("\"").to_string()
) }
}; };
NodeDisplayBase: graph::NodeDisplayBase = { NodeDisplayBase: graph::NodeDisplayBase = {
@ -317,80 +317,50 @@ SeparatorNode: graph::NodeDisplay = {
} }
} }
EdgeDisplay: presets::EdgeDisplay = { EdgeDisplay: graph::EdgeDisplayBase = {
"Hide" => "Hide" =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::Hide,
graph::GraphMapEdges::Hide
),
"Products" => "Products" =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::Products,
graph::GraphMapEdges::Products
),
"MaskProducts" <mask: Set> => "MaskProducts" <mask: Set> =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::MaskEntities{ mask },
graph::GraphMapEdges::MaskEntities{ mask }
),
"Entities" => "Entities" =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::Entities,
graph::GraphMapEdges::Entities
),
"MaskEntities" <mask: Set> => "MaskEntities" <mask: Set> =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::MaskEntities{ mask },
graph::GraphMapEdges::MaskEntities{ mask }
),
"Context" => "Context" =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::Context,
graph::GraphMapEdges::Context
),
"MaskContext" <mask: Set> => "MaskContext" <mask: Set> =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::MaskContext{ mask },
graph::GraphMapEdges::MaskContext{ mask }
),
"Union" => "Union" =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::Union,
graph::GraphMapEdges::Union
),
"MaskUnion" <mask: Set> => "MaskUnion" <mask: Set> =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::MaskUnion{ mask },
graph::GraphMapEdges::MaskUnion{ mask }
),
"Difference" => "Difference" =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::Difference,
graph::GraphMapEdges::Difference
),
"MaskDifference" <mask: Set> => "MaskDifference" <mask: Set> =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::MaskDifference{ mask },
graph::GraphMapEdges::MaskDifference{ mask }
),
"EntitiesDeleted" => "EntitiesDeleted" =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::EntitiesDeleted,
graph::GraphMapEdges::EntitiesDeleted
),
"MaskEntitiesDeleted" <mask: Set> => "MaskEntitiesDeleted" <mask: Set> =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::MaskEntitiesDeleted{ mask },
graph::GraphMapEdges::MaskEntitiesDeleted{ mask }
),
"EntitiesAdded" => "EntitiesAdded" =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::EntitiesAdded,
graph::GraphMapEdges::EntitiesAdded
),
"MaskEntitiesAdded" <mask: Set> => "MaskEntitiesAdded" <mask: Set> =>
presets::EdgeDisplay::Display( graph::EdgeDisplayBase::MaskEntitiesAdded{ mask },
graph::GraphMapEdges::MaskEntitiesAdded{ mask }
),
} }
/// Edge display formatters separated by arbitrary strings in quotes /// Edge display formatters separated by arbitrary strings in quotes
SeparatorEdge: Vec<presets::EdgeDisplay> = { SeparatorEdge: graph::EdgeDisplay = {
<v: EdgeDisplay> => vec![v], <v: EdgeDisplay> => graph::EdgeDisplay{ base: vec![v] },
<v:(<EdgeDisplay> <LiteralSeparatorEdge>)+> <e: EdgeDisplay?> => <v:(<EdgeDisplay> <LiteralSeparatorEdge>)+> <e: EdgeDisplay?> =>
match e { match e {
None => v.iter().fold(vec![], None => graph::EdgeDisplay{ base: v.iter().fold(vec![],
|mut acc, (a, b)| { |mut acc, (a, b)| {
acc.push(a.clone()); acc.push(a.clone());
acc.push(b.clone()); acc.push(b.clone());
acc.clone() acc.clone()
}), }) },
Some(e) => { Some(e) => {
let mut v = v.iter().fold(vec![], let mut v = v.iter().fold(vec![],
|mut acc, (a, b)| { |mut acc, (a, b)| {
@ -399,7 +369,7 @@ SeparatorEdge: Vec<presets::EdgeDisplay> = {
acc.clone() acc.clone()
}); });
v.push(e); v.push(e);
v graph::EdgeDisplay{ base: v }
} }
} }
} }

View File

@ -157,7 +157,7 @@ impl NodeDisplay {
/// Helper structure that specifies what information to display for edges /// Helper structure that specifies what information to display for edges
#[derive(Clone)] #[derive(Clone)]
pub enum GraphMapEdges { pub enum EdgeDisplayBase {
String { string: String }, String { string: String },
Hide, Hide,
Products, Products,
@ -176,136 +176,93 @@ pub enum GraphMapEdges {
MaskEntitiesAdded { mask: RSset }, MaskEntitiesAdded { mask: RSset },
} }
pub struct EdgeDisplay {
pub base: Vec<EdgeDisplayBase>
}
type GraphMapEdgesFnTy<'a> = type GraphMapEdgesFnTy<'a> =
dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a; dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a;
/// Helper structure that holds a formatting function from node as RSsystem to
/// string
pub struct GraphMapEdgesTy<'a> { fn match_edge_display<'a>(
functions: Vec<Box<GraphMapEdgesFnTy<'a>>>, base: &'a EdgeDisplayBase,
translator: Rc<translator::Translator> translator: Rc<translator::Translator>
} ) -> Box<GraphMapEdgesFnTy<'a>> {
use EdgeDisplayBase::*;
impl<'a, const N: usize> From<([GraphMapEdges; N], Rc<translator::Translator>)>
for GraphMapEdgesTy<'a>
{
fn from(value: ([GraphMapEdges; N], Rc<translator::Translator>)) -> Self {
Self::from((value.0.to_vec(), value.1))
}
}
impl<'a> From<(&[GraphMapEdges], Rc<translator::Translator>)>
for GraphMapEdgesTy<'a>
{
fn from(value: (&[GraphMapEdges], Rc<translator::Translator>)) -> Self {
Self::from((value.0.to_vec(), value.1))
}
}
impl<'a> From<(Vec<GraphMapEdges>, Rc<translator::Translator>)>
for GraphMapEdgesTy<'a>
{
fn from(value: (Vec<GraphMapEdges>, Rc<translator::Translator>)) -> Self {
use GraphMapEdges::*;
use super::format_helpers::graph_map_edges_ty_from::*; use super::format_helpers::graph_map_edges_ty_from::*;
let mut new = GraphMapEdgesTy {functions: vec![], translator: value.1}; match base {
for f in value.0 {
match f {
String { string } => { String { string } => {
new.functions.push(format_string( format_string(translator, string.clone())
Rc::clone(&new.translator), string))
} }
Hide => { Hide => {
new.functions.push(format_hide( format_hide(translator)
Rc::clone(&new.translator)
))
}, },
Products => { Products => {
new.functions.push(format_products( format_products(translator)
Rc::clone(&new.translator)
))
}, },
MaskProducts { mask } => { MaskProducts { mask } => {
new.functions.push(format_mask_products( format_mask_products(translator, mask.clone())
Rc::clone(&new.translator), mask))
}, },
Entities => { Entities => {
new.functions.push(format_entities( format_entities(translator)
Rc::clone(&new.translator)
))
}, },
MaskEntities { mask } => { MaskEntities { mask } => {
new.functions.push(format_mask_entities( format_mask_entities(translator, mask.clone())
Rc::clone(&new.translator), mask))
}, },
Context => { Context => {
new.functions.push(format_context( format_context(translator)
Rc::clone(&new.translator)
))
}, },
MaskContext { mask } => { MaskContext { mask } => {
new.functions.push(format_mask_context( format_mask_context(translator, mask.clone())
Rc::clone(&new.translator), mask))
}, },
Union => { Union => {
new.functions.push(format_union( format_union(translator)
Rc::clone(&new.translator)
))
}, },
MaskUnion { mask } => { MaskUnion { mask } => {
new.functions.push(format_mask_union( format_mask_union(translator, mask.clone())
Rc::clone(&new.translator), mask))
}, },
Difference => { Difference => {
new.functions.push(format_difference( format_difference(translator)
Rc::clone(&new.translator)
))
}, },
MaskDifference { mask } => { MaskDifference { mask } => {
new.functions.push(format_mask_difference( format_mask_difference(translator, mask.clone())
Rc::clone(&new.translator), mask))
}, },
EntitiesDeleted => { EntitiesDeleted => {
new.functions.push(format_entities_deleted( format_entities_deleted(translator)
Rc::clone(&new.translator)
))
}, },
MaskEntitiesDeleted { mask } => { MaskEntitiesDeleted { mask } => {
new.functions.push(format_mask_entities_deleted( format_mask_entities_deleted(translator, mask.clone())
Rc::clone(&new.translator), mask))
}, },
EntitiesAdded => { EntitiesAdded => {
new.functions.push(format_entities_added( format_entities_added(translator)
Rc::clone(&new.translator)
))
}, },
MaskEntitiesAdded { mask } => { MaskEntitiesAdded { mask } => {
new.functions.push(format_mask_entities_added( format_mask_entities_added(translator, mask.clone())
Rc::clone(&new.translator), mask))
}, },
};
}
new
} }
} }
impl<'a> GraphMapEdgesTy<'a> {
pub fn generate(self) -> Box<GraphMapEdgesFnTy<'a>> {
let mut accumulator: Box<GraphMapEdgesFnTy<'a>> =
super::format_helpers::graph_map_edges_ty_from::format_hide(
Rc::clone(&self.translator)
);
for f in self.functions {
accumulator = Box::new(move |i, n| {
(accumulator)(i, n)
+ &f(i, n)
})
}
impl EdgeDisplay {
pub fn generate<'a>(
self,
translator: Rc<translator::Translator>,
_current_graph: &RSgraph
) -> Box<GraphMapEdgesFnTy<'a>> {
Box::new(
move |i, n| {
let mut accumulator = String::new();
for b in &self.base {
let f = match_edge_display(b,
Rc::clone(&translator));
accumulator.push_str(&(f)(i, n));
}
accumulator accumulator
} }
)
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -13,7 +13,6 @@ use lalrpop_util::ParseError;
// the code // the code
use crate::grammar; use crate::grammar;
use super::structure::RSlabel;
use super::structure::{RSset, RSsystem}; use super::structure::{RSset, RSsystem};
use super::translator::Translator; use super::translator::Translator;
use super::*; use super::*;
@ -58,25 +57,18 @@ impl Default for SaveOptions {
} }
} }
// Describes display options for edges (RSlabels).
#[derive(Clone)]
pub enum EdgeDisplay {
Separator(String),
Display(graph::GraphMapEdges),
}
// Describes output options for a graph. // Describes output options for a graph.
pub enum GraphSaveOptions { pub enum GraphSaveOptions {
Dot { Dot {
node_display: graph::NodeDisplay, node_display: graph::NodeDisplay,
edge_display: Vec<EdgeDisplay>, edge_display: graph::EdgeDisplay,
node_color: graph::NodeColor, node_color: graph::NodeColor,
edge_color: graph::EdgeColor, edge_color: graph::EdgeColor,
so: SaveOptions, so: SaveOptions,
}, },
GraphML { GraphML {
node_display: graph::NodeDisplay, node_display: graph::NodeDisplay,
edge_display: Vec<EdgeDisplay>, edge_display: graph::EdgeDisplay,
so: SaveOptions, so: SaveOptions,
}, },
Serialize { Serialize {
@ -554,41 +546,41 @@ pub fn bisimilar(
// Output Functions // Output Functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
type GraphMapEdgesFnTy<'a> = // type GraphMapEdgesFnTy<'a> =
dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a; // dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a;
fn generate_edge_printing_fn<'a>( // fn generate_edge_printing_fn<'a>(
edge_display: &[EdgeDisplay], // edge_display: graph::EdgeDisplay,
translator: Rc<Translator>, // translator: Rc<Translator>,
) -> Box<GraphMapEdgesFnTy<'a>> { // ) -> Box<GraphMapEdgesFnTy<'a>> {
// The type cannot be aliased since rust doesnt like generics. // // The type cannot be aliased since rust doesnt like generics.
// We are iterating over the edge_display and constructing a function // // We are iterating over the edge_display and constructing a function
// (accumulator) that prints out our formatted nodes. So at each step we // // (accumulator) that prints out our formatted nodes. So at each step we
// call the previous function and add the next string or function. // // call the previous function and add the next string or function.
let edge_display = edge_display.iter().map( // let edge_display = edge_display.iter().map(
|e| { // |e| {
match e { // match e {
EdgeDisplay::Display(d) => { // EdgeDisplay::Display(d) => {
d.clone() // d.clone()
}, // },
EdgeDisplay::Separator(s) => { // EdgeDisplay::Separator(s) => {
graph::GraphMapEdges::String { string: s.clone() } // graph::EdgeDisplayBase::String { string: s.clone() }
} // }
} // }
} // }
).collect::<Vec<_>>(); // ).collect::<Vec<_>>();
let gmet = graph::GraphMapEdgesTy::from( // let gmet = graph::GraphMapEdgesTy::from(
(edge_display, Rc::clone(&translator)) // (edge_display, Rc::clone(&translator))
); // );
gmet.generate() // gmet.generate()
} // }
/// Writes the specified graph to a file in .dot format. /// Writes the specified graph to a file in .dot format.
pub fn dot( pub fn dot(
system: &EvaluatedSystem, system: &EvaluatedSystem,
node_display: graph::NodeDisplay, node_display: graph::NodeDisplay,
edge_display: Vec<EdgeDisplay>, edge_display: graph::EdgeDisplay,
node_color: graph::NodeColor, node_color: graph::NodeColor,
edge_color: graph::EdgeColor edge_color: graph::EdgeColor
) -> Result<String, String> { ) -> Result<String, String> {
@ -601,8 +593,7 @@ pub fn dot(
let rc_translator = Rc::new(translator.clone()); let rc_translator = Rc::new(translator.clone());
let modified_graph = graph.map( let modified_graph = graph.map(
node_display.generate(Rc::clone(&rc_translator), graph), node_display.generate(Rc::clone(&rc_translator), graph),
generate_edge_printing_fn(&edge_display, edge_display.generate(Rc::clone(&rc_translator), graph),
Rc::clone(&rc_translator)),
); );
let graph = Rc::new(graph.to_owned()); let graph = Rc::new(graph.to_owned());
@ -629,7 +620,7 @@ pub fn dot(
pub fn graphml( pub fn graphml(
system: &EvaluatedSystem, system: &EvaluatedSystem,
node_display: graph::NodeDisplay, node_display: graph::NodeDisplay,
edge_display: Vec<EdgeDisplay>, edge_display: graph::EdgeDisplay,
) -> Result<String, String> { ) -> Result<String, String> {
match system { match system {
EvaluatedSystem::System { EvaluatedSystem::System {
@ -643,8 +634,8 @@ pub fn graphml(
let modified_graph = graph.map( let modified_graph = graph.map(
node_display.generate(Rc::clone(&rc_translator), node_display.generate(Rc::clone(&rc_translator),
graph), graph),
generate_edge_printing_fn(&edge_display, edge_display.generate(rc_translator,
rc_translator), graph),
); );
use petgraph_graphml::GraphMl; use petgraph_graphml::GraphMl;