diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/core.rs b/src/core.rs index 3672435..d4b29d4 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,4 +1,4 @@ -use std::{error::Error, rc::Rc}; +use std::{error::Error, fmt::Display, rc::Rc}; use crate::func::*; @@ -8,52 +8,84 @@ pub trait Context { fn hash(s: &[u8]) -> Hash; } -type Hash = [u8; 32]; +pub const HASH_SIZE: usize = 32; + +pub type Hash = [u8; HASH_SIZE]; pub trait Serializer { fn write(&mut self, buf: &[u8]); + fn tell(&self) -> usize; } -impl Serializer for F { +impl Serializer for Vec { fn write(&mut self, buf: &[u8]) { - self(buf); + self.extend(buf); + } + + fn tell(&self) -> usize { + self.len() } } -pub trait Mentionable { - type Fctr: Factory; +pub trait Serializable { + fn serialize(&self, serializer: &mut dyn Serializer); +} + +pub trait Mentionable<'a, Ctx: 'a + Context>: 'a + Serializable { + type Fctr: Factory<'a, Ctx, Mtbl = Self>; - fn serialize(&self, serializer: F); fn factory(&self) -> Self::Fctr; - fn topology(&self) -> Hash; + fn topology(&self) -> Hash { + let mut vec = Vec::new(); + for point in self.points() { + vec.extend(point.point); + } + Ctx::hash(&vec) + } + fn points(&self) -> Vec>>; } pub trait Deserializer { - fn read_n_const(&mut self) -> Result<[u8; N], &[u8]>; fn read_n(&mut self, n: usize) -> &[u8]; fn read_all(&mut self, n: usize) -> &[u8]; } -pub trait Factory: Clone { - type Mtbl: Mentionable; - type ParseError: Error; - - fn deserialize(&self, deserializer: F) - -> Result; +pub trait ExtDeserialiser { + fn read_n_const(&mut self) -> Result<[u8; N], &[u8]>; } -pub trait Origin<'a, Ctx: Context>: 'a { - type Mtbl: Mentionable; - fn factory(&self) -> >::Fctr; +impl ExtDeserialiser for D { + fn read_n_const(&mut self) -> Result<[u8; N], &[u8]> { + let slice = self.read_n(N); + match slice.try_into() { + Ok(array) => Ok(array), + Err(_) => Err(slice), + } + } +} + +pub trait Factory<'a, Ctx: 'a + Context>: Clone + 'a { + type Mtbl: Mentionable<'a, Ctx, Fctr = Self>; + type ParseError: Error; + + fn deserialize( + &self, + deserializer: &mut dyn Deserializer, + ) -> Result; +} + +pub trait Origin<'a, Ctx: 'a + Context>: 'a { + type Mtbl: Mentionable<'a, Ctx>; + fn factory(&self) -> >::Fctr; fn resolve(&self) -> <::T as WeakFunctor>::F<'a, Rc>; } struct LocalOrigin(Rc); -impl<'a, Ctx: 'a + Context, A: 'a + Mentionable> Origin<'a, Ctx> for LocalOrigin { +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for LocalOrigin { type Mtbl = A; - fn factory(&self) -> >::Fctr { + fn factory(&self) -> >::Fctr { self.0.factory() } @@ -68,16 +100,24 @@ impl From for LocalOrigin { } } -#[derive(Clone)] -pub struct Point<'a, Ctx: Context, A: Mentionable> { +pub struct Point<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> { pub point: Hash, pub origin: Rc>, } -impl<'a, Ctx: 'a + Context, A: 'a + Mentionable> Point<'a, Ctx, A> { +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Clone for Point<'a, Ctx, A> { + fn clone(&self) -> Self { + Self { + point: self.point, + origin: self.origin.clone(), + } + } +} + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { fn prepare_bytes_for_hashing(mentioned: &A) -> Vec { let mut vec = mentioned.topology().to_vec(); - mentioned.serialize(|x: &[u8]| vec.extend(x.iter())); + mentioned.serialize(&mut vec); vec } @@ -94,7 +134,7 @@ impl<'a, Ctx: 'a + Context, A: 'a + Mentionable> Point<'a, Ctx, A> { } } -impl<'a, Ctx: 'a + Context, A: 'a + Mentionable> From for Point<'a, Ctx, A> { +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> From for Point<'a, Ctx, A> { fn from(value: A) -> Self { Self::from_values( Ctx::hash(Self::prepare_bytes_for_hashing(&value).as_slice()), @@ -102,3 +142,106 @@ impl<'a, Ctx: 'a + Context, A: 'a + Mentionable> From for Point<'a, Ctx, ) } } + +type TypelessSerialize<'a> = dyn 'a + Fn(&mut dyn Serializer); + +pub struct TypelessMentionable<'a, Ctx: 'a + Context> { + t_serialize: Box>, + t_factory: TypelessFactory<'a, Ctx>, + t_topology: Hash, + t_points: Vec>>, +} + +type TypelessParsed<'a, Ctx> = Result, Box>; + +type TypelessDeserialize<'a, Ctx> = dyn 'a + Fn(&mut dyn Deserializer) -> TypelessParsed<'a, Ctx>; + +pub struct TypelessFactory<'a, Ctx: 'a + Context> { + t_deserialize: Rc>, +} + +impl<'a, Ctx: 'a + Context> Serializable for TypelessMentionable<'a, Ctx> { + fn serialize(&self, serializer: &mut dyn Serializer) { + (self.t_serialize)(serializer); + } +} + +impl<'a, Ctx: 'a + Context> Mentionable<'a, Ctx> for TypelessMentionable<'a, Ctx> { + type Fctr = TypelessFactory<'a, Ctx>; + + fn factory(&self) -> Self::Fctr { + self.t_factory.clone() + } + + fn topology(&self) -> Hash { + self.t_topology + } + + fn points(&self) -> Vec>> { + self.t_points.clone() + } +} + +impl<'a, Ctx: 'a + Context> Clone for TypelessFactory<'a, Ctx> { + fn clone(&self) -> Self { + Self { + t_deserialize: self.t_deserialize.clone(), + } + } +} + +#[derive(Debug)] +pub struct TypelessError<'a>(Box); + +impl<'a> Display for TypelessError<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl<'a> Error for TypelessError<'a> {} + +impl<'a, Ctx: 'a + Context> Factory<'a, Ctx> for TypelessFactory<'a, Ctx> { + type Mtbl = TypelessMentionable<'a, Ctx>; + + type ParseError = TypelessError<'a>; + + fn deserialize( + &self, + deserializer: &mut dyn Deserializer, + ) -> Result { + match (self.t_deserialize)(deserializer) { + Ok(mentionable) => Ok(mentionable), + Err(error) => Err(TypelessError(error)), + } + } +} + +impl<'a, Ctx: 'a + Context> TypelessMentionable<'a, Ctx> { + pub fn from_mentionable>(mentionable: Rc) -> Self { + let factory = TypelessFactory::from_factory(mentionable.factory()); + let topology = mentionable.topology(); + let points = mentionable.points(); + TypelessMentionable { + t_serialize: Box::new(move |serializer| mentionable.serialize(serializer)), + t_factory: factory, + t_topology: topology, + t_points: points, + } + } +} + +impl<'a, Ctx: 'a + Context> TypelessFactory<'a, Ctx> { + pub fn from_factory>(factory: F) -> Self { + TypelessFactory { + t_deserialize: Rc::new( + move |deserializer| match factory.deserialize(deserializer) { + Ok(mentionable) => { + Ok(TypelessMentionable::from_mentionable(Rc::new(mentionable))) + } + Err(error) => Err(Box::new(error)), + }, + ), + } + } +} diff --git a/src/func.rs b/src/func.rs index 8c8e20b..cbbdead 100644 --- a/src/func.rs +++ b/src/func.rs @@ -7,7 +7,7 @@ pub mod test_suite; pub mod tests; pub trait WeakFunctor { - type F<'a, A: 'a>: 'a; + type F<'a, A: 'a>: 'a where Self: 'a; } /// Rust-specific implementation of [Functor], respecting `move` semantics. diff --git a/src/func/classes/composition.rs b/src/func/classes/composition.rs index 2c81f7a..d04e938 100644 --- a/src/func/classes/composition.rs +++ b/src/func/classes/composition.rs @@ -3,7 +3,7 @@ use crate::func::*; struct CompositionClass(U, V); impl WeakFunctor for CompositionClass { - type F<'a, A: 'a> = U::F<'a, V::F<'a, A>>; + type F<'a, A: 'a> = U::F<'a, V::F<'a, A>> where U: 'a, V: 'a; } impl Functor for CompositionClass { diff --git a/src/func/classes/stackless.rs b/src/func/classes/stackless.rs index a9918e8..657e27e 100644 --- a/src/func/classes/stackless.rs +++ b/src/func/classes/stackless.rs @@ -3,12 +3,14 @@ use std::{cell::Cell, rc::Rc}; use crate::func::*; enum EvalTree<'a> { - Atom(Box Option>>), + Atom(Box Oet<'a>>), Composite(Box>, Box>), } +type Oet<'a> = Option>; + impl<'a> EvalTree<'a> { - fn next(self) -> Option> { + fn next(self) -> Oet<'a> { match self { EvalTree::Atom(f) => f(), EvalTree::Composite(left, right) => match *left { @@ -25,11 +27,13 @@ impl<'a> EvalTree<'a> { } } +type StackessDyn<'a, A> = dyn 'a + FnOnce(Box) -> Oet<'a>; + pub struct Stackless<'a, A: 'a>( - Box) -> Option>>, + Box>, ); -fn set_cell(cell: Rc>>, a: A) -> () { +fn set_cell(cell: Rc>>, a: A) { if cell.replace(Some(a)).is_some() { panic!("MITM overwritten") } @@ -43,7 +47,7 @@ fn get_cell(cell: Rc>>) -> A { } impl<'a, A: 'a> Stackless<'a, A> { - fn call(self, f: impl 'a + FnOnce(A)) -> Option> { + fn call(self, f: impl 'a + FnOnce(A)) -> Oet<'a> { self.0(Box::new(f)) } @@ -273,6 +277,7 @@ mod stackless_test { #[test] fn test_dumb() { - assert_eq!(dumb(1000).evaluate(), 1000); + let n = 1000; + assert_eq!(dumb(n).evaluate(), n); } } diff --git a/src/func/test_suite.rs b/src/func/test_suite.rs index e779bd4..33254eb 100644 --- a/src/func/test_suite.rs +++ b/src/func/test_suite.rs @@ -3,7 +3,7 @@ use super::{tests::*, *}; pub trait FunctorTestSuite: WeakFunctor + Eqr { fn sample<'a, A: 'a, F: FnMut(&'a dyn Fn(A) -> Self::F<'a, A>)>(f: F) where - Self::F<'a, A>: 'a; + Self::F<'a, A>: 'a, Self: 'a; } pub fn functor_follows_laws() -> R { diff --git a/src/lib.rs b/src/lib.rs index dc7ea65..0e1cd37 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod core; pub mod func; +pub mod std; #[cfg(test)] mod xrcs; diff --git a/src/std.rs b/src/std.rs new file mode 100644 index 0000000..7f1b30e --- /dev/null +++ b/src/std.rs @@ -0,0 +1,138 @@ +pub mod atomic; +pub mod inlining; + +use std::{error::Error, fmt::Display, rc::Rc}; + +use crate::core::*; +use crate::func::*; + +struct WrappedOrigin<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> { + w_factory: A::Fctr, + w_resolve: Box <::T as WeakFunctor>::F<'a, Rc>>, +} + +trait MappableOrigin<'a, Ctx: 'a + Context>: Origin<'a, Ctx> { + fn map>( + self: Rc, + map_mentionable: impl 'a + Clone + Fn(Rc) -> B, + map_factory: impl 'a + FnOnce(>::Fctr) -> B::Fctr, + ) -> WrappedOrigin<'a, Ctx, B>; +} + +fn map_resolve<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>, B: Mentionable<'a, Ctx>>( + resolve: impl 'a + Fn() -> <::T as WeakFunctor>::F<'a, Rc>, + map_mentionable: impl 'a + Fn(Rc) -> B, +) -> <::T as WeakFunctor>::F<'a, Rc> { + Ctx::T::fmap( + move |resolved| Rc::new(map_mentionable(resolved)), + resolve(), + ) +} + +impl<'a, Ctx: 'a + Context, O: ?Sized + Origin<'a, Ctx>> MappableOrigin<'a, Ctx> for O { + fn map>( + self: Rc, + map_mentionable: impl 'a + Clone + Fn(Rc) -> B, + map_factory: impl 'a + FnOnce(>::Fctr) -> B::Fctr, + ) -> WrappedOrigin<'a, Ctx, B> { + let origin = self.clone(); + WrappedOrigin { + w_factory: map_factory(self.factory()), + w_resolve: Box::new(move || { + let origin = origin.clone(); + let map_mentionable = map_mentionable.clone(); + map_resolve( + move || origin.resolve(), + map_mentionable, + ) + }), + } + } +} + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for WrappedOrigin<'a, Ctx, A> { + type Mtbl = A; + + fn factory(&self) -> >::Fctr { + self.w_factory.clone() + } + + fn resolve(&self) -> <::T as WeakFunctor>::F<'a, Rc> { + (self.w_resolve)() + } +} + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Point<'a, Ctx, A> { + pub fn typeless(&self) -> Point<'a, Ctx, TypelessMentionable<'a, Ctx>> { + Point { + point: self.point, + origin: Rc::new(self.origin.clone().map( + TypelessMentionable::from_mentionable, + TypelessFactory::from_factory, + )), + } + } +} + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Serializable for Point<'a, Ctx, A> { + fn serialize(&self, serializer: &mut dyn Serializer) { + serializer.write(&self.point) + } +} + +impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> Mentionable<'a, Ctx> for Point<'a, Ctx, A> { + type Fctr = PointFactory; + + fn factory(&self) -> Self::Fctr { + PointFactory { + factory: self.origin.factory(), + } + } + + fn topology(&self) -> Hash { + Ctx::hash(&self.point) + } + + fn points(&self) -> Vec>> { + vec![self.typeless()] + } +} + +#[derive(Clone)] +pub struct PointFactory { + factory: F, +} + +#[derive(Debug)] +pub enum PointParseError { + WrongLength(usize), +} + +impl Display for PointParseError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PointParseError::WrongLength(length) => f.write_fmt(format_args!( + "expected {} bytes, received {}", + HASH_SIZE, length + )), + } + } +} + +impl Error for PointParseError {} + +impl<'a, Ctx: 'a + Context, F: Factory<'a, Ctx>> Factory<'a, Ctx> for PointFactory { + type Mtbl = Point<'a, Ctx, F::Mtbl>; + + type ParseError = PointParseError; + + fn deserialize( + &self, + deserializer: &mut dyn Deserializer, + ) -> Result { + match deserializer.read_n_const::() { + Ok(point) => Ok(Point {point, origin: todo!()}), + Err(slice) => Err(PointParseError::WrongLength(slice.len())), + } + } +} diff --git a/src/std/atomic.rs b/src/std/atomic.rs new file mode 100644 index 0000000..bb5fd88 --- /dev/null +++ b/src/std/atomic.rs @@ -0,0 +1,51 @@ +use std::{error::Error, marker::PhantomData}; + +use crate::core::*; + +pub trait Atomic: 'static + Sized + Clone + Serializable { + type ParseError: Error; + fn deserialize(deserializer: &mut dyn Deserializer) -> Result; +} + +pub struct AtomicFactory(PhantomData); + +impl AtomicFactory { + fn new() -> Self { + AtomicFactory(PhantomData) + } +} + +impl Clone for AtomicFactory { + fn clone(&self) -> Self { + Self::new() + } +} + +impl<'a, Ctx: 'a + Context, A: Atomic> Mentionable<'a, Ctx> for A { + type Fctr = AtomicFactory; + + fn factory(&self) -> Self::Fctr { + AtomicFactory::new() + } + + fn topology(&self) -> Hash { + Ctx::hash(b"") + } + + fn points(&self) -> Vec>> { + vec![] + } +} + +impl<'a, Ctx: 'a + Context, A: Atomic> Factory<'a, Ctx> for AtomicFactory { + type Mtbl = A; + + type ParseError = A::ParseError; + + fn deserialize( + &self, + deserializer: &mut dyn Deserializer, + ) -> Result { + A::deserialize(deserializer) + } +} diff --git a/src/std/inlining.rs b/src/std/inlining.rs new file mode 100644 index 0000000..e69de29