mod builders;
mod modify;
mod traversal;
mod view;
pub use builders::LineBuilder;
use std::fmt::Debug;
use derive_more::{From, Into};
use portgraph::dot::DotFormat;
use portgraph::{NodeIndex, PortGraph, PortMut, PortView, Weights};
use crate::predicate::{EdgePredicate, Symbol};
use crate::{BiMap, EdgeProperty, HashSet, PatternID, Universe};
#[derive(Clone, Copy, PartialEq, Eq, From, Into, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct StateID(NodeIndex);
#[derive(Clone, Copy, Debug)]
pub struct OutPort(StateID, usize);
impl OutPort {
#[allow(unused)]
pub fn state(&self) -> StateID {
self.0
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
struct State {
matches: Vec<PatternID>,
scope: HashSet<Symbol>,
deterministic: bool,
}
#[derive(Clone, Debug, Copy, From, Into)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
struct Transition<PNode, PEdge, OffsetID> {
predicate: EdgePredicate<PNode, PEdge, OffsetID>,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ScopeAutomaton<PNode, PEdge, OffsetID = <PEdge as EdgeProperty>::OffsetID> {
graph: PortGraph,
weights: Weights<Option<State>, Option<Transition<PNode, PEdge, OffsetID>>>,
root: StateID,
}
impl<PNode: Clone, PEdge: EdgeProperty> Default for ScopeAutomaton<PNode, PEdge> {
fn default() -> Self {
let mut graph = PortGraph::new();
let root: StateID = graph.add_node(0, 0).into();
let weights = {
let mut w = Weights::new();
w[root.0] = Some(State {
matches: Vec::new(),
scope: HashSet::from_iter([Symbol::root()]),
deterministic: true,
});
w
};
Self {
graph,
weights,
root,
}
}
}
impl<PNode: Clone, PEdge: EdgeProperty> ScopeAutomaton<PNode, PEdge> {
pub fn new() -> Self {
Default::default()
}
pub(crate) fn str_weights(&self) -> Weights<String, String>
where
PNode: Debug,
PEdge: Debug,
<PEdge as EdgeProperty>::OffsetID: Debug,
{
let mut str_weights = Weights::new();
for n in self.graph.nodes_iter() {
if let Some(w) = self.weights[n].as_ref() {
str_weights[n] = format!("{:?}", w);
if let Some(w) = self.weights[n].as_ref().map(|w| &w.matches) {
if !w.is_empty() {
str_weights[n] += &format!("[{:?}]", w);
}
}
}
}
for p in self.graph.ports_iter() {
if let Some(w) = self.weights[p].as_ref() {
str_weights[p] = format!("{:?}", w);
}
}
str_weights
}
pub fn dot_string(&self) -> String
where
PNode: Debug,
PEdge: Debug,
<PEdge as EdgeProperty>::OffsetID: Debug,
{
self.graph
.dot_format()
.with_weights(&self.str_weights())
.finish()
}
pub(crate) fn root(&self) -> StateID {
self.root
}
}
#[derive(Clone, Debug)]
struct AssignMap<U: Universe> {
map: BiMap<Symbol, U>,
state_id: StateID,
}
impl<U: Universe> AssignMap<U> {
fn new(root_state: StateID, root: U) -> Self {
let map = BiMap::from_iter([(Symbol::root(), root)]);
Self {
map,
state_id: root_state,
}
}
}