diff --git a/scopegraphs/src/containers/env.rs b/scopegraphs/src/containers/env.rs index 928f59e..2a84687 100644 --- a/scopegraphs/src/containers/env.rs +++ b/scopegraphs/src/containers/env.rs @@ -4,6 +4,8 @@ use futures::future::Shared; use std::hash::Hash; use std::rc::Rc; +use super::ResolveOrUserError; + /// Interface for environment containers that support the operations required for query resolution. pub trait EnvContainer<'sg, 'rslv, LABEL: 'sg, DATA: 'sg>: From> + 'rslv @@ -132,7 +134,7 @@ where } } -impl<'sg: 'rslv, 'rslv, LABEL: 'sg + Eq, DATA: 'sg + Eq, E: 'rslv> +/* impl<'sg: 'rslv, 'rslv, LABEL: 'sg + Eq, DATA: 'sg + Eq, E: 'rslv> Injectable<'sg, 'rslv, LABEL, DATA, Result> for Result, E> where ResolvedPath<'sg, LABEL, DATA>: Hash + Clone, @@ -141,6 +143,20 @@ where fn inject_if(data_ok: Result, path: ResolvedPath<'sg, LABEL, DATA>) -> Self { data_ok.map(|ok| if ok { Env::single(path) } else { Env::empty() }) } +} */ + +impl<'sg: 'rslv, 'rslv, LABEL: 'sg + Eq, DATA: 'sg + Eq, RE, UE> + Injectable<'sg, 'rslv, LABEL, DATA, Result> + for Result, ResolveOrUserError> +where + ResolvedPath<'sg, LABEL, DATA>: Hash + Clone, + ResolveOrUserError: Clone + 'rslv, +{ + fn inject_if(data_ok: Result, path: ResolvedPath<'sg, LABEL, DATA>) -> Self { + data_ok + .map(|ok| if ok { Env::single(path) } else { Env::empty() }) + .map_err(|err| ResolveOrUserError::User(err)) + } } impl<'sg: 'rslv, 'rslv, LABEL: 'sg + Eq, DATA: 'sg + Eq> @@ -202,16 +218,18 @@ where } } -impl<'sg: 'rslv, 'rslv, LABEL: Clone + Eq + 'sg, DATA: Eq + 'sg, E: Clone + 'rslv> - Filterable<'sg, 'rslv, LABEL, DATA, Result> for Result, E> +impl<'sg: 'rslv, 'rslv, LABEL: Clone + Eq + 'sg, DATA: Eq + 'sg, RE, UE> + Filterable<'sg, 'rslv, LABEL, DATA, Result> + for Result, ResolveOrUserError> where Env<'sg, LABEL, DATA>: Clone, ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone, + ResolveOrUserError: Clone + 'rslv, { fn filter( base_env: &Env<'sg, LABEL, DATA>, sub_env: &Env<'sg, LABEL, DATA>, - equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = Result>, + equiv: &'rslv impl DataEquivalence<'sg, DATA, Output = Result>, ) -> Self { let sub_env = sub_env.clone(); sub_env.into_iter().try_fold( @@ -227,10 +245,12 @@ where equiv.data_equiv(p1.data, p2.data) } }, - )?; - // p1 is not shadowed, so add it to accumulator - if !shadowed { - filtered_env.insert(p1); + ); + match shadowed { + // p1 is not shadowed, so add it to accumulator + Ok(false) => filtered_env.insert(p1), + Ok(true) => {} // ignore + Err(err) => return Err(ResolveOrUserError::User(err)), } Ok(filtered_env) @@ -267,3 +287,64 @@ where }) } } + + +#[cfg(test)] +mod test { + use scopegraphs_macros::{label_order, Label}; + + use crate::{completeness::{Delay, ExplicitClose}, containers::ResolveOrUserError, resolve::{DataEquivalence, DataWellformedness, Resolve}, ScopeGraph, Storage}; + + pub mod scopegraphs { + pub use crate::*; + } + + + macro_rules! t { + ($DWFO: ty, $DEQO: ty, $OUT: ty) => { + { + #[derive(Label, Clone, Copy, Debug, PartialEq, Eq, Hash)] + enum Lbl { } + + fn test_dwf<'a>(_ : impl DataWellformedness<'a, u32, Output = $DWFO>) { } + fn test_equiv<'a>(_ : impl DataEquivalence<'a, u32, Output = $DEQO>) { } + + fn some_dwf(_: &u32) -> $DWFO { + todo!() + } + + fn some_equiv(_: &u32, _: &u32) -> $DEQO { + todo!() + } + + + let storage = Storage::new(); + let sg: ScopeGraph = ScopeGraph::new(&storage, ExplicitClose::default()); + + let dwf = some_dwf; + let equiv = some_equiv; + + test_dwf(dwf); + test_equiv(equiv); + + let query: $OUT = sg.query() + .with_path_wellformedness(query_regex!(Lbl: e)) + .with_data_wellformedness(dwf) + .with_data_equivalence(equiv) + // .with_label_order(label_order!(Lbl)) + .resolve(todo!()); + } + }; + } + + #[test] + fn test_type() { + if false { + t![bool, bool, Result<_, Delay<_>>]; + t![Result, bool, Result<_, ResolveOrUserError, ()>>]; + t![bool, Result, Result<_, ResolveOrUserError, ()>>]; + t![Result, Result, Result<_, ResolveOrUserError, ()>>]; + } + } + +} diff --git a/scopegraphs/src/containers/mod.rs b/scopegraphs/src/containers/mod.rs index ef2afc5..57a336c 100644 --- a/scopegraphs/src/containers/mod.rs +++ b/scopegraphs/src/containers/mod.rs @@ -3,7 +3,17 @@ //! Using these interfaces, the resolution algorithms can deal with custom behavior introduced //! by [`Completeness`](crate::completeness::Completeness) implementations. +/// Union of errors during resolution (i.e., delays) and error during predicate evaluation. +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub enum ResolveOrUserError { + /// Resolution error. + Resolve(RE), + /// User error (predicates) + User(UE), +} + mod scope; + pub use scope::*; mod path; diff --git a/scopegraphs/src/containers/scope.rs b/scopegraphs/src/containers/scope.rs index b53a4e8..648aba0 100644 --- a/scopegraphs/src/containers/scope.rs +++ b/scopegraphs/src/containers/scope.rs @@ -26,7 +26,7 @@ pub trait ScopeContainer<'sg, 'rslv, LABEL: Debug + 'sg, DATA: 'sg>: Debug { /// - [Result] of scope containers, and /// - [FutureWrapper] of scope containers. /// ``` -/// # use scopegraphs::containers::ScopeContainerWf; +/// # use scopegraphs::containers::{ResolveOrUserError,ScopeContainerWf}; /// # use scopegraphs::future_wrapper::FutureWrapper; /// # use scopegraphs::Scope; /// # use std::fmt::Debug; @@ -44,10 +44,11 @@ pub trait ScopeContainer<'sg, 'rslv, LABEL: Debug + 'sg, DATA: 'sg>: Debug { /// test::<'_, '_, LABEL, DATA, bool>(vec); /// # } /// -/// # fn result<'sg, 'rslv, LABEL: LBound<'sg>, DATA: DBound<'sg>, E: Debug + Clone>() { -/// let result: Result, E> = todo!(); +/// # fn result<'sg, 'rslv, LABEL: LBound<'sg>, DATA: DBound<'sg>, RE: Debug + Clone + 'rslv, UE: Debug + Clone + 'rslv>() { +/// let result: Result, RE> = todo!(); /// test::<'_, '_, LABEL, DATA, bool>(result); -/// test::<'_, '_, LABEL, DATA, Result>(result); +/// let result_or_err: Result, ResolveOrUserError> = todo!(); +/// test::<'_, '_, LABEL, DATA, Result>(result_or_err); /// # } /// /// # fn future<'sg, 'rslv, LABEL: LBound<'sg>, DATA: DBound<'sg>>() { @@ -70,13 +71,13 @@ pub trait ScopeContainer<'sg, 'rslv, LABEL: Debug + 'sg, DATA: 'sg>: Debug { /// ``` /// /// ```no_run -/// # use scopegraphs::containers::ScopeContainerWf; +/// # use scopegraphs::containers::{ResolveOrUserError, ScopeContainerWf}; /// # use scopegraphs::Scope; /// # use std::fmt::Debug; /// # use std::hash::Hash; /// /// test::<'_, '_, (), (), bool>(Result::<_, ()>::Ok(Vec::::new())); -/// test::<'_, '_, (), (), Result>(Result::<_, ()>::Ok(Vec::::new())); +/// test::<'_, '_, (), (), Result>(Result::<_, ResolveOrUserError<(), ()>>::Ok(Vec::::new())); /// /// fn test<'sg, 'rslv, LABEL: Clone + Hash + Eq + Debug + 'sg, DATA: Hash + Eq + 'sg, DWFO>( /// cont: impl ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DWFO> diff --git a/scopegraphs/src/resolve/lookup.rs b/scopegraphs/src/resolve/lookup.rs index 559972a..f0c7813 100644 --- a/scopegraphs/src/resolve/lookup.rs +++ b/scopegraphs/src/resolve/lookup.rs @@ -342,18 +342,14 @@ where #[cfg(test)] mod tests { + use std::convert::Infallible; + use scopegraphs_macros::label_order; use crate::{ - add_scope, - completeness::{ + add_scope, completeness::{ Delay, ExplicitClose, FutureCompleteness, ImplicitClose, UncheckedCompleteness, - }, - future_wrapper::FutureWrapper, - query_regex, - resolve::{Resolve, ResolvedPath}, - storage::Storage, - Label, ScopeGraph, + }, containers::ResolveOrUserError, future_wrapper::FutureWrapper, query_regex, resolve::{Resolve, ResolvedPath}, storage::Storage, Label, ScopeGraph }; #[derive(Label, Hash, PartialEq, Eq, Debug, Clone, Copy)] @@ -392,7 +388,7 @@ mod tests { |data: &Self| data.matches(n) } - fn matcher_res(n: &'a str) -> impl (for<'b> Fn(&'b Self) -> Result>) { + fn matcher_res(n: &'a str) -> impl (for<'b> Fn(&'b Self) -> Result) { |data: &Self| Ok(data.matches(n)) } @@ -692,7 +688,7 @@ mod tests { let_lex.close(); let_def.close(); - let env = scope_graph + let env: Result<_, ResolveOrUserError<_, Infallible>> = scope_graph .query() .with_path_wellformedness(query_regex!(Lbl: Lex* Imp? Def)) .with_data_wellformedness(TData::matcher_res("x"))