diff --git a/syndicate/src/dataspace.rs b/syndicate/src/dataspace.rs index dcc6387..8e49016 100644 --- a/syndicate/src/dataspace.rs +++ b/syndicate/src/dataspace.rs @@ -1,4 +1,5 @@ -//! Implements a [*dataspace*](#GarnockJones2017) entity. +//! Implements a [*dataspace*][crate::dataspace#GarnockJones2017] +//! entity. //! //! **References.** //! diff --git a/syndicate/src/error.rs b/syndicate/src/error.rs index 28b51f9..e13c0e6 100644 --- a/syndicate/src/error.rs +++ b/syndicate/src/error.rs @@ -1,5 +1,8 @@ -pub use super::schemas::internal_protocol::_Any; -pub use super::schemas::internal_protocol::_Ptr; +//! Actor errors. + +use super::schemas::internal_protocol::_Any; + +#[doc(inline)] pub use super::schemas::internal_protocol::Error; use preserves::value::NestedValue; @@ -14,6 +17,9 @@ impl std::fmt::Display for Error { } } +/// Construct an [`Error`] with the given `message` and `detail`. +/// +/// When no relevant detail exists, convention is to set `detail` to `false`. pub fn error(message: &str, detail: Detail) -> Error where _Any: From { Error { message: message.to_owned(), @@ -21,6 +27,12 @@ pub fn error(message: &str, detail: Detail) -> Error where _Any: From) -> _Any { match result { Ok(()) => { diff --git a/syndicate/src/lib.rs b/syndicate/src/lib.rs index 0413d48..5f8e565 100644 --- a/syndicate/src/lib.rs +++ b/syndicate/src/lib.rs @@ -8,11 +8,14 @@ pub mod bag; pub mod dataspace; pub mod during; pub mod error; +#[doc(hidden)] pub mod pattern; pub mod relay; pub mod rewrite; pub mod schemas { + //! Auto-generated codecs for [Syndicate protocol + //! schemas](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols/src/branch/main/schemas). include!(concat!(env!("OUT_DIR"), "/src/schemas/mod.rs")); } diff --git a/syndicate/src/rewrite.rs b/syndicate/src/rewrite.rs index b6f3c0d..207334b 100644 --- a/syndicate/src/rewrite.rs +++ b/syndicate/src/rewrite.rs @@ -1,3 +1,6 @@ +//! The implementation of [capability attenuation][crate::actor::Cap]: +//! filtering and rewriting of assertions and messages. + use preserves::value::Map; use preserves::value::NestedValue; use preserves::value::Value; @@ -6,33 +9,50 @@ use std::convert::TryFrom; use super::schemas::sturdy::*; +/// A triple of (1) the count of bindings captured by (2) a checked +/// `Pattern`, plus (3) a checked `Template`. pub type CheckedRewrite = (usize, Pattern, Template); +/// A safety-checked [`Caveat`]: none of the errors enumerated in +/// `CaveatError` apply. #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct CheckedCaveat { alts: Vec } +/// Represents any detected error in a [`Caveat`]; that is, in a +/// [`Pattern`] or a [`Template`]. #[derive(Debug)] pub enum CaveatError { + /// A template refers to a binding not present in the corresponding pattern. UnboundRef, + /// A pattern includes a negation of a subpattern that includes a binding. BindingUnderNegation, + /// A constructor specification includes an arity that exceeds the range of a [`usize`]. LudicrousArity, + /// A member index in a compound pattern exceeds the arity limit of the constructor. IndexOutOfBounds, + /// A member index for a sequence-like compound is not an integer. InvalidIndex, + /// A compound template does not specify a subtemplate for each of + /// the slots of the compound value being constructed. IncompleteTemplate, } impl Attenuation { + /// Yields `Ok(())` iff `self` has no [`CaveatError`]. pub fn validate(&self) -> Result<(), CaveatError> { for c in &self.0 { c.validate()? } Ok(()) } + /// Yields a vector of [`CheckedCaveat`s][CheckedCaveat] iff + /// `self` has no [`CaveatError`]. pub fn check(&self) -> Result, CaveatError> { self.0.iter().map(Caveat::check).collect() } } impl Caveat { + /// Yields `Ok(())` iff `self` has no [`CaveatError`]. pub fn validate(&self) -> Result<(), CaveatError> { match self { Caveat::Rewrite(b) => (&**b).validate(), @@ -40,6 +60,7 @@ impl Caveat { } } + /// Yields a [`CheckedCaveat`] iff `self` has no [`CaveatError`]. pub fn check(&self) -> Result { match self { Caveat::Rewrite(b) => @@ -313,6 +334,7 @@ impl Rewrite { } impl CheckedCaveat { + /// Rewrites `a` using the patterns/templates contained in `self`. pub fn rewrite(&self, a: &_Any) -> Option<_Any> { for (n, p, t) in &self.alts { let mut bindings = Vec::with_capacity(*n); diff --git a/syndicate/src/skeleton.rs b/syndicate/src/skeleton.rs index 7865551..7d88d57 100644 --- a/syndicate/src/skeleton.rs +++ b/syndicate/src/skeleton.rs @@ -1,3 +1,10 @@ +//! High-speed index over a set of assertions and a set of +//! [`Observe`rs][crate::schemas::dataspace::Observe] of those +//! assertions. +//! +//! Generally speaking, you will not need to use this module; instead, +//! create [`Dataspace`][crate::dataspace::Dataspace] entities. + use super::bag; use preserves::value::{Map, NestedValue, Set, Value}; @@ -18,12 +25,17 @@ type Bag = bag::BTreeBag; type Captures = AnyValue; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] -pub enum Guard { +enum Guard { Rec(AnyValue, usize), Seq(usize), Map, } +/// Index of assertions and [`Observe`rs][crate::schemas::dataspace::Observe]. +/// +/// Generally speaking, you will not need to use this structure; +/// instead, create [`Dataspace`][crate::dataspace::Dataspace] +/// entities. #[derive(Debug)] pub struct Index { all_assertions: Bag, @@ -64,6 +76,7 @@ struct Endpoints { //--------------------------------------------------------------------------- impl Index { + /// Construct a new `Index`. pub fn new() -> Self { Index { all_assertions: Bag::new(), @@ -72,6 +85,11 @@ impl Index { } } + /// Adds a new observer. If any existing assertions in the index + /// match `pat`, establishes corresponding assertions at + /// `observer`. Once the observer is registered, subsequent + /// arriving assertions will be matched against `pat` and + /// delivered to `observer` if they match. pub fn add_observer( &mut self, t: &mut Activation, @@ -83,6 +101,7 @@ impl Index { self.observer_count += 1; } + /// Removes an existing observer. pub fn remove_observer( &mut self, t: &mut Activation, @@ -94,6 +113,7 @@ impl Index { self.observer_count -= 1; } + /// Inserts an assertion into the index, notifying matching observers. pub fn insert(&mut self, t: &mut Activation, outer_value: &AnyValue) { let net = self.all_assertions.change(outer_value.clone(), 1); match net { @@ -119,6 +139,7 @@ impl Index { } } + /// Removes an assertion from the index, notifying matching observers. pub fn remove(&mut self, t: &mut Activation, outer_value: &AnyValue) { let net = self.all_assertions.change(outer_value.clone(), -1); match net { @@ -144,6 +165,7 @@ impl Index { } } + /// Routes a message using the index, notifying matching observers. pub fn send(&mut self, t: &mut Activation, outer_value: &AnyValue) { Modification::new( false, @@ -158,14 +180,18 @@ impl Index { }).perform(&mut self.root); } + /// Retrieves the current count of distinct assertions in the index. pub fn assertion_count(&self) -> usize { return self.all_assertions.len() } + /// Retrieves the current count of assertions in the index, + /// including duplicates. pub fn endpoint_count(&self) -> isize { return self.all_assertions.total() } + /// Retrieves the current count of observers of the index. pub fn observer_count(&self) -> usize { return self.observer_count } @@ -234,7 +260,7 @@ impl Node { } #[derive(Debug)] -pub enum Stack<'a, T> { +enum Stack<'a, T> { Empty, Item(T, &'a Stack<'a, T>) } @@ -387,7 +413,7 @@ impl Continuation { Continuation { cached_assertions, leaf_map: Map::new() } } - pub fn add_observer( + fn add_observer( &mut self, t: &mut Activation, analysis: &pattern::PatternAnalysis, @@ -427,7 +453,7 @@ impl Continuation { endpoints.endpoints.insert(observer.clone(), capture_map); } - pub fn remove_observer( + fn remove_observer( &mut self, t: &mut Activation, analysis: pattern::PatternAnalysis,