mod component;
mod graph_base;
mod sequence;
pub use component::{ComponentGraph, ContainmentScope};
pub use sequence::{SequenceEvent, SequenceGraph};
use log::trace;
use orrery_core::{identifier::Id, semantic};
use crate::RenderError;
#[derive(Debug)]
pub enum GraphKind<'a, 'idx> {
ComponentGraph(ComponentGraph<'a, 'idx>),
SequenceGraph(SequenceGraph<'a>),
}
impl<'a, 'idx> GraphKind<'a, 'idx> {
fn build_component(
elements: &'a [semantic::Element],
) -> Result<(Self, Vec<HierarchyNode<'a, 'idx>>), RenderError> {
let (graph, children) = ComponentGraph::new_from_elements(elements)?;
Ok((Self::ComponentGraph(graph), children))
}
fn build_sequence(
elements: &'a [semantic::Element],
) -> Result<(Self, Vec<HierarchyNode<'a, 'idx>>), RenderError> {
let (graph, children) = SequenceGraph::new_from_elements(elements)?;
Ok((Self::SequenceGraph(graph), children))
}
}
#[derive(Debug)]
pub struct GraphedDiagram<'a, 'idx> {
ast_diagram: &'a semantic::Diagram,
graph_kind: GraphKind<'a, 'idx>,
}
impl<'a, 'idx> GraphedDiagram<'a, 'idx> {
pub fn ast_diagram(&self) -> &semantic::Diagram {
self.ast_diagram
}
pub fn graph_kind(&self) -> &GraphKind<'a, 'idx> {
&self.graph_kind
}
fn new(ast_diagram: &'a semantic::Diagram, graph_kind: GraphKind<'a, 'idx>) -> Self {
Self {
ast_diagram,
graph_kind,
}
}
}
#[derive(Debug)]
struct HierarchyNode<'a, 'idx> {
graphed_diagram: GraphedDiagram<'a, 'idx>,
container_id: Option<Id>,
children: Vec<HierarchyNode<'a, 'idx>>,
}
impl<'a, 'idx> HierarchyNode<'a, 'idx> {
fn new(
graphed_diagram: GraphedDiagram<'a, 'idx>,
container_id: Option<Id>,
children: Vec<HierarchyNode<'a, 'idx>>,
) -> Self {
HierarchyNode {
graphed_diagram,
container_id,
children,
}
}
fn build_from_ast_diagram(
ast_diagram: &'a semantic::Diagram,
container_id: Option<Id>,
) -> Result<Self, RenderError> {
let (graph, children) = match ast_diagram.kind() {
semantic::DiagramKind::Component => {
GraphKind::build_component(ast_diagram.scope().elements())?
}
semantic::DiagramKind::Sequence => {
GraphKind::build_sequence(ast_diagram.scope().elements())?
}
};
let graphed_diagram = GraphedDiagram::new(ast_diagram, graph);
Ok(Self::new(graphed_diagram, container_id, children))
}
}
#[derive(Debug)]
pub struct DiagramHierarchy<'a, 'idx> {
root: HierarchyNode<'a, 'idx>,
}
impl<'a, 'idx> DiagramHierarchy<'a, 'idx> {
pub fn from_diagram(diagram: &'a semantic::Diagram) -> Result<Self, RenderError> {
let root_diagram = HierarchyNode::build_from_ast_diagram(diagram, None)?;
let hierarchy = DiagramHierarchy { root: root_diagram };
trace!(hierarchy:?; "Created diagram hierarchy");
Ok(hierarchy)
}
pub fn iter_post_order(&self) -> impl Iterator<Item = (Option<Id>, &GraphedDiagram<'_, '_>)> {
let mut stack = Vec::new();
stack.push(&self.root);
let mut i = 0;
while i < stack.len() {
let node = stack[i];
for child in node.children.iter().rev() {
stack.push(child);
}
i += 1;
}
stack
.into_iter()
.rev()
.map(|node| (node.container_id, &node.graphed_diagram))
}
}