use std::{fmt::Debug, path::PathBuf};
use num::traits::NumAssign;
use crate::{
store::defaults::NodeIdentifier,
types::{HyperAST, NodeId, TypedNodeId, WithChildren},
};
pub trait PrimInt: num::PrimInt + NumAssign + Debug {}
impl<T> PrimInt for T where T: num::PrimInt + NumAssign + Debug {}
pub trait TreePath<IdN = NodeIdentifier, Idx = u16> {
fn node(&self) -> Option<&IdN>;
fn offset(&self) -> Option<&Idx>;
fn check<'store, HAST>(&self, stores: &'store HAST) -> Result<(), ()>
where
HAST: HyperAST<'store, IdN = IdN::IdN>,
HAST::T: WithChildren<ChildIdx = Idx>,
HAST::IdN: Eq,
IdN: NodeId,
IdN::IdN: NodeId<IdN = IdN::IdN>;
}
pub trait TreePathMut<IdN, Idx>: TreePath<IdN, Idx> {
fn pop(&mut self) -> Option<(IdN, Idx)>;
fn goto(&mut self, node: IdN, i: Idx);
fn inc(&mut self, node: IdN);
fn dec(&mut self, node: IdN);
}
pub trait TypedTreePath<TIdN: TypedNodeId, Idx>: TreePath<TIdN::IdN, Idx> {
fn node_typed(&self) -> Option<&TIdN>;
fn pop_typed(&mut self) -> Option<(TIdN, Idx)>;
fn goto_typed(&mut self, node: TIdN, i: Idx);
}
pub mod position_accessors {
use super::*;
pub trait RootedPosition<IdN> {
fn root(&self) -> IdN;
}
pub trait SolvedPosition<IdN> {
fn node(&self) -> IdN;
}
pub trait WithOffsets
where
Self::Idx: PrimInt,
{
type Idx;
}
pub trait WithPath<IdN>: WithOffsets {
}
pub trait WithPreOrderOffsets: WithOffsets {
type It: Iterator<Item = Self::Idx>;
fn iter(&self) -> Self::It;
}
pub trait WithPreOrderPath<IdN>: WithPath<IdN> + WithPreOrderOffsets {
type ItPath: Iterator<Item = (Self::Idx, IdN)>;
fn iter_offsets_and_nodes(&self) -> Self::ItPath;
}
#[cfg(debug_assertions)]
pub fn assert_invariants_pre<'store, IdN, P, HAST>(p: &P, store: &'store HAST)
where
IdN: std::cmp::Eq + std::hash::Hash + std::fmt::Debug + Clone + NodeId,
P: WithPreOrderPath<IdN> + RootedPosition<IdN>,
HAST: HyperAST<'store, IdN = IdN::IdN, Idx = P::Idx>,
<IdN as NodeId>::IdN: PartialEq<<<IdN as NodeId>::IdN as NodeId>::IdN>,
<IdN as NodeId>::IdN: std::fmt::Debug,
<<IdN as NodeId>::IdN as NodeId>::IdN: std::fmt::Debug,
{
use crate::types::NodeStore;
use std::collections::HashSet;
let mut set: HashSet<IdN> = HashSet::default();
let root = p.root();
let mut prev = root.clone();
let it = p.iter_offsets_and_nodes();
let snd_it = p.iter();
set.insert(root);
for ((o0, x), o1) in it.into_iter().zip(snd_it) {
assert_eq!(o0, o1);
if !set.insert(x.clone()) {
panic!("path returns 2 times the same node")
}
let b = store.node_store().resolve(prev.as_id());
assert_eq!(x.as_id(), &b.child(&o0).expect("should have a child"));
prev = x.clone();
}
}
pub trait WithPostOrderOffsets: WithOffsets {
type It: Iterator<Item = Self::Idx>;
fn iter(&self) -> Self::It;
}
pub trait WithPostOrderPath<IdN>: WithPath<IdN> + WithPostOrderOffsets {
type ItPath: Iterator<Item = (Self::Idx, IdN)>;
fn iter_offsets_and_parents(&self) -> Self::ItPath;
}
#[cfg(debug_assertions)]
pub fn assert_invariants_post<'store, IdN, P, HAST>(p: &P, store: &'store HAST)
where
IdN: std::cmp::Eq + std::hash::Hash + std::fmt::Debug + Clone + NodeId,
P: WithPostOrderPath<IdN> + SolvedPosition<IdN>,
HAST: HyperAST<'store, IdN = IdN::IdN, Idx = P::Idx>,
<IdN as NodeId>::IdN: PartialEq<<<IdN as NodeId>::IdN as NodeId>::IdN>,
<IdN as NodeId>::IdN: std::fmt::Debug,
<<IdN as NodeId>::IdN as NodeId>::IdN: std::fmt::Debug,
{
use crate::types::NodeStore;
use std::collections::HashSet;
let mut set: HashSet<IdN> = HashSet::default();
let node = p.node();
let mut prev = node.clone();
let it = p.iter_offsets_and_parents();
let snd_it = p.iter();
set.insert(node);
for ((o0, x), o1) in it.into_iter().zip(snd_it) {
assert_eq!(o0, o1);
if !set.insert(x.clone()) {
panic!("path returns 2 times the same node")
}
let b = store.node_store().resolve(x.as_id());
assert_eq!(prev.as_id(), &b.child(&o0).expect("should have a child"));
prev = x.clone();
}
}
pub trait WithFullPostOrderPath<IdN>: RootedPosition<IdN> + WithPostOrderPath<IdN> {
fn iter_with_nodes(&self) -> (IdN, Self::ItPath);
}
#[cfg(debug_assertions)]
pub fn assert_invariants_post_full<'store, IdN, P, HAST>(p: &P, store: &'store HAST)
where
IdN: std::cmp::Eq + std::hash::Hash + std::fmt::Debug + Clone + NodeId,
P: WithFullPostOrderPath<IdN>,
HAST: HyperAST<'store, IdN = IdN::IdN, Idx = P::Idx>,
<IdN as NodeId>::IdN: PartialEq<<<IdN as NodeId>::IdN as NodeId>::IdN>,
<IdN as NodeId>::IdN: std::fmt::Debug,
<<IdN as NodeId>::IdN as NodeId>::IdN: std::fmt::Debug,
{
use crate::types::NodeStore;
use std::collections::HashSet;
let mut set: HashSet<IdN> = HashSet::default();
let (node, it) = p.iter_with_nodes();
let mut prev = node.clone();
let snd_it = p.iter_offsets_and_parents();
let third_it = p.iter();
set.insert(node);
for (((o0, x), (o1, y)), o2) in it.into_iter().zip(snd_it).zip(third_it) {
dbg!(&prev, o0);
assert_eq!(x, y);
assert_eq!(o0, o1);
assert_eq!(o2, o1);
if !set.insert(x.clone()) {
panic!("path returns 2 times the same node")
}
let b = store.node_store().resolve(x.as_id());
assert_eq!(prev.as_id(), &b.child(&(o0)).expect("should have a child"));
prev = x.clone();
}
}
pub trait TopoIndexPositionT<IdN>
where
Self::IdI: PrimInt,
{
type IdI;
fn index(&self) -> Self::IdI;
}
pub trait FileAndOffsetPostionT<IdN>
where
Self::IdO: PrimInt,
{
type IdO;
fn file(&self) -> std::path::PathBuf;
fn offset(&self) -> Self::IdO;
fn len(&self) -> Self::IdO;
fn start(&self) -> Self::IdO;
fn end(&self) -> Self::IdO;
}
}
pub struct PositionConverter<'src, SrcPos> {
src: &'src SrcPos,
}
impl<'src, SrcPos> PositionConverter<'src, SrcPos> {
pub fn new(src: &'src SrcPos) -> Self {
Self { src }
}
pub fn with_stores<'store, HAST>(
self,
stores: &'store HAST,
) -> WithHyperAstPositionConverter<'store, 'src, SrcPos, HAST> {
WithHyperAstPositionConverter {
src: self.src,
stores,
}
}
}
pub struct WithHyperAstPositionConverter<'store, 'src, SrcPos, HAST> {
src: &'src SrcPos,
stores: &'store HAST,
}
pub mod building;
pub mod tags {
#[derive(Clone, Copy, Debug)]
pub struct TopDownNoSpace;
#[derive(Clone, Copy, Debug)]
pub struct TopDownFull;
#[derive(Clone, Copy, Debug)]
pub struct BottomUpNoSpace;
#[derive(Clone, Copy, Debug)]
pub struct BottomUpFull;
}
mod node_filter_traits {
pub trait NoSpace {}
pub trait Full {}
}
pub use building::CompoundPositionPreparer;
pub mod offsets;
pub mod file_and_offset;
pub type Position = file_and_offset::Position<PathBuf, usize>;
pub mod offsets_and_nodes;
pub use offsets_and_nodes::*;
mod topological_offset;
pub use topological_offset::*;
mod spaces_related;
pub use spaces_related::{
compute_position_and_nodes_with_no_spaces, compute_position_with_no_spaces,
global_pos_with_spaces, path_with_spaces,
};
mod computing_offset_bottom_up;
mod computing_offset_top_down;
pub use computing_offset_top_down::{compute_position, compute_position_and_nodes, compute_range};
mod computing_path;
pub use computing_path::resolve_range;
mod structural_pos;
pub use structural_pos::{
ExploreStructuralPositions, Scout, SpHandle, StructuralPositionStore, TypedScout,
};
pub type StructuralPosition<IdN = NodeIdentifier, Idx = u16> =
structural_pos::StructuralPosition<IdN, Idx>;