From 46fe82b044f8b3ac58d1e62ced7a4df9f5585814 Mon Sep 17 00:00:00 2001 From: Aron Zwaan Date: Wed, 30 Oct 2024 10:08:57 +0100 Subject: [PATCH 1/5] Propagate user errors --- scopegraphs/src/containers/env.rs | 34 ++++++++++++++++++++++++------- scopegraphs/src/containers/mod.rs | 6 ++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/scopegraphs/src/containers/env.rs b/scopegraphs/src/containers/env.rs index 928f59e..48d812d 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 @@ -143,6 +145,20 @@ where } } +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::Resolve(err)) + } +} + impl<'sg: 'rslv, 'rslv, LABEL: 'sg + Eq, DATA: 'sg + Eq> Injectable<'sg, 'rslv, LABEL, DATA, FutureWrapper<'rslv, bool>> for FutureWrapper<'rslv, Env<'sg, LABEL, DATA>> @@ -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) diff --git a/scopegraphs/src/containers/mod.rs b/scopegraphs/src/containers/mod.rs index ef2afc5..b062555 100644 --- a/scopegraphs/src/containers/mod.rs +++ b/scopegraphs/src/containers/mod.rs @@ -3,7 +3,13 @@ //! Using these interfaces, the resolution algorithms can deal with custom behavior introduced //! by [`Completeness`](crate::completeness::Completeness) implementations. +enum ResolveOrUserError { + Resolve(RE), + User(UE), +} + mod scope; + pub use scope::*; mod path; From 558c44b9c89a6667aded3718546d67d3de4b2fc8 Mon Sep 17 00:00:00 2001 From: Aron Zwaan Date: Wed, 30 Oct 2024 10:15:05 +0100 Subject: [PATCH 2/5] Make error type public --- scopegraphs/src/containers/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scopegraphs/src/containers/mod.rs b/scopegraphs/src/containers/mod.rs index b062555..62ef5a4 100644 --- a/scopegraphs/src/containers/mod.rs +++ b/scopegraphs/src/containers/mod.rs @@ -3,8 +3,11 @@ //! Using these interfaces, the resolution algorithms can deal with custom behavior introduced //! by [`Completeness`](crate::completeness::Completeness) implementations. -enum ResolveOrUserError { +/// Union of errors during resolution (i.e., delays) and error during predicate evaluation. +pub enum ResolveOrUserError { + /// Resolution error. Resolve(RE), + /// User error (predicates) User(UE), } From 08b8b38fb743a8617bbb7d6704d7c2ec8b2f8048 Mon Sep 17 00:00:00 2001 From: Aron Zwaan Date: Wed, 30 Oct 2024 10:43:49 +0100 Subject: [PATCH 3/5] WIP error bounds --- scopegraphs/src/containers/env.rs | 4 ++-- scopegraphs/src/containers/mod.rs | 1 + scopegraphs/src/containers/scope.rs | 13 +++++++------ scopegraphs/src/resolve/lookup.rs | 20 ++++++++------------ 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/scopegraphs/src/containers/env.rs b/scopegraphs/src/containers/env.rs index 48d812d..59f19aa 100644 --- a/scopegraphs/src/containers/env.rs +++ b/scopegraphs/src/containers/env.rs @@ -134,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, @@ -143,7 +143,7 @@ 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> diff --git a/scopegraphs/src/containers/mod.rs b/scopegraphs/src/containers/mod.rs index 62ef5a4..57a336c 100644 --- a/scopegraphs/src/containers/mod.rs +++ b/scopegraphs/src/containers/mod.rs @@ -4,6 +4,7 @@ //! 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), 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..0ed3b5b 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)) } @@ -658,7 +654,7 @@ mod tests { // todo!("assert the correct edges are closed!") } - #[test] + /* #[test] fn test_label_order_complex_explicit_close() { let storage = Storage::new(); let scope_graph: ScopeGraph> = @@ -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")) @@ -707,7 +703,7 @@ mod tests { assert!(matches!(path.data(), &Data { name: "x", data: 2 })); // todo!("assert the correct edges are closed!") - } + }*/ #[test] fn test_caching() { From 209e0b3dd4159308ff54d383e9a3328a75c71328 Mon Sep 17 00:00:00 2001 From: Aron Zwaan Date: Wed, 6 Nov 2024 10:37:25 +0100 Subject: [PATCH 4/5] WIP result-based interface --- scopegraphs/src/containers/env.rs | 6 +++--- scopegraphs/src/resolve/lookup.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scopegraphs/src/containers/env.rs b/scopegraphs/src/containers/env.rs index 59f19aa..030853c 100644 --- a/scopegraphs/src/containers/env.rs +++ b/scopegraphs/src/containers/env.rs @@ -146,16 +146,16 @@ where } */ impl<'sg: 'rslv, 'rslv, LABEL: 'sg + Eq, DATA: 'sg + Eq, RE, UE> - Injectable<'sg, 'rslv, LABEL, DATA, Result> + 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 { + 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::Resolve(err)) + .map_err(|err| ResolveOrUserError::User(err)) } } diff --git a/scopegraphs/src/resolve/lookup.rs b/scopegraphs/src/resolve/lookup.rs index 0ed3b5b..f0c7813 100644 --- a/scopegraphs/src/resolve/lookup.rs +++ b/scopegraphs/src/resolve/lookup.rs @@ -654,7 +654,7 @@ mod tests { // todo!("assert the correct edges are closed!") } - /* #[test] + #[test] fn test_label_order_complex_explicit_close() { let storage = Storage::new(); let scope_graph: ScopeGraph> = @@ -703,7 +703,7 @@ mod tests { assert!(matches!(path.data(), &Data { name: "x", data: 2 })); // todo!("assert the correct edges are closed!") - }*/ + } #[test] fn test_caching() { From b79f946633e8350a220b72fd9f9619fc59a79c74 Mon Sep 17 00:00:00 2001 From: Aron Zwaan Date: Mon, 18 Nov 2024 16:35:03 +0100 Subject: [PATCH 5/5] Add tests --- scopegraphs/src/containers/env.rs | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/scopegraphs/src/containers/env.rs b/scopegraphs/src/containers/env.rs index 030853c..2a84687 100644 --- a/scopegraphs/src/containers/env.rs +++ b/scopegraphs/src/containers/env.rs @@ -287,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, ()>>]; + } + } + +}