Skip to content

Commit 677b3c4

Browse files
committed
Trait for shadow operation
1 parent 05b9ca9 commit 677b3c4

File tree

5 files changed

+163
-76
lines changed

5 files changed

+163
-76
lines changed

scopegraphs/src/containers/env.rs

+97-36
Original file line numberDiff line numberDiff line change
@@ -165,58 +165,119 @@ where
165165
}
166166
}
167167

168-
// Mergeable
168+
// Shadowable
169169

170-
/// Environment Container in which a path can be injected based on a condition.
171-
pub trait Mergable<'sg, 'rslv, LABEL: 'sg, DATA: 'sg, DEQO>:
170+
/// Sub trait of [EnvContainer] that validates that shadowin operations can be applied on it.
171+
pub trait Shadowable<'sg, 'rslv, LABEL: 'sg, DATA: 'sg, DEQO>:
172172
EnvContainer<'sg, 'rslv, LABEL, DATA>
173173
where
174174
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
175175
{
176-
/// Creates a new environment that contains path when `data_ok` is `true`, and is empty otherwise.
177-
fn merge_if(
178-
&self,
179-
data_equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = DEQO>,
180-
sub_env: Self,
176+
/// Implementation of the shadow operation on this container.
177+
fn shadow(
178+
base_env: Env<'sg, LABEL, DATA>,
179+
sub_env: &Env<'sg, LABEL, DATA>,
180+
equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = DEQO>,
181181
) -> Self;
182182
}
183183

184-
impl<'sg: 'rslv, 'rslv, LABEL: Eq + 'sg, DATA: Eq + 'sg, ENVC>
185-
Mergable<'sg, 'rslv, LABEL, DATA, bool> for ENVC
184+
impl<'sg: 'rslv, 'rslv, LABEL: 'sg, DATA: 'sg, ENVC> Shadowable<'sg, 'rslv, LABEL, DATA, bool>
185+
for ENVC
186186
where
187187
ENVC: EnvContainer<'sg, 'rslv, LABEL, DATA>,
188188
Env<'sg, LABEL, DATA>: Clone,
189189
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
190190
{
191-
fn merge_if(
192-
&self,
193-
data_equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = bool>,
194-
sub_env: Self,
191+
fn shadow(
192+
base_env: Env<'sg, LABEL, DATA>,
193+
sub_env: &Env<'sg, LABEL, DATA>,
194+
equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = bool>,
195195
) -> Self {
196-
let base_env = self;
197-
base_env.flat_map(move |base_env| {
198-
if !base_env.is_empty() && data_equiv.always_equivalent() {
199-
<ENVC as From<Env<'sg, LABEL, DATA>>>::from(base_env.clone())
200-
} else {
201-
let base_env = base_env.clone();
202-
203-
sub_env.flat_map(move |sub_env| {
204-
let filtered_env = sub_env
205-
.iter()
206-
.filter(|p1| {
207-
!base_env
208-
.iter()
209-
.any(|p2| data_equiv.data_equiv(p1.data, p2.data))
210-
})
211-
.collect::<Vec<_>>();
212-
213-
let mut new_env = base_env;
214-
for path in filtered_env {
215-
new_env.insert(path.clone())
196+
let filtered_env = sub_env
197+
.iter()
198+
.filter(|p1| !base_env.iter().any(|p2| equiv.data_equiv(p1.data, p2.data)))
199+
.collect::<Vec<_>>();
200+
201+
// FIXME: factor out this part?
202+
let mut new_env = base_env;
203+
for path in filtered_env {
204+
new_env.insert(path.clone())
205+
}
206+
new_env.into()
207+
}
208+
}
209+
210+
impl<'sg: 'rslv, 'rslv, LABEL: Clone + Eq + 'sg, DATA: Eq + 'sg, E: Clone + 'rslv>
211+
Shadowable<'sg, 'rslv, LABEL, DATA, Result<bool, E>> for Result<Env<'sg, LABEL, DATA>, E>
212+
where
213+
Env<'sg, LABEL, DATA>: Clone,
214+
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
215+
{
216+
fn shadow(
217+
base_env: Env<'sg, LABEL, DATA>,
218+
sub_env: &Env<'sg, LABEL, DATA>,
219+
equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = Result<bool, E>>,
220+
) -> Self {
221+
let sub_env = sub_env.clone();
222+
let filtered_env = sub_env.into_iter().try_fold(
223+
Vec::<ResolvedPath<'sg, LABEL, DATA>>::new(),
224+
|mut filtered_env: Vec<ResolvedPath<'sg, LABEL, DATA>>,
225+
p1: ResolvedPath<'sg, LABEL, DATA>| {
226+
let shadowed = base_env.iter().try_fold(
227+
/* initially, not shadowed */ false,
228+
|previously_shadowed: bool, p2: &ResolvedPath<'sg, LABEL, DATA>| {
229+
if previously_shadowed {
230+
Ok(true) // if it was shadowed, it will be
231+
} else {
232+
// not yet shadowed, try if current path shadows
233+
equiv.data_equiv(p1.data, p2.data)
234+
}
235+
},
236+
)?;
237+
// p1 is not shadowed, so add it to accumulator
238+
if !shadowed {
239+
filtered_env.push(p1);
240+
}
241+
242+
Ok(filtered_env)
243+
},
244+
)?;
245+
let mut new_env = base_env;
246+
filtered_env
247+
.into_iter()
248+
.for_each(|path| new_env.insert(path));
249+
new_env.into()
250+
}
251+
}
252+
253+
impl<'sg: 'rslv, 'rslv, LABEL: Clone + Eq + 'sg, DATA: Eq + 'sg>
254+
Shadowable<'sg, 'rslv, LABEL, DATA, FutureWrapper<'rslv, bool>>
255+
for FutureWrapper<'rslv, Env<'sg, LABEL, DATA>>
256+
where
257+
Env<'sg, LABEL, DATA>: Clone,
258+
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
259+
{
260+
fn shadow(
261+
base_env: Env<'sg, LABEL, DATA>,
262+
sub_env: &Env<'sg, LABEL, DATA>,
263+
equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = FutureWrapper<'rslv, bool>>,
264+
) -> Self {
265+
let sub_env = sub_env.clone();
266+
FutureWrapper::new(async move {
267+
let mut filtered_env: Vec<ResolvedPath<'sg, LABEL, DATA>> = Vec::new();
268+
'outer: for sub_path in sub_env {
269+
for base_path in &base_env {
270+
if equiv.data_equiv(sub_path.data, base_path.data).await {
271+
continue 'outer;
216272
}
217-
new_env.into()
218-
})
273+
}
274+
filtered_env.push(sub_path.clone());
275+
}
276+
let mut new_env = base_env;
277+
for path in filtered_env {
278+
new_env.insert(path);
219279
}
280+
new_env
220281
})
221282
}
222283
}

scopegraphs/src/containers/path.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use futures::future::join_all;
44
use std::fmt::Debug;
55
use std::hash::Hash;
66

7-
use super::{Injectable, Mergable};
7+
use super::{Injectable, Shadowable};
88

99
/// Interface for path containers that support the operations required for query resolution.
1010
pub trait PathContainer<'sg, 'rslv, LABEL: 'sg, DATA: 'sg>: Debug + 'rslv {
@@ -19,23 +19,24 @@ pub trait PathContainer<'sg, 'rslv, LABEL: 'sg, DATA: 'sg>: Debug + 'rslv {
1919
}
2020

2121
/// Trait that is auto-implemented for any [PathContainer] implementation that yields a valid [EnvContainer].
22-
pub trait PathContainerWf<'sg, 'rslv, LABEL: 'sg, DATA: 'sg, DWFO>:
22+
pub trait PathContainerWf<'sg, 'rslv, LABEL: 'sg, DATA: 'sg, DWFO, DEQO>:
2323
PathContainer<'sg, 'rslv, LABEL, DATA, EnvContainer = Self::EnvContainerWf>
2424
where
2525
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
2626
{
2727
/// Witness that ```Self::EnvContainer``` is a valid environment container.
2828
type EnvContainerWf: Injectable<'sg, 'rslv, LABEL, DATA, DWFO>
29-
+ Mergable<'sg, 'rslv, LABEL, DATA, bool>;
29+
+ Shadowable<'sg, 'rslv, LABEL, DATA, DEQO>;
3030
}
3131

32-
impl<'sg, 'rslv, LABEL, DATA, DWFO, T> PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO> for T
32+
impl<'sg, 'rslv, LABEL, DATA, DWFO, DEQO, T> PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>
33+
for T
3334
where
3435
LABEL: Debug + 'sg,
3536
DATA: 'sg,
3637
T: PathContainer<'sg, 'rslv, LABEL, DATA>,
3738
Self::EnvContainer:
38-
Injectable<'sg, 'rslv, LABEL, DATA, DWFO> + Mergable<'sg, 'rslv, LABEL, DATA, bool>,
39+
Injectable<'sg, 'rslv, LABEL, DATA, DWFO> + Shadowable<'sg, 'rslv, LABEL, DATA, DEQO>,
3940
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
4041
{
4142
type EnvContainerWf = Self::EnvContainer;

scopegraphs/src/containers/scope.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -83,23 +83,24 @@ pub trait ScopeContainer<'sg, 'rslv, LABEL: Debug + 'sg, DATA: 'sg>: Debug {
8383
/// }
8484
/// ```
8585
///
86-
pub trait ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO>:
86+
pub trait ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>:
8787
ScopeContainer<'sg, 'rslv, LABEL, DATA, PathContainer = Self::PathContainerWf>
8888
where
8989
LABEL: Debug + 'sg,
9090
DATA: 'sg,
9191
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
9292
{
9393
/// Refinement of `Self::PathContainer`, carrying proof that this scope container resolves to valid path containers.
94-
type PathContainerWf: PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO>;
94+
type PathContainerWf: PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>;
9595
}
9696

97-
impl<'sg, 'rslv, LABEL, DATA, DWFO, T> ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO> for T
97+
impl<'sg, 'rslv, LABEL, DATA, DWFO, DEQO, T> ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>
98+
for T
9899
where
99100
LABEL: Debug + 'sg,
100101
DATA: 'sg,
101102
T: ScopeContainer<'sg, 'rslv, LABEL, DATA>,
102-
Self::PathContainer: PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO>,
103+
Self::PathContainer: PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>,
103104
ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
104105
{
105106
type PathContainerWf = Self::PathContainer;

0 commit comments

Comments
 (0)