1use std::fmt::Debug;
2
3use super::{tags, TreePath, TreePathMut};
4use crate::types::{HyperAST, NodeId, NodeStore, Tree, WithChildren};
5use crate::PrimInt;
6
7#[derive(Clone)]
9pub struct StructuralPosition<IdN, Idx, Config = tags::TopDownFull> {
10 pub(super) parents: Vec<IdN>, pub(super) offsets: Vec<Idx>,
12 _phantom: std::marker::PhantomData<Config>,
13}
14
15impl<IdN, C, Idx> super::node_filter_traits::Full for StructuralPosition<IdN, Idx, C> {}
16
17impl<IdN: Debug, Idx: Debug> std::fmt::Debug for StructuralPosition<IdN, Idx, tags::TopDownFull> {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 write!(f, "SP{{{:?} {:?} TopDown}}", &self.parents, &self.offsets)
20 }
21}
22
23impl<IdN: Debug, Idx: Debug> std::fmt::Debug for StructuralPosition<IdN, Idx, tags::BottomUpFull> {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "SP{{{:?} {:?} BottomUp}}", &self.parents, &self.offsets)
26 }
27}
28
29impl<IdN: std::hash::Hash, C, Idx: std::hash::Hash> std::hash::Hash
30 for StructuralPosition<IdN, Idx, C>
31{
32 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
33 self.parents.last().hash(state);
34 self.parents.first().hash(state);
35 self.offsets.hash(state);
36 }
37}
38impl<IdN: std::cmp::PartialEq, C, Idx: std::cmp::PartialEq> PartialEq
39 for StructuralPosition<IdN, Idx, C>
40{
41 fn eq(&self, other: &Self) -> bool {
42 self.parents.last() == other.parents.last()
43 && self.parents.first() == other.parents.first()
44 && self.offsets == other.offsets
45 }
46}
47impl<IdN: std::cmp::Eq, C, Idx: std::cmp::Eq> Eq for StructuralPosition<IdN, Idx, C> {}
48impl<IdN: std::cmp::Eq, Idx: PrimInt> PartialOrd for StructuralPosition<IdN, Idx> {
49 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
50 Some(self.cmp(other))
51 }
52}
53impl<IdN: std::cmp::Eq, Idx: PrimInt> Ord for StructuralPosition<IdN, Idx> {
54 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
55 use crate::position::position_accessors::SharedPath;
56 use std::cmp::Ordering::*;
57 match crate::position::position_accessors::WithPreOrderOffsets::shared_ancestors(
58 self, other,
59 ) {
60 SharedPath::Exact(_) => std::cmp::Ordering::Equal,
61 SharedPath::Remain(_) => Less,
62 SharedPath::Submatch(_) => Greater,
63 SharedPath::Different(a) => {
64 let c = self.offsets[a.len() + 1].cmp(&other.offsets[a.len() + 1]);
65 assert_ne!(c, std::cmp::Ordering::Equal);
66 c
67 }
68 }
69 }
70}
71
72impl<IdN, Idx, C> StructuralPosition<IdN, Idx, C> {
73 pub fn empty() -> Self {
74 Self {
75 parents: vec![],
76 offsets: vec![],
77 _phantom: Default::default(),
78 }
79 }
80 pub fn _set_first_node(&mut self, n: IdN, o: Idx) {
81 assert!(self.parents.is_empty());
82 assert!(self.offsets.len() == 1);
83 self.parents.push(n);
84 self.offsets[0] = o;
85 }
86 pub(crate) fn solved(self, node: IdN) -> SolvedStructuralPosition<IdN, Idx, C> {
87 SolvedStructuralPosition {
88 parents: self.parents,
89 offsets: self.offsets,
90 node,
91 _phantom: Default::default(),
92 }
93 }
94
95 pub fn parent(&self) -> Option<&IdN> {
96 let i = self.parents.len().checked_sub(2)?;
97 self.parents.get(i)
98 }
99}
100
101impl<IdN, Idx: PrimInt, C> super::position_accessors::WithOffsets
102 for StructuralPosition<IdN, Idx, C>
103{
104 type Idx = Idx;
105}
106
107impl<IdN, Idx: PrimInt> super::position_accessors::WithPath<IdN> for StructuralPosition<IdN, Idx> {}
108
109impl<IdN, Idx: PrimInt> super::position_accessors::WithPreOrderOffsets
110 for StructuralPosition<IdN, Idx>
111{
112 type It<'a>
113 = SPIter<'a, Idx>
114 where
115 Idx: 'a,
116 Self: 'a;
117
118 fn iter_offsets(&self) -> Self::It<'_> {
119 let mut iter = self.offsets.iter();
120 iter.next().unwrap();
121 SPIter(iter)
122 }
123}
124
125impl<IdN, Idx: PrimInt> super::position_accessors::WithPostOrderOffsets
126 for StructuralPosition<IdN, Idx>
127{
128 fn iter(&self) -> impl Iterator<Item = Self::Idx> {
129 self.offsets[1..]
130 .iter()
131 .rev()
132 .cloned()
133 .map(|o| o - num::one())
134 }
135}
136
137impl<IdN: Copy, Idx: PrimInt> super::position_accessors::WithPostOrderPath<IdN>
138 for StructuralPosition<IdN, Idx>
139{
140 fn iter_offsets_and_parents(&self) -> impl Iterator<Item = (Self::Idx, IdN)> {
141 super::position_accessors::WithPostOrderOffsets::iter(self)
142 .zip(self.parents.iter().rev().skip(1).cloned())
143 }
144}
145
146impl<IdN: Copy, Idx: PrimInt> super::position_accessors::RootedPosition<IdN>
147 for StructuralPosition<IdN, Idx>
148{
149 fn root(&self) -> IdN {
150 self.parents.first().unwrap().clone()
151 }
152}
153
154impl<IdN: Copy, Idx: PrimInt> super::position_accessors::WithFullPostOrderPath<IdN>
155 for StructuralPosition<IdN, Idx>
156{
157 fn iter_with_nodes(&self) -> (IdN, impl Iterator<Item = (Self::Idx, IdN)>) {
158 use crate::position::position_accessors::WithPostOrderPath;
159 (*self.node().unwrap(), self.iter_offsets_and_parents())
160 }
161}
162
163impl<IdN: Copy, Idx: PrimInt> super::position_accessors::SolvedPosition<IdN>
164 for StructuralPosition<IdN, Idx>
165{
166 fn node(&self) -> IdN {
167 *TreePath::node(self).unwrap()
168 }
169}
170
171pub struct SPIter<'a, Idx>(std::slice::Iter<'a, Idx>);
172
173impl<'a, Idx: PrimInt> Iterator for SPIter<'a, Idx> {
174 type Item = Idx;
175
176 fn next(&mut self) -> Option<Self::Item> {
177 self.0.next().map(|x| *x - num::one())
178 }
179}
180
181#[derive(Clone, Debug)]
183pub struct SolvedStructuralPosition<IdN, Idx, Config = tags::TopDownFull> {
184 pub(super) parents: Vec<IdN>,
185 pub(super) offsets: Vec<Idx>,
186 pub(super) node: IdN,
187 _phantom: std::marker::PhantomData<Config>,
188}
189impl<IdN, Idx, C> Into<(IdN, Vec<Idx>)> for SolvedStructuralPosition<IdN, Idx, C> {
190 fn into(self) -> (IdN, Vec<Idx>) {
191 (self.node, self.offsets)
192 }
193}
194impl<IdN, Idx, C> From<SolvedStructuralPosition<IdN, Idx, C>> for StructuralPosition<IdN, Idx, C> {
195 fn from(value: SolvedStructuralPosition<IdN, Idx, C>) -> Self {
196 Self {
197 parents: value.parents,
198 offsets: value.offsets,
199 _phantom: Default::default(),
200 }
201 }
202}
203impl<IdN: Copy, Idx: PrimInt> TreePath<IdN, Idx> for StructuralPosition<IdN, Idx> {
211 fn node(&self) -> Option<&IdN> {
212 self.parents.last()
213 }
214
215 fn offset(&self) -> Option<&Idx> {
216 self.offsets.last()
217 }
218
219 fn check<'store, HAST>(&self, stores: &'store HAST) -> Result<(), ()>
220 where
221 HAST: HyperAST<'store, IdN = IdN::IdN>,
222 HAST::T: WithChildren<ChildIdx = Idx>,
223 HAST::IdN: Eq,
224 IdN: NodeId,
225 IdN::IdN: NodeId<IdN = IdN::IdN>,
226 {
227 use num::one;
228 assert_eq!(self.offsets.len(), self.parents.len());
229 if self.parents.is_empty() {
230 return Ok(());
231 }
232 let mut i = self.parents.len() - 1;
233
234 while i > 0 {
235 let e = self.parents[i];
236 let o = self.offsets[i] - one();
237 let p = self.parents[i - 1];
238 let b = stores.node_store().resolve(&p.as_id());
239 if !b.has_children()
240 || Some(e.as_id()) != b.child(&num::cast(o).expect("too big")).as_ref()
241 {
242 return Err(());
243 }
244 i -= 1;
245 }
246 Ok(())
247 }
248}
249
250impl<IdN: Copy, Idx: PrimInt> TreePathMut<IdN, Idx> for StructuralPosition<IdN, Idx> {
251 fn pop(&mut self) -> Option<(IdN, Idx)> {
252 Some((self.parents.pop()?, self.offsets.pop()?))
253 }
254
255 fn goto(&mut self, node: IdN, i: Idx) {
256 use num::one;
257 self.parents.push(node);
258 self.offsets.push(i + one());
261 }
262
263 fn inc(&mut self, node: IdN) {
264 use num::one;
265 *self.parents.last_mut().unwrap() = node;
266 *self.offsets.last_mut().unwrap() += one();
267 }
268
269 fn dec(&mut self, node: IdN) {
270 use num::one;
271 *self.parents.last_mut().unwrap() = node;
272 if let Some(offsets) = self.offsets.last_mut() {
273 assert!(*offsets >= one());
274 *offsets -= one();
275 }
276 }
277}
278
279impl<IdN, Idx: num::Zero, C> StructuralPosition<IdN, Idx, C> {
280 pub fn new(node: IdN) -> Self {
281 Self {
282 parents: vec![node],
283 offsets: vec![num::zero()],
284 _phantom: Default::default(),
285 }
286 }
287}
288
289impl<IdN, Idx: PrimInt, C> StructuralPosition<IdN, Idx, C> {
290 pub fn o(&self) -> Option<Idx> {
291 self.offsets
292 .last()
293 .and_then(|&x| x.checked_sub(&num::one()))
294 }
295}
296
297impl<IdN, Idx> From<(Vec<IdN>, Vec<Idx>, IdN)> for StructuralPosition<IdN, Idx> {
298 fn from(mut x: (Vec<IdN>, Vec<Idx>, IdN)) -> Self {
299 assert_eq!(x.0.len() + 1, x.1.len());
300 x.0.push(x.2);
301 Self {
302 parents: x.0,
303 offsets: x.1,
304 _phantom: Default::default(),
305 }
306 }
307}
308impl<IdN, Idx> From<(Vec<IdN>, Vec<Idx>)> for StructuralPosition<IdN, Idx> {
309 fn from(x: (Vec<IdN>, Vec<Idx>)) -> Self {
310 assert_eq!(x.0.len(), x.1.len());
311 Self {
312 parents: x.0,
313 offsets: x.1,
314 _phantom: Default::default(),
315 }
316 }
317}
318impl<IdN, Idx: num::Zero> From<IdN> for StructuralPosition<IdN, Idx> {
319 fn from(node: IdN) -> Self {
320 Self::new(node)
321 }
322}
323
324mod impl_c_p_p_receivers {
325
326 use super::super::building;
327 use super::PrimInt;
328 use super::SolvedStructuralPosition;
329 use super::StructuralPosition;
330 use building::top_down;
331
332 impl<IdN, Idx: PrimInt, C> top_down::CreateBuilder for StructuralPosition<IdN, Idx, C> {
333 fn create() -> Self {
334 Self {
335 offsets: vec![],
336 parents: vec![],
337 _phantom: Default::default(),
338 }
339 }
340 }
341
342 impl<IdN, Idx: PrimInt, C> top_down::ReceiveParent<IdN, Self> for StructuralPosition<IdN, Idx, C> {
343 fn push(self, _parent: IdN) -> Self {
344 self
345 }
346 }
347
348 impl<IdN, Idx: PrimInt, C> building::top_down::ReceiveDirName<Self>
349 for StructuralPosition<IdN, Idx, C>
350 {
351 fn push(self, _dir_name: &str) -> Self {
352 self
353 }
354 }
355
356 impl<IdN, Idx: PrimInt, C> building::bottom_up::ReceiveDirName<Self>
357 for StructuralPosition<IdN, Idx, C>
358 {
359 fn push(self, _dir_name: &str) -> Self {
360 self
361 }
362 }
363
364 impl<IdN, Idx: PrimInt, C> building::top_down::ReceiveIdx<Idx, Self>
372 for StructuralPosition<IdN, Idx, C>
373 {
374 fn push(self, _idx: Idx) -> Self {
375 self
377 }
378 }
379
380 impl<IdN, Idx: PrimInt, C> building::top_down::ReceiveIdxNoSpace<Idx, Self>
388 for StructuralPosition<IdN, Idx, C>
389 {
390 fn push(mut self, idx: Idx) -> Self {
391 self.offsets.push(idx);
392 self
393 }
394 }
395
396 impl<IdN, Idx: PrimInt, C> top_down::FileSysReceiver for StructuralPosition<IdN, Idx, C> {
397 type InFile<O> = Self;
398 }
399
400 impl<IdN, Idx: PrimInt, IdO, C> building::top_down::ReceiveOffset<IdO, Self>
401 for StructuralPosition<IdN, Idx, C>
402 {
403 fn push(self, _bytes: IdO) -> Self {
404 self
405 }
406 }
407 impl<IdN, Idx: PrimInt, IdO, C> building::SetLen<IdO, Self> for StructuralPosition<IdN, Idx, C> {
408 fn set(self, _len: IdO) -> Self {
409 self
410 }
411 }
412 impl<IdN, Idx: PrimInt, C> top_down::SetNode<IdN, SolvedStructuralPosition<IdN, Idx, C>>
420 for StructuralPosition<IdN, Idx, C>
421 {
422 fn set_node(self, node: IdN) -> SolvedStructuralPosition<IdN, Idx, C> {
423 self.solved(node)
424 }
425 }
426 impl<IdN, Idx: PrimInt, C> top_down::SetFileName<Self> for StructuralPosition<IdN, Idx, C> {
427 fn set_file_name(self, _file_name: &str) -> Self {
428 self
429 }
430 }
431 impl<IdN, Idx: PrimInt, IdO, C> building::ReceiveRows<IdO, Self>
432 for StructuralPosition<IdN, Idx, C>
433 {
434 fn push(self, _row: IdO) -> Self {
435 self
436 }
437 }
438 impl<IdN, Idx: PrimInt, IdO, C> building::ReceiveColumns<IdO, Self>
439 for StructuralPosition<IdN, Idx, C>
440 {
441 fn push(self, _col: IdO) -> Self {
442 self
443 }
444 }
445 impl<IdN, Idx: PrimInt, C> building::Transition<Self> for StructuralPosition<IdN, Idx, C> {
446 fn transit(self) -> Self {
447 self
448 }
449 }
450}