From 1959b1833ed2be1a19b4568f196471212824ab97 Mon Sep 17 00:00:00 2001 From: timofey Date: Mon, 31 Jul 2023 16:16:14 +0000 Subject: [PATCH] `stackless::atom` --- src/func/instances/stackless.rs | 89 +++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/src/func/instances/stackless.rs b/src/func/instances/stackless.rs index d862ef8..1ea8f57 100644 --- a/src/func/instances/stackless.rs +++ b/src/func/instances/stackless.rs @@ -5,13 +5,46 @@ //! //! [`lazy`]: super::lazy +use std::marker::PhantomData; use std::{cell::Cell, rc::Rc}; use crate::func::class_prelude::*; use crate::func::derivations::{ApplicativeLA2ViaSeq, ApplicativeTupleViaLA2}; +trait Atom { + fn next<'t>(self: Box) -> Oet<'t> + where + Self: 't; +} + +struct Wrapper<'a, F>(F, PhantomData<&'a ()>); + +fn atom<'a, F: 'a + FnOnce() -> Oet<'a>>(f: F) -> EvalTree<'a> { + EvalTree::Atom(Box::new(Wrapper(f, PhantomData))) +} + +fn batom<'a, F: 'a + FnOnce() -> Oet<'a>>(f: F) -> Box> { + Box::new(atom(f)) +} + +fn satom<'a, F: 'a + FnOnce() -> Oet<'a>>(f: F) -> Oet<'a> { + Some(atom(f)) +} + +impl<'a, F> Atom for Wrapper<'a, F> +where + F: 'a + FnOnce() -> Oet<'a>, +{ + fn next<'t>(self: Box) -> Oet<'t> + where + Self: 't, + { + (self.0)() + } +} + enum EvalTree<'a> { - Atom(Box Oet<'a>>), + Atom(Box), Composite(Box>, Box>), } @@ -20,9 +53,9 @@ type Oet<'a> = Option>; impl<'a> EvalTree<'a> { fn next(self) -> Oet<'a> { match self { - Self::Atom(f) => f(), + Self::Atom(f) => f.next(), Self::Composite(etl, etr) => match *etl { - Self::Atom(f) => match f() { + Self::Atom(f) => match f.next() { Some(newleft) => Some(Self::Composite(Box::new(newleft), etr)), None => Some(*etr), }, @@ -63,13 +96,11 @@ impl<'a, A: 'a> Stackless<'a, A> { let cell_l = Rc::new(Cell::new(None)); let cell_r = cell_l.clone(); Some(EvalTree::Composite( - Box::new(EvalTree::Atom(Box::new(move || { - self.call(move |a| set_cell(cell_l, a)) - }))), - Box::new(EvalTree::Atom(Box::new(move || { + batom(move || self.call(move |a| set_cell(cell_l, a))), + batom(move || { let stackless = f(get_cell(cell_r)); - Some(EvalTree::Atom(Box::new(|| stackless.0(takesb)))) - }))), + satom(|| stackless.0(takesb)) + }), )) })) } @@ -80,16 +111,14 @@ impl<'a, A: 'a> Stackless<'a, A> { let cell_l = Rc::new(Cell::new(None)); let cell_r = cell_l.clone(); Some(EvalTree::Composite( - Box::new(EvalTree::Atom(Box::new(move || { - self.call(move |a| set_cell(cell_l, a)) - }))), - Box::new(EvalTree::Atom(Box::new(move || { + batom(move || self.call(move |a| set_cell(cell_l, a))), + batom(move || { let b = f(get_cell(cell_r)); - Some(EvalTree::Atom(Box::new(|| { + satom(|| { takesb(b); None - }))) - }))), + }) + }), )) })) } @@ -110,10 +139,10 @@ impl<'a, A: 'a> Stackless<'a, A> { impl<'a, A: 'a> From for Stackless<'a, A> { fn from(value: A) -> Self { Stackless(Box::new(|takesa| { - Some(EvalTree::Atom(Box::new(|| { + satom(|| { takesa(value); None - }))) + }) })) } } @@ -132,11 +161,11 @@ impl<'a> Functor<'a> for StacklessInstance { fn replace(fa: Self::F, b: B) -> Self::F { Stackless(Box::new(|takesb| { Some(EvalTree::Composite( - Box::new(EvalTree::Atom(Box::new(move || fa.call(drop)))), - Box::new(EvalTree::Atom(Box::new(move || { + batom(move || fa.call(drop)), + batom(move || { takesb(b); None - }))), + }), )) })) } @@ -176,8 +205,8 @@ impl<'a> Applicative<'a> for StacklessInstance { fn discard_first(fa: Self::F, fb: Self::F) -> Self::F { Stackless(Box::new(|takesb| { Some(EvalTree::Composite( - Box::new(EvalTree::Atom(Box::new(|| fa.call(drop)))), - Box::new(EvalTree::Atom(Box::new(|| fb.0(takesb)))), + batom(|| fa.call(drop)), + batom(|| fb.0(takesb)), )) })) } @@ -185,8 +214,8 @@ impl<'a> Applicative<'a> for StacklessInstance { fn discard_second(fa: Self::F, fb: Self::F) -> Self::F { Stackless(Box::new(|takesa| { Some(EvalTree::Composite( - Box::new(EvalTree::Atom(Box::new(|| fa.0(takesa)))), - Box::new(EvalTree::Atom(Box::new(|| fb.call(drop)))), + batom(|| fa.0(takesa)), + batom(|| fb.call(drop)), )) })) } @@ -211,13 +240,11 @@ impl<'a> Monad<'a> for StacklessInstance { let cell_l = Rc::new(Cell::new(None)); let cell_r = cell_l.clone(); Some(EvalTree::Composite( - Box::new(EvalTree::Atom(Box::new(move || { - ffa.call(move |a| set_cell(cell_l, a)) - }))), - Box::new(EvalTree::Atom(Box::new(move || { + batom(move || ffa.call(move |a| set_cell(cell_l, a))), + batom(move || { let stackless = get_cell(cell_r); - Some(EvalTree::Atom(Box::new(|| stackless.0(takesa)))) - }))), + satom(|| stackless.0(takesa)) + }), )) })) }