use scopegraphs_prust_lib::hashmap::HashSet as TrieSet;
use std::collections::HashSet;
use std::fmt::{Debug, Formatter};
use std::hash::Hash;
use std::marker::PhantomData;
use std::rc::Rc;
use super::{Scope, ScopeGraph};
mod params;
pub use params::*;
use scopegraphs_regular_expressions::RegexMatcher;
pub mod lookup;
#[derive(Hash, PartialEq, Eq)]
pub enum EdgeOrData<LABEL> {
Data,
Edge(LABEL),
}
impl<LABEL: Debug> Debug for EdgeOrData<LABEL> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
EdgeOrData::Data => write!(f, "$"),
EdgeOrData::Edge(lbl) => write!(f, "@{:?}", lbl),
}
}
}
impl<LABEL: Copy> Clone for EdgeOrData<LABEL> {
fn clone(&self) -> Self {
*self
}
}
impl<LABEL: Copy> Copy for EdgeOrData<LABEL> {}
#[derive(Hash, PartialEq, Eq, Debug)]
enum InnerPath<LABEL> {
Start {
source: Scope,
},
Step {
prefix: Path<LABEL>,
label: LABEL,
target: Scope,
},
}
#[derive(Clone)]
pub struct Path<LABEL> {
inner_path: Rc<InnerPath<LABEL>>,
scopes: Rc<TrieSet<Scope>>,
}
impl<LABEL> PartialEq for Path<LABEL>
where
Scope: PartialEq,
LABEL: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.inner_path == other.inner_path
}
}
impl<LABEL> Eq for Path<LABEL>
where
Scope: Eq,
LABEL: Eq,
{
}
impl<LABEL> Hash for Path<LABEL>
where
Scope: Hash,
LABEL: Hash,
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inner_path.hash(state);
}
}
impl<LABEL> Debug for Path<LABEL>
where
LABEL: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Path")
.field("inner_path", &self.inner_path)
.finish()
}
}
#[derive(Hash, PartialEq, Eq, Debug)]
pub struct ResolvedPath<'sg, LABEL, DATA> {
path: Path<LABEL>,
data: &'sg DATA,
}
impl<'sg, LABEL: Clone, DATA> Clone for ResolvedPath<'sg, LABEL, DATA> {
fn clone(&self) -> Self {
Self {
path: self.path.clone(),
data: self.data,
}
}
}
impl<'sg, LABEL, DATA> ResolvedPath<'sg, LABEL, DATA> {
pub fn path(&self) -> &Path<LABEL> {
&self.path
}
pub fn data(&self) -> &DATA {
self.data
}
}
impl<LABEL> Path<LABEL> {
pub fn new(source: Scope) -> Self {
Self {
inner_path: Rc::new(InnerPath::Start { source }),
scopes: Rc::new(TrieSet::new().insert(source)),
}
}
pub fn target(&self) -> Scope {
match self.inner_path.as_ref() {
InnerPath::Start { source } => *source,
InnerPath::Step { target, .. } => *target,
}
}
pub fn step(&self, label: LABEL, target: Scope) -> Option<Self> {
if self.scopes.search(&target) {
None
} else {
Some(Self {
inner_path: Rc::new(InnerPath::Step {
prefix: Self {
inner_path: self.inner_path.clone(),
scopes: self.scopes.clone(),
},
label,
target,
}),
scopes: Rc::new(self.scopes.insert(target)),
})
}
}
pub fn resolve<DATA>(self, data: &DATA) -> ResolvedPath<'_, LABEL, DATA> {
ResolvedPath { path: self, data }
}
}
#[derive(Debug)]
pub struct Env<'sg, LABEL: 'sg, DATA>(HashSet<ResolvedPath<'sg, LABEL, DATA>>);
impl<'sg, LABEL, DATA> IntoIterator for Env<'sg, LABEL, DATA> {
type Item = ResolvedPath<'sg, LABEL, DATA>;
type IntoIter = <HashSet<ResolvedPath<'sg, LABEL, DATA>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<LABEL, DATA> Default for Env<'_, LABEL, DATA> {
fn default() -> Self {
Self::new()
}
}
impl<'sg, LABEL, DATA> Env<'sg, LABEL, DATA> {
pub fn new() -> Self {
Self(HashSet::new())
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a ResolvedPath<'sg, LABEL, DATA>> + 'a {
self.0.iter()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl<'sg, LABEL, DATA> Env<'sg, LABEL, DATA>
where
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
{
pub fn single(path: ResolvedPath<'sg, LABEL, DATA>) -> Self {
let mut env = Env::new();
env.insert(path);
env
}
pub fn insert(&mut self, path: ResolvedPath<'sg, LABEL, DATA>) {
self.0.insert(path);
}
pub fn merge(&mut self, other: &Self) {
self.0.extend(other.0.iter().cloned())
}
}
impl<'sg, LABEL: 'sg, DATA: Hash> FromIterator<ResolvedPath<'sg, LABEL, DATA>>
for Env<'sg, LABEL, DATA>
where
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash,
{
fn from_iter<T: IntoIterator<Item = ResolvedPath<'sg, LABEL, DATA>>>(iter: T) -> Self {
Env(HashSet::from_iter(iter))
}
}
impl<'sg, LABEL: 'sg, DATA: Hash> FromIterator<Env<'sg, LABEL, DATA>> for Env<'sg, LABEL, DATA>
where
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash,
{
fn from_iter<T: IntoIterator<Item = Env<'sg, LABEL, DATA>>>(iter: T) -> Self {
iter.into_iter().flatten().collect()
}
}
impl<'sg, LABEL: 'sg + Clone, DATA> Clone for Env<'sg, LABEL, DATA> {
fn clone(&self) -> Self {
Env(self.0.clone())
}
}
pub trait Resolve<'sg, 'rslv> {
type EnvContainer
where
'sg: 'rslv,
Self: 'rslv;
fn resolve(&'rslv self, scope: Scope) -> Self::EnvContainer;
}
pub struct Query<'storage, 'sg, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq> {
_phantom: PhantomData<&'rslv ()>,
scope_graph: &'sg ScopeGraph<'storage, LABEL, DATA, CMPL>,
path_wellformedness: PWF,
data_wellformedness: DWF,
label_order: LO,
data_equivalence: DEq,
}
impl<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, DEq>
{
pub fn with_path_wellformedness<NPWF>(
self,
new_path_wellformedness: NPWF,
) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, NPWF, DWF, LO, DEq>
where
NPWF: for<'a> RegexMatcher<&'a LABEL> + 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self.scope_graph,
path_wellformedness: new_path_wellformedness,
data_wellformedness: self.data_wellformedness,
label_order: self.label_order,
data_equivalence: self.data_equivalence,
}
}
pub fn with_data_wellformedness<NDWF>(
self,
new_data_wellformedness: NDWF,
) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, NDWF, LO, DEq>
where
NDWF: DataWellformedness<DATA> + 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self.scope_graph,
path_wellformedness: self.path_wellformedness,
data_wellformedness: new_data_wellformedness,
label_order: self.label_order,
data_equivalence: self.data_equivalence,
}
}
pub fn with_label_order<NLO>(
self,
new_label_order: NLO,
) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, NLO, DEq>
where
NLO: LabelOrder<LABEL> + 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self.scope_graph,
path_wellformedness: self.path_wellformedness,
data_wellformedness: self.data_wellformedness,
label_order: new_label_order,
data_equivalence: self.data_equivalence,
}
}
pub fn with_data_equivalence<NDEq>(
self,
new_data_equivalence: NDEq,
) -> Query<'sg, 'storage, 'rslv, LABEL, DATA, CMPL, PWF, DWF, LO, NDEq>
where
NDEq: DataEquiv<DATA> + 'rslv,
{
Query {
_phantom: PhantomData,
scope_graph: self.scope_graph,
path_wellformedness: self.path_wellformedness,
data_wellformedness: self.data_wellformedness,
label_order: self.label_order,
data_equivalence: new_data_equivalence,
}
}
}
impl<'storage, LABEL, DATA, CMPL> ScopeGraph<'storage, LABEL, DATA, CMPL> {
pub fn query<'sg>(
&'sg self,
) -> Query<
'storage,
'sg,
'_,
LABEL,
DATA,
CMPL,
(),
DefaultDataWellformedness,
DefaultLabelOrder,
DefaultDataEquiv,
>
where
'storage: 'sg,
{
Query {
_phantom: PhantomData,
scope_graph: self,
path_wellformedness: (),
data_wellformedness: DefaultDataWellformedness::default(),
label_order: DefaultLabelOrder::default(),
data_equivalence: DefaultDataEquiv::default(),
}
}
}