diff --git a/scopegraphs/src/containers/env.rs b/scopegraphs/src/containers/env.rs index 0937f45..261fed2 100644 --- a/scopegraphs/src/containers/env.rs +++ b/scopegraphs/src/containers/env.rs @@ -165,63 +165,58 @@ where } } -// Shadowable +// Filtering -/// Sub trait of [EnvContainer] that validates that shadowin operations can be applied on it. -pub trait Shadowable<'sg, 'rslv, LABEL: 'sg, DATA: 'sg, DEQO>: +/// Sub trait of [EnvContainer] that validates that filtering operations (for shadowing) can be applied on it. +pub trait Filterable<'sg, 'rslv, LABEL: 'sg, DATA: 'sg, DEQO>: EnvContainer<'sg, 'rslv, LABEL, DATA> where ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone, { /// Implementation of the shadow operation on this container. - fn shadow( - base_env: Env<'sg, LABEL, DATA>, + fn filter( + base_env: &Env<'sg, LABEL, DATA>, sub_env: &Env<'sg, LABEL, DATA>, equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = DEQO>, ) -> Self; } -impl<'sg: 'rslv, 'rslv, LABEL: 'sg, DATA: 'sg, ENVC> Shadowable<'sg, 'rslv, LABEL, DATA, bool> +impl<'sg: 'rslv, 'rslv, LABEL: 'sg, DATA: 'sg, ENVC> Filterable<'sg, 'rslv, LABEL, DATA, bool> for ENVC where ENVC: EnvContainer<'sg, 'rslv, LABEL, DATA>, Env<'sg, LABEL, DATA>: Clone, ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone, { - fn shadow( - base_env: Env<'sg, LABEL, DATA>, + fn filter( + base_env: &Env<'sg, LABEL, DATA>, sub_env: &Env<'sg, LABEL, DATA>, equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = bool>, ) -> Self { - let filtered_env = sub_env + sub_env .iter() .filter(|p1| !base_env.iter().any(|p2| equiv.data_equiv(p1.data, p2.data))) - .collect::>(); - - // FIXME: factor out this part? - let mut new_env = base_env; - for path in filtered_env { - new_env.insert(path.clone()) - } - new_env.into() + .cloned() + .collect::>() + .into() } } impl<'sg: 'rslv, 'rslv, LABEL: Clone + Eq + 'sg, DATA: Eq + 'sg, E: Clone + 'rslv> - Shadowable<'sg, 'rslv, LABEL, DATA, Result> for Result, E> + Filterable<'sg, 'rslv, LABEL, DATA, Result> for Result, E> where Env<'sg, LABEL, DATA>: Clone, ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone, { - fn shadow( - base_env: Env<'sg, LABEL, DATA>, + fn filter( + base_env: &Env<'sg, LABEL, DATA>, sub_env: &Env<'sg, LABEL, DATA>, equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = Result>, ) -> Self { let sub_env = sub_env.clone(); - let filtered_env = sub_env.into_iter().try_fold( - Vec::>::new(), - |mut filtered_env: Vec>, + sub_env.into_iter().try_fold( + Env::new(), + |mut filtered_env: Env<'sg, LABEL, DATA>, p1: ResolvedPath<'sg, LABEL, DATA>| { let shadowed = base_env.iter().try_fold( /* initially, not shadowed */ false, @@ -236,48 +231,40 @@ where )?; // p1 is not shadowed, so add it to accumulator if !shadowed { - filtered_env.push(p1); + filtered_env.insert(p1); } Ok(filtered_env) }, - )?; - let mut new_env = base_env; - filtered_env - .into_iter() - .for_each(|path| new_env.insert(path)); - new_env.into() + ) } } impl<'sg: 'rslv, 'rslv, LABEL: Clone + Eq + 'sg, DATA: Eq + 'sg> - Shadowable<'sg, 'rslv, LABEL, DATA, FutureWrapper<'rslv, bool>> + Filterable<'sg, 'rslv, LABEL, DATA, FutureWrapper<'rslv, bool>> for FutureWrapper<'rslv, Env<'sg, LABEL, DATA>> where Env<'sg, LABEL, DATA>: Clone, ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone, { - fn shadow( - base_env: Env<'sg, LABEL, DATA>, + fn filter( + base_env: &Env<'sg, LABEL, DATA>, sub_env: &Env<'sg, LABEL, DATA>, equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = FutureWrapper<'rslv, bool>>, ) -> Self { + let base_env = base_env.clone(); let sub_env = sub_env.clone(); FutureWrapper::new(async move { - let mut filtered_env: Vec> = Vec::new(); + let mut filtered_env = Env::new(); 'outer: for sub_path in sub_env { for base_path in &base_env { if equiv.data_equiv(sub_path.data, base_path.data).await { continue 'outer; } } - filtered_env.push(sub_path.clone()); - } - let mut new_env = base_env; - for path in filtered_env { - new_env.insert(path); + filtered_env.insert(sub_path.clone()); } - new_env + filtered_env }) } } diff --git a/scopegraphs/src/containers/path.rs b/scopegraphs/src/containers/path.rs index 9257725..9ec306b 100644 --- a/scopegraphs/src/containers/path.rs +++ b/scopegraphs/src/containers/path.rs @@ -4,7 +4,7 @@ use futures::future::join_all; use std::fmt::Debug; use std::hash::Hash; -use super::{Injectable, Shadowable}; +use super::{Injectable, Filterable}; /// Interface for path containers that support the operations required for query resolution. pub trait PathContainer<'sg, 'rslv, LABEL: 'sg, DATA: 'sg>: Debug + 'rslv { @@ -26,7 +26,7 @@ where { /// Witness that ```Self::EnvContainer``` is a valid environment container. type EnvContainerWf: Injectable<'sg, 'rslv, LABEL, DATA, DWFO> - + Shadowable<'sg, 'rslv, LABEL, DATA, DEQO>; + + Filterable<'sg, 'rslv, LABEL, DATA, DEQO>; } impl<'sg, 'rslv, LABEL, DATA, DWFO, DEQO, T> PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO> @@ -36,7 +36,7 @@ where DATA: 'sg, T: PathContainer<'sg, 'rslv, LABEL, DATA>, Self::EnvContainer: - Injectable<'sg, 'rslv, LABEL, DATA, DWFO> + Shadowable<'sg, 'rslv, LABEL, DATA, DEQO>, + Injectable<'sg, 'rslv, LABEL, DATA, DWFO> + Filterable<'sg, 'rslv, LABEL, DATA, DEQO>, ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone, { type EnvContainerWf = Self::EnvContainer; diff --git a/scopegraphs/src/resolve/lookup.rs b/scopegraphs/src/resolve/lookup.rs index 0d70359..62cb350 100644 --- a/scopegraphs/src/resolve/lookup.rs +++ b/scopegraphs/src/resolve/lookup.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use crate::completeness::Completeness; use crate::containers::{ EnvContainer, Injectable, PathContainer, PathContainerWf, ScopeContainer, ScopeContainerWf, - Shadowable, + Filterable, }; use crate::resolve::{ DataEquivalence, DataWellformedness, EdgeOrData, LabelOrder, Path, Query, Resolve, ResolvedPath, @@ -224,10 +224,14 @@ where if !base_env.is_empty() && local_self.data_equiv.always_equivalent() { base_env.clone().into() } else { - let base_env = base_env.clone(); + let mut base_env = base_env.clone(); let sub_env = local_self.resolve_edge(path_wellformedness.clone(), edge, path); sub_env.flat_map(move |sub_env| { - Shadowable::shadow(base_env, sub_env, local_self.data_equiv) + let merged_env: EnvC<'sg, 'rslv, CMPL, LABEL, DATA, DWF::Output, DEq::Output> = Filterable::filter(&base_env, sub_env, local_self.data_equiv); + merged_env.flat_map(move |merged_env| { + base_env.merge(merged_env); + base_env.into() + }) }) } })) diff --git a/scopegraphs/src/resolve/mod.rs b/scopegraphs/src/resolve/mod.rs index d231551..002a1ba 100644 --- a/scopegraphs/src/resolve/mod.rs +++ b/scopegraphs/src/resolve/mod.rs @@ -372,7 +372,7 @@ where } } -impl<'sg, LABEL: 'sg, DATA: Hash> FromIterator> +impl<'sg, LABEL: 'sg, DATA> FromIterator> for Env<'sg, LABEL, DATA> where ResolvedPath<'sg, LABEL, DATA>: Eq + Hash,