grabapl/
lib.rs

1//! Grabapl docs. Todo.
2
3extern crate core;
4
5mod experimental;
6pub mod graph;
7pub mod operation;
8pub mod semantics;
9#[cfg(feature = "serde")]
10mod serde;
11pub mod util;
12
13use crate::util::InternString;
14use ::serde::{Deserialize, Serialize};
15use derive_more::From;
16pub use graph::EdgeInsertionOrder;
17pub use graph::EdgeKey;
18pub use graph::Graph;
19pub use graph::NodeKey;
20pub use semantics::Semantics;
21
22/// A marker for substitution in the graph.
23///
24/// Useful for programmatically defined operations to know the substitution of their input pattern.
25#[derive(derive_more::Debug, Clone, Copy, PartialEq, Eq, Hash, From)]
26#[debug("P({_0})")]
27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
28pub struct SubstMarker(pub InternString);
29interned_string_newtype!(SubstMarker);
30
31// TODO: maybe we could have an input builder? basically we want to have one connected component per input.
32// then we allow building an input graph with the builder, but the finalize method checks that we have exactly one input node
33// (actually we could enforce that statically via it being the entry point) and that it is in fact weakly connected (ie ignoring edge direction)
34// The input pattern for the Operation would then instead be a Vec of those input connected component patterns.
35
36// TODO: What if two separate connected components overlap in the substitution? this leads to 'node references' to some degree.
37// Probably only really bad if the 'shape' of that node changes while another reference to it expects something else. eg deleting the node or changing its type
38
39pub mod prelude {
40    pub use super::SubstMarker;
41    pub use crate::graph::{Graph, NodeKey};
42    pub use crate::operation::builder::{BuilderOpLike, OperationBuilder};
43    pub use crate::operation::builtin::LibBuiltinOperation;
44    pub use crate::operation::signature::OperationSignature;
45    pub use crate::operation::signature::parameter::{GraphWithSubstitution, OperationParameter};
46    pub use crate::operation::signature::parameterbuilder::OperationParameterBuilder;
47    pub use crate::operation::user_defined::{AbstractNodeId, UserDefinedOperation};
48    pub use crate::operation::{
49        BuiltinOperation, Operation, OperationContext, OperationId, run_from_concrete,
50    };
51    pub use crate::semantics::{
52        AbstractGraph, AbstractJoin, AbstractMatcher, ConcreteGraph, ConcreteToAbstract, Semantics,
53    };
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use crate::graph::dot::DotCollector;
60    // #[test]
61    // this is an old test with old test matching behavior.
62    fn child_order() {
63        let mut collector = DotCollector::new();
64        let mut graph = Graph::<&str, ()>::new();
65
66        macro_rules! c {
67            () => {
68                collector.collect(&graph);
69            };
70        }
71
72        c!();
73        let a = graph.add_node("hello");
74        c!();
75        let b = graph.add_node("world");
76        c!();
77
78        graph.add_edge(a, b, ());
79        c!();
80
81        let next_edge = graph.next_outgoing_edge(a, (a, b));
82        assert_eq!(next_edge, (a, b));
83
84        let prev_edge = graph.prev_outgoing_edge(a, (a, b));
85        assert_eq!(prev_edge, (a, b));
86
87        let c = graph.add_node("foo");
88        c!();
89        graph.add_edge(a, c, ());
90        c!();
91        let next_edge = graph.next_outgoing_edge(a, (a, b));
92        assert_eq!(next_edge, (a, c));
93        let prev_edge = graph.prev_outgoing_edge(a, (a, c));
94        assert_eq!(prev_edge, (a, b));
95        let prev_edge = graph.prev_outgoing_edge(a, (a, b));
96        assert_eq!(prev_edge, (a, c));
97
98        let d = graph.add_node("bar");
99        c!();
100        graph.add_edge(a, d, ());
101        c!();
102        let next_edge = graph.next_outgoing_edge(a, (a, c));
103        assert_eq!(next_edge, (a, d));
104        let next_edge = graph.next_outgoing_edge(a, (a, d));
105        assert_eq!(next_edge, (a, b));
106        let prev_edge = graph.prev_outgoing_edge(a, (a, b));
107        assert_eq!(prev_edge, (a, d));
108
109        let before_b = graph.add_node("before_b");
110        c!();
111        graph.add_edge_ordered(
112            a,
113            before_b,
114            (),
115            EdgeInsertionOrder::Prepend,
116            EdgeInsertionOrder::Append,
117        );
118        c!();
119
120        let after_d = graph.add_node("after_d");
121        c!();
122        graph.add_edge_ordered(
123            a,
124            after_d,
125            (),
126            EdgeInsertionOrder::Append,
127            EdgeInsertionOrder::Append,
128        );
129        c!();
130
131        let next_edge = graph.next_outgoing_edge(a, (a, b));
132        assert_eq!(next_edge, (a, c));
133        let prev_edge = graph.prev_outgoing_edge(a, (a, b));
134        assert_eq!(prev_edge, (a, before_b));
135        let next_edge = graph.next_outgoing_edge(a, (a, d));
136        assert_eq!(next_edge, (a, after_d));
137        let prev_edge = graph.prev_outgoing_edge(a, (a, before_b));
138        assert_eq!(prev_edge, (a, after_d));
139
140        let dot = collector.finalize();
141        println!("{}", dot);
142        assert!(false);
143    }
144}