use crate::Graph;
use crate::graph::NodeAttribute;
use crate::operation::BuiltinOperation;
use crate::operation::query::BuiltinQuery;
use petgraph::data::Build;
pub mod example;
pub mod example_with_ref;
#[derive(Default)]
pub struct AnyMatcher<A> {
phantom_data: std::marker::PhantomData<A>,
}
impl<A> AbstractMatcher for AnyMatcher<A> {
type Abstract = A;
fn matches(_argument: &Self::Abstract, _parameter: &Self::Abstract) -> bool {
true
}
}
pub trait AbstractMatcher {
type Abstract;
fn matches(argument: &Self::Abstract, parameter: &Self::Abstract) -> bool;
}
#[derive(Default)]
pub struct MatchJoiner<M: AbstractMatcher<Abstract: Clone>> {
phantom: std::marker::PhantomData<M>,
}
impl<M: AbstractMatcher<Abstract: Clone>> AbstractJoin for MatchJoiner<M> {
type Abstract = M::Abstract;
fn join(a: &Self::Abstract, b: &Self::Abstract) -> Option<Self::Abstract> {
if M::matches(a, b) {
Some(b.clone())
} else {
if M::matches(b, a) {
Some(a.clone())
} else {
None
}
}
}
}
pub trait AbstractJoin {
type Abstract;
fn join(a: &Self::Abstract, b: &Self::Abstract) -> Option<Self::Abstract> {
None
}
}
pub trait Semantics {
type NodeConcrete: Clone;
type NodeAbstract: Clone + PartialEq;
type EdgeConcrete: Clone;
type EdgeAbstract: Clone + PartialEq;
type NodeMatcher: AbstractMatcher<Abstract = Self::NodeAbstract>;
type EdgeMatcher: AbstractMatcher<Abstract = Self::EdgeAbstract>;
type NodeJoin: AbstractJoin<Abstract = Self::NodeAbstract>;
type EdgeJoin: AbstractJoin<Abstract = Self::EdgeAbstract>;
type NodeConcreteToAbstract: ConcreteToAbstract<Concrete = Self::NodeConcrete, Abstract = Self::NodeAbstract>;
type EdgeConcreteToAbstract: ConcreteToAbstract<Concrete = Self::EdgeConcrete, Abstract = Self::EdgeAbstract>;
type BuiltinOperation: BuiltinOperation<S = Self>;
type BuiltinQuery: BuiltinQuery<S = Self>;
fn top_node_abstract() -> Option<Self::NodeAbstract> {
None
}
fn top_edge_abstract() -> Option<Self::EdgeAbstract> {
None
}
fn new_concrete_graph() -> ConcreteGraph<Self> {
Graph::new()
}
fn new_abstract_graph() -> AbstractGraph<Self> {
Graph::new()
}
fn join_edges(a: &Self::EdgeAbstract, b: &Self::EdgeAbstract) -> Option<Self::EdgeAbstract> {
Self::EdgeJoin::join(a, b)
}
fn join_nodes(a: &Self::NodeAbstract, b: &Self::NodeAbstract) -> Option<Self::NodeAbstract> {
Self::NodeJoin::join(a, b)
}
fn concrete_to_abstract(c: &ConcreteGraph<Self>) -> AbstractGraph<Self> {
let mut abstract_graph = Graph::new();
for (node_key, node_concrete) in c.nodes() {
let node_abstract = Self::NodeConcreteToAbstract::concrete_to_abstract(&node_concrete);
abstract_graph.graph.add_node(node_key);
abstract_graph
.node_attr_map
.insert(node_key, NodeAttribute::new(node_abstract));
}
abstract_graph.max_node_key = c.max_node_key;
for (src, dst, weight) in c.graph.all_edges() {
let edge_abstract = Self::EdgeConcreteToAbstract::concrete_to_abstract(weight.attr());
let new_edge_attr = weight.with(edge_abstract);
abstract_graph.graph.add_edge(src, dst, new_edge_attr);
}
abstract_graph
}
}
pub type ConcreteGraph<S> = Graph<<S as Semantics>::NodeConcrete, <S as Semantics>::EdgeConcrete>;
pub type AbstractGraph<S> = Graph<<S as Semantics>::NodeAbstract, <S as Semantics>::EdgeAbstract>;
pub trait ConcreteToAbstract {
type Concrete;
type Abstract;
fn concrete_to_abstract(c: &Self::Concrete) -> Self::Abstract;
}