1use scopegraphs_prust_lib::hashmap::HashSet as TrieSet;
2use std::collections::HashSet;
3use std::fmt::{Debug, Formatter};
4use std::hash::Hash;
5use std::marker::PhantomData;
6use std::rc::Rc;
7
8use super::{Scope, ScopeGraph};
9
10mod params;
11pub use params::*;
12use scopegraphs_regular_expressions::RegexMatcher;
13
14pub mod lookup;
15
16#[derive(Hash, PartialEq, Eq)]
21pub enum EdgeOrData<LABEL> {
22 Data,
23 Edge(LABEL),
24}
25
26impl<LABEL: Debug> Debug for EdgeOrData<LABEL> {
27 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28 match self {
29 EdgeOrData::Data => write!(f, "$"),
30 EdgeOrData::Edge(lbl) => write!(f, "@{:?}", lbl),
31 }
32 }
33}
34
35impl<LABEL: Copy> Clone for EdgeOrData<LABEL> {
37 fn clone(&self) -> Self {
38 *self
39 }
40}
41
42impl<LABEL: Copy> Copy for EdgeOrData<LABEL> {}
43
44#[derive(Hash, PartialEq, Eq, Debug)]
45enum InnerPath<LABEL> {
46 Start {
47 source: Scope,
48 },
49 Step {
50 prefix: Path<LABEL>,
51 label: LABEL,
52 target: Scope,
53 },
54}
55
56#[derive(Clone)]
58pub struct Path<LABEL> {
59 inner_path: Rc<InnerPath<LABEL>>,
60 scopes: Rc<TrieSet<Scope>>,
70 }
72
73impl<LABEL> PartialEq for Path<LABEL>
74where
75 Scope: PartialEq,
76 LABEL: PartialEq,
77{
78 fn eq(&self, other: &Self) -> bool {
79 self.inner_path == other.inner_path
81 }
82}
83
84impl<LABEL> Eq for Path<LABEL>
85where
86 Scope: Eq,
87 LABEL: Eq,
88{
89}
90
91impl<LABEL> Hash for Path<LABEL>
92where
93 Scope: Hash,
94 LABEL: Hash,
95{
96 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
97 self.inner_path.hash(state);
99 }
100}
101
102impl<LABEL> Debug for Path<LABEL>
103where
104 LABEL: Debug,
105{
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("Path")
108 .field("inner_path", &self.inner_path)
110 .finish()
111 }
112}
113
114#[derive(Hash, PartialEq, Eq, Debug)]
116pub struct ResolvedPath<'sg, LABEL, DATA> {
117 path: Path<LABEL>,
118 data: &'sg DATA,
119}
120
121impl<'sg, LABEL: Clone, DATA> Clone for ResolvedPath<'sg, LABEL, DATA> {
122 fn clone(&self) -> Self {
123 Self {
124 path: self.path.clone(),
125 data: self.data,
126 }
127 }
128}
129
130impl<'sg, LABEL, DATA> ResolvedPath<'sg, LABEL, DATA> {
131 pub fn path(&self) -> &Path<LABEL> {
132 &self.path
133 }
134
135 pub fn data(&self) -> &DATA {
136 self.data
137 }
138}
139
140impl<LABEL> Path<LABEL> {
141 pub fn new(source: Scope) -> Self {
143 Self {
144 inner_path: Rc::new(InnerPath::Start { source }),
145 scopes: Rc::new(TrieSet::new().insert(source)),
146 }
147 }
148
149 pub fn target(&self) -> Scope {
151 match self.inner_path.as_ref() {
152 InnerPath::Start { source } => *source,
153 InnerPath::Step { target, .. } => *target,
154 }
155 }
156
157 pub fn step(&self, label: LABEL, target: Scope) -> Option<Self> {
161 if self.scopes.search(&target) {
162 None
163 } else {
164 Some(Self {
165 inner_path: Rc::new(InnerPath::Step {
166 prefix: Self {
167 inner_path: self.inner_path.clone(),
168 scopes: self.scopes.clone(),
169 },
170 label,
171 target,
172 }),
173 scopes: Rc::new(self.scopes.insert(target)),
174 })
175 }
176 }
177
178 pub fn resolve<DATA>(self, data: &DATA) -> ResolvedPath<'_, LABEL, DATA> {
180 ResolvedPath { path: self, data }
181 }
182}
183
184#[derive(Debug)]
192pub struct Env<'sg, LABEL: 'sg, DATA>(HashSet<ResolvedPath<'sg, LABEL, DATA>>);
193
194impl<'sg, LABEL, DATA> IntoIterator for Env<'sg, LABEL, DATA> {
195 type Item = ResolvedPath<'sg, LABEL, DATA>;
196
197 type IntoIter = <HashSet<ResolvedPath<'sg, LABEL, DATA>> as IntoIterator>::IntoIter;
198
199 fn into_iter(self) -> Self::IntoIter {
200 self.0.into_iter()
201 }
202}
203
204impl<LABEL, DATA> Default for Env<'_, LABEL, DATA> {
205 fn default() -> Self {
206 Self::new()
207 }
208}
209
210impl<'sg, LABEL, DATA> Env<'sg, LABEL, DATA> {
211 pub fn new() -> Self {
213 Self(HashSet::new())
214 }
215
216 pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a ResolvedPath<'sg, LABEL, DATA>> + 'a {
218 self.0.iter()
219 }
220
221 pub fn is_empty(&self) -> bool {
223 self.0.is_empty()
224 }
225}
226
227impl<'sg, LABEL, DATA> Env<'sg, LABEL, DATA>
228where
229 ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
230{
231 pub fn single(path: ResolvedPath<'sg, LABEL, DATA>) -> Self {
233 let mut env = Env::new();
234 env.insert(path);
235 env
236 }
237
238 pub fn insert(&mut self, path: ResolvedPath<'sg, LABEL, DATA>) {
240 self.0.insert(path);
241 }
242
243 pub fn merge(&mut self, other: &Self) {
245 self.0.extend(other.0.iter().cloned())
246 }
247}
248
249impl<'sg, LABEL: 'sg, DATA: Hash> FromIterator<ResolvedPath<'sg, LABEL, DATA>>
250 for Env<'sg, LABEL, DATA>
251where
252 ResolvedPath<'sg, LABEL, DATA>: Eq + Hash,
253{
254 fn from_iter<T: IntoIterator<Item = ResolvedPath<'sg, LABEL, DATA>>>(iter: T) -> Self {
255 Env(HashSet::from_iter(iter))
256 }
257}
258
259impl<'sg, LABEL: 'sg, DATA: Hash> FromIterator<Env<'sg, LABEL, DATA>> for Env<'sg, LABEL, DATA>
260where
261 ResolvedPath<'sg, LABEL, DATA>: Eq + Hash,
262{
263 fn from_iter<T: IntoIterator<Item = Env<'sg, LABEL, DATA>>>(iter: T) -> Self {
264 iter.into_iter().flatten().collect()
265 }
266}
267
268impl<'sg, LABEL: 'sg + Clone, DATA> Clone for Env<'sg, LABEL, DATA> {
269 fn clone(&self) -> Self {
270 Env(self.0.clone())
271 }
272}
273
274pub trait Resolve<'sg, 'rslv> {
275 type EnvContainer
276 where
277 'sg: 'rslv,
278 Self: 'rslv;
279
280 fn resolve(&'rslv self, scope: Scope) -> Self::EnvContainer;
281}
282
283pub struct Query<'storage, 'sg, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq> {
284 _phantom: PhantomData<&'rslv ()>,
285 scope_graph: &'sg ScopeGraph<'storage, LABEL, DATA, CMPL>,
286 path_wellformedness: PWF,
287 data_wellformedness: DWF,
288 label_order: LO,
289 data_equivalence: DEq,
290}
291
292impl<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
293 Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
294{
295 pub fn with_path_wellformedness<NPWF>(
296 self,
297 new_path_wellformedness: NPWF,
298 ) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, NPWF, DWF, LO, DEq>
299 where
300 NPWF: for<'a> RegexMatcher<&'a LABEL> + 'rslv,
301 {
302 Query {
303 _phantom: PhantomData,
304 scope_graph: self.scope_graph,
305 path_wellformedness: new_path_wellformedness,
306 data_wellformedness: self.data_wellformedness,
307 label_order: self.label_order,
308 data_equivalence: self.data_equivalence,
309 }
310 }
311
312 pub fn with_data_wellformedness<NDWF>(
313 self,
314 new_data_wellformedness: NDWF,
315 ) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, NDWF, LO, DEq>
316 where
317 NDWF: DataWellformedness<DATA> + 'rslv,
318 {
319 Query {
320 _phantom: PhantomData,
321 scope_graph: self.scope_graph,
322 path_wellformedness: self.path_wellformedness,
323 data_wellformedness: new_data_wellformedness,
324 label_order: self.label_order,
325 data_equivalence: self.data_equivalence,
326 }
327 }
328
329 pub fn with_label_order<NLO>(
330 self,
331 new_label_order: NLO,
332 ) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, NLO, DEq>
333 where
334 NLO: LabelOrder<LABEL> + 'rslv,
335 {
336 Query {
337 _phantom: PhantomData,
338 scope_graph: self.scope_graph,
339 path_wellformedness: self.path_wellformedness,
340 data_wellformedness: self.data_wellformedness,
341 label_order: new_label_order,
342 data_equivalence: self.data_equivalence,
343 }
344 }
345
346 pub fn with_data_equivalence<NDEq>(
347 self,
348 new_data_equivalence: NDEq,
349 ) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, NDEq>
350 where
351 NDEq: DataEquiv<DATA> + 'rslv,
352 {
353 Query {
354 _phantom: PhantomData,
355 scope_graph: self.scope_graph,
356 path_wellformedness: self.path_wellformedness,
357 data_wellformedness: self.data_wellformedness,
358 label_order: self.label_order,
359 data_equivalence: new_data_equivalence,
360 }
361 }
362}
363
364impl<'storage, LABEL, DATA, CMPL> ScopeGraph<'storage, LABEL, DATA, CMPL> {
365 pub fn query<'sg>(
366 &'sg self,
367 ) -> Query<
368 'storage,
369 'sg,
370 '_,
371 LABEL,
372 DATA,
373 CMPL,
374 (),
375 DefaultDataWellformedness,
376 DefaultLabelOrder,
377 DefaultDataEquiv,
378 >
379 where
380 'storage: 'sg,
381 {
382 Query {
383 _phantom: PhantomData,
384 scope_graph: self,
385 path_wellformedness: (),
386 data_wellformedness: DefaultDataWellformedness::default(),
387 label_order: DefaultLabelOrder::default(),
388 data_equivalence: DefaultDataEquiv::default(),
389 }
390 }
391}