//! Basic implementation of a stack/linked list. use crate::func::{context::*, controlflow::ControlFlow}; use crate::rcore::*; use crate::rstd::{inlining::*, nullable::*, point::*, *}; /// Node containing a (nullable) reference to the next node and an element. pub struct StackNode<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> { /// Reference comes first due to being inlineable. pub rest: Stack<'a, Ctx, A>, /// Unlike the original implementation in Python, doesn't default to using Point. pub element: A, } /// Type representing a stack, an alias to a [Nullable] of a [StackNode]. pub type Stack<'a, Ctx, A> = Nullable<'a, Ctx, StackNode<'a, Ctx, A>>; #[derive(Clone)] pub struct StackNodeFactory { element_factory: F, } impl StackNodeFactory { fn new(factory: F) -> Self { StackNodeFactory { element_factory: factory, } } } impl<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> Serializable for StackNode<'a, Ctx, A> { fn serialize(&self, serializer: &mut dyn Serializer) { self.rest.serialize(serializer); self.element.serialize(serializer); } } impl<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>> MentionableBase<'a, Ctx> for StackNode<'a, Ctx, A> { type Fctr = StackNodeFactory; fn factory(&self) -> Self::Fctr { StackNodeFactory::new(self.element.factory()) } } impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> MentionableTop<'a, Ctx> for StackNode<'a, Ctx, A> { fn points_typed(&self, points: &mut impl PointsVisitor<'a, Ctx>) where Self: Mentionable<'a, Ctx>, { self.rest.points_typed(points); self.element.points_typed(points); } } #[derive(Debug)] pub enum StackParseError { Point(PointParseError), Element(ElementParseError), } impl From for StackParseError { fn from(value: PointParseError) -> Self { Self::Point(value) } } impl Display for StackParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Point(ppe) => { write!(f, "can't parse stack's next pointer: {}", ppe) } Self::Element(epe) => { write!(f, "can't parse stack's element: {}", epe) } } } } impl Error for StackParseError {} impl StackNodeFactory { fn parse_point<'a, Ctx: Context<'a>, I: InCtx<'a, Ctx>>( &self, inctx: I, ) -> IParseResult<'a, Ctx, NullableFactory, I> where StackNodeFactory: Factory<'a, Ctx>, { NullableFactory::new(self.clone()).ideserialize(inctx) } } impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx>> FactoryBase<'a, Ctx> for StackNodeFactory { type Mtbl = StackNode<'a, Ctx, F::Mtbl>; type ParseError = StackParseError>; } impl ImplMode for StackNodeFactory { type Mode = F::Mode; } impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx> + RegularFactory<'a, Ctx>> QRegularFactory<'a, Ctx> for StackNodeFactory where F::Mtbl: MentionableTop<'a, Ctx>, { fn qrdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { let (rest, inctx) = self.parse_point(inctx)?; let element = self .element_factory .deserialize(inctx) .map_err(StackParseError::Element)?; Ok(StackNode { rest, element }) } fn qrextend(&self, mut mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self> { mentionable.element = self .element_factory .extend(mentionable.element, tail) .map_err(StackParseError::Element)?; Ok(mentionable) } } /// See [`StackVecResult`]. pub type StackFaiure<'a, Ctx, A> = ResolutionFailure<'a, Ctx, StackNode<'a, Ctx, A>>; /// See [`StackVecWrapped`]. pub type StackVecResult<'a, Ctx, A> = Result, StackFaiure<'a, Ctx, A>>; /// See [`ExtStackClone::vec`]. pub type StackVecWrapped<'a, Ctx, A> = Wrapped<'a, Ctx, StackVecResult<'a, Ctx, A>>; /// Extention trait with helper methods for [Stack]s. pub trait ExtStack<'a, Ctx: Context<'a>, A: MentionableBase<'a, Ctx>>: MentionableBase<'a, Ctx> { /// Get an empty stack ([`Nullable::Null`]). fn empty(factory: A::Fctr) -> Self; /// Get the corresponding factory. fn f(factory: A::Fctr) -> Self::Fctr; /// Add one element. /// /// Note: consumes the stack. For non-consuming version do `.clone()` before adding. fn add(self, element: A) -> Self; } /// Extention trait with helper methods for [Stack]s. pub trait ExtStackClone<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone>: MentionableBase<'a, Ctx> { /// Collect all the elements into a [`Vec`]. fn vec(self) -> StackVecWrapped<'a, Ctx, A>; } impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Mentionable<'a, Ctx>> ExtStack<'a, Ctx, A> for Stack<'a, Ctx, A> where StackNode<'a, Ctx, A>: Mentionable<'a, Ctx, _Fctr = StackNodeFactory>, { fn empty(factory: A::Fctr) -> Self { Nullable::Null(StackNodeFactory::new(factory.clone())) } fn f(factory: A::Fctr) -> Self::Fctr { NullableFactory::new(StackNodeFactory::new(factory.clone())) } fn add(self, element: A) -> Self { Nullable::NotNull( StackNode { rest: self, element, } .into(), ) } } impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + Clone> ExtStackClone<'a, Ctx, A> for Stack<'a, Ctx, A> where StackNode<'a, Ctx, A>: Mentionable<'a, Ctx, _Fctr = StackNodeFactory>, StackNodeFactory: FactoryParse<'a, Ctx>, { fn vec(self) -> StackVecWrapped<'a, Ctx, A> { Ctx::T::iterate_mut((vec![], self), |(mut vec, stack)| match stack { Nullable::Null(_) => Ctx::pure(ControlFlow::Break(Ok(vec))), Nullable::NotNull(point) => point.resolve_map(|resolved| { let node = match resolved { Ok(node) => node, Err(error) => { return ControlFlow::Break(Err(error)); } }; vec.push(node.element.clone()); ControlFlow::Continue((vec, node.rest.clone())) }), }) } } impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx> + InliningFactory<'a, Ctx>> InliningFactory<'a, Ctx> for StackNodeFactory where F::Mtbl: MentionableTop<'a, Ctx>, { fn extension_error(&self, tail: &[u8]) -> Self::ParseError { StackParseError::Element(self.element_factory.extension_error(tail)) } fn ideserialize>(&self, inctx: I) -> IParseResult<'a, Ctx, Self, I> { let (rest, inctx) = self.parse_point(inctx)?; let (element, inctx) = self .element_factory .ideserialize(inctx) .map_err(StackParseError::Element)?; Ok((StackNode { rest, element }, inctx)) } } impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx> + FixedSizeFactory<'a, Ctx>> FixedSizeFactory<'a, Ctx> for StackNodeFactory where F::Mtbl: MentionableTop<'a, Ctx>, { fn size(&self) -> usize { Stack::<'a, Ctx, F::Mtbl>::SIZE + self.element_factory.size() } } impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx> + ConstSizeFactory<'a, Ctx>> ConstSizeFactory<'a, Ctx> for StackNodeFactory where F::Mtbl: MentionableTop<'a, Ctx>, { const SIZE: usize = Stack::<'a, Ctx, F::Mtbl>::SIZE + F::SIZE; } #[cfg(test)] mod tests { use std::rc::Rc; use crate::rstd::{ atomic::{atomic_object::*, plain::*}, tracing::*, }; use crate::testing::{counted::*, traced::*, *}; use super::*; type T = Stack<'static, Ctx, AtomicObject>; fn unstack( stack: &T, ) -> Result>, StackFaiure<'static, TestContextPlain, AtomicObject>> { Ok(stack .clone() .vec()? .iter() .map(|plain| plain.raw()) .collect()) } fn make_stack>() -> T { let stack: T = Stack::empty(Plain::f()); let stack: T = stack.add(Plain::from_slice(b"A0").into()); let stack: T = stack.add(Plain::from_slice(b"B1").into()); let stack: T = stack.add(Plain::from_slice(b"C2").into()); stack } fn validate_stack(stack: &T) { let mut vec: Vec> = unstack(stack).unwrap(); vec.reverse(); assert_eq!(vec, vec![b"A0".to_vec(), b"B1".to_vec(), b"C2".to_vec()]); } #[test] fn test_stack() -> Result<(), StackFaiure<'static, TestContextPlain, AtomicObject>> { let stack: T = make_stack(); validate_stack(&stack); let stack: T = reparse(stack.into()); validate_stack(&stack); Ok(()) } #[test] fn test_counted() -> Result<(), point::PointParseError> { let stack: T = make_stack(); let count = stack.clone().vec().count(); assert_eq!(count, 0); let stack: T = Rc::new(stack).delay()?; let count = stack.clone().vec().count(); assert_eq!(count, 3); Ok(()) } #[test] fn test_traced() -> Result<(), point::PointParseError> { let stack: T = make_stack(); let traced = stack.clone().vec(); assert_eq!(traced.length(), 0); assert_eq!(traced.width(), 0); assert_eq!(format!("{}", traced.effect), "."); let stack: T = Rc::new(stack).trace()?; let traced = stack.clone().vec(); assert_eq!(traced.length(), 3); assert_eq!(traced.width(), 1); assert_eq!(format!("{}", traced.effect), "( ? > ? > ? )"); Ok(()) } #[test] fn test_rendered() -> Result<(), point::PointParseError> { let stack: T = make_stack(); let rendered = stack.clone().vec().render(); assert_eq!(rendered.length(), 0); assert_eq!(rendered.width(), 0); assert_eq!(format!("{}", rendered), "."); let stack: T = Rc::new(stack).trace()?; let rendered = stack.clone().vec().render(); assert_eq!(rendered.length(), 3); assert_eq!(rendered.width(), 1); assert_eq!(format!("{}", rendered), "( ? > ? > ? )"); Ok(()) } }