hyperon/space/
module.rs

1use std::fmt::{Debug, Display};
2
3use hyperon_atom::{matcher::BindingsSet, Atom};
4use hyperon_common::FlexRef;
5use hyperon_space::{complex_query, DynSpace, Space, SpaceCommon, SpaceMut, SpaceVisitor};
6
7pub struct ModuleSpace {
8    main: DynSpace,
9    deps: Vec<DynSpace>,
10}
11
12impl Display for ModuleSpace {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        write!(f, "ModuleSpace({})", &self.main)
15    }
16}
17
18impl Debug for ModuleSpace {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20        write!(f, "ModuleSpace({:?})", &self.main)
21    }
22}
23
24impl ModuleSpace {
25    pub fn new(space: DynSpace) -> Self {
26        Self { main: space, deps: Vec::new() }
27    }
28
29    pub fn main(&self) -> DynSpace {
30        self.main.clone()
31    }
32
33    pub fn query(&self, query: &Atom) -> BindingsSet {
34        complex_query(query, |query| self.single_query(query))
35    }
36 
37    fn single_query(&self, query: &Atom) -> BindingsSet {
38        log::debug!("ModuleSpace::query: {} {}", self, query);
39        let mut results = self.main.borrow().query(query);
40        for dep in &self.deps {
41            if let Some(space) = dep.borrow().as_any().downcast_ref::<Self>()  {
42                results.extend(space.query_no_deps(query));
43            } else {
44                panic!("Only ModuleSpace is expected inside dependencies collection");
45            }
46        }
47        results
48    }
49
50    fn query_no_deps(&self, query: &Atom) -> BindingsSet {
51        log::debug!("ModuleSpace::query_no_deps: {} {}", self, query);
52        self.main.borrow().query(query)
53    }
54
55    pub fn add_dep(&mut self, space: DynSpace) {
56        self.deps.push(space)
57    }
58
59    pub fn deps(&self) -> &Vec<DynSpace> {
60        &self.deps
61    }
62}
63
64impl Space for ModuleSpace {
65    fn common(&self) -> FlexRef<'_, SpaceCommon> {
66        self.main.common()
67    }
68    fn query(&self, query: &Atom) -> BindingsSet {
69        ModuleSpace::query(self, query)
70    }
71    fn atom_count(&self) -> Option<usize> {
72        self.main.borrow().atom_count()
73    }
74    fn visit(&self, v: &mut dyn SpaceVisitor) -> Result<(), ()> {
75        self.main.borrow().visit(v)
76    }
77    fn as_any(&self) -> &dyn std::any::Any {
78        self
79    }
80}
81
82impl SpaceMut for ModuleSpace {
83    fn add(&mut self, atom: Atom) {
84        self.main.borrow_mut().add(atom)
85    }
86    fn remove(&mut self, atom: &Atom) -> bool {
87        self.main.borrow_mut().remove(atom)
88    }
89    fn replace(&mut self, from: &Atom, to: Atom) -> bool {
90        self.main.borrow_mut().replace(from, to)
91    }
92    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
93        self
94    }
95}
96
97#[cfg(test)]
98mod test {
99    use hyperon_common::assert_eq_no_order;
100    use hyperon_atom::*;
101    use crate::space::grounding::*;
102    use super::*;
103
104    #[test]
105    fn complex_query_two_subspaces() {
106        let mut a = GroundingSpace::new();
107        a.add(expr!("a" "b"));
108        let mut b = GroundingSpace::new();
109        b.add(expr!("b" "c"));
110
111        let mut main = ModuleSpace::new(GroundingSpace::new().into());
112        main.add_dep(ModuleSpace::new(a.into()).into());
113        main.add_dep(ModuleSpace::new(b.into()).into());
114
115        assert_eq_no_order!(main.query(&expr!("," (a "b") ("b" c))), vec![bind!{ a: sym!("a"), c: sym!("c") }]);
116        assert_eq_no_order!(main.query(&expr!("," ("a" b) (b "c"))), vec![bind!{ b: sym!("b") }]);
117    }
118}
119