stackless::atom

This commit is contained in:
AF 2023-07-31 16:16:14 +00:00
parent c2102268e4
commit 1959b1833e

View File

@ -5,13 +5,46 @@
//! //!
//! [`lazy`]: super::lazy //! [`lazy`]: super::lazy
use std::marker::PhantomData;
use std::{cell::Cell, rc::Rc}; use std::{cell::Cell, rc::Rc};
use crate::func::class_prelude::*; use crate::func::class_prelude::*;
use crate::func::derivations::{ApplicativeLA2ViaSeq, ApplicativeTupleViaLA2}; use crate::func::derivations::{ApplicativeLA2ViaSeq, ApplicativeTupleViaLA2};
trait Atom {
fn next<'t>(self: Box<Self>) -> 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<EvalTree<'a>> {
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<Self>) -> Oet<'t>
where
Self: 't,
{
(self.0)()
}
}
enum EvalTree<'a> { enum EvalTree<'a> {
Atom(Box<dyn 'a + FnOnce() -> Oet<'a>>), Atom(Box<dyn 'a + Atom>),
Composite(Box<EvalTree<'a>>, Box<EvalTree<'a>>), Composite(Box<EvalTree<'a>>, Box<EvalTree<'a>>),
} }
@ -20,9 +53,9 @@ type Oet<'a> = Option<EvalTree<'a>>;
impl<'a> EvalTree<'a> { impl<'a> EvalTree<'a> {
fn next(self) -> Oet<'a> { fn next(self) -> Oet<'a> {
match self { match self {
Self::Atom(f) => f(), Self::Atom(f) => f.next(),
Self::Composite(etl, etr) => match *etl { 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)), Some(newleft) => Some(Self::Composite(Box::new(newleft), etr)),
None => Some(*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_l = Rc::new(Cell::new(None));
let cell_r = cell_l.clone(); let cell_r = cell_l.clone();
Some(EvalTree::Composite( Some(EvalTree::Composite(
Box::new(EvalTree::Atom(Box::new(move || { batom(move || self.call(move |a| set_cell(cell_l, a))),
self.call(move |a| set_cell(cell_l, a)) batom(move || {
}))),
Box::new(EvalTree::Atom(Box::new(move || {
let stackless = f(get_cell(cell_r)); 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_l = Rc::new(Cell::new(None));
let cell_r = cell_l.clone(); let cell_r = cell_l.clone();
Some(EvalTree::Composite( Some(EvalTree::Composite(
Box::new(EvalTree::Atom(Box::new(move || { batom(move || self.call(move |a| set_cell(cell_l, a))),
self.call(move |a| set_cell(cell_l, a)) batom(move || {
}))),
Box::new(EvalTree::Atom(Box::new(move || {
let b = f(get_cell(cell_r)); let b = f(get_cell(cell_r));
Some(EvalTree::Atom(Box::new(|| { satom(|| {
takesb(b); takesb(b);
None None
}))) })
}))), }),
)) ))
})) }))
} }
@ -110,10 +139,10 @@ impl<'a, A: 'a> Stackless<'a, A> {
impl<'a, A: 'a> From<A> for Stackless<'a, A> { impl<'a, A: 'a> From<A> for Stackless<'a, A> {
fn from(value: A) -> Self { fn from(value: A) -> Self {
Stackless(Box::new(|takesa| { Stackless(Box::new(|takesa| {
Some(EvalTree::Atom(Box::new(|| { satom(|| {
takesa(value); takesa(value);
None None
}))) })
})) }))
} }
} }
@ -132,11 +161,11 @@ impl<'a> Functor<'a> for StacklessInstance {
fn replace<A: 'a, B: 'a>(fa: Self::F<A>, b: B) -> Self::F<B> { fn replace<A: 'a, B: 'a>(fa: Self::F<A>, b: B) -> Self::F<B> {
Stackless(Box::new(|takesb| { Stackless(Box::new(|takesb| {
Some(EvalTree::Composite( Some(EvalTree::Composite(
Box::new(EvalTree::Atom(Box::new(move || fa.call(drop)))), batom(move || fa.call(drop)),
Box::new(EvalTree::Atom(Box::new(move || { batom(move || {
takesb(b); takesb(b);
None None
}))), }),
)) ))
})) }))
} }
@ -176,8 +205,8 @@ impl<'a> Applicative<'a> for StacklessInstance {
fn discard_first<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> Self::F<B> { fn discard_first<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> Self::F<B> {
Stackless(Box::new(|takesb| { Stackless(Box::new(|takesb| {
Some(EvalTree::Composite( Some(EvalTree::Composite(
Box::new(EvalTree::Atom(Box::new(|| fa.call(drop)))), batom(|| fa.call(drop)),
Box::new(EvalTree::Atom(Box::new(|| fb.0(takesb)))), batom(|| fb.0(takesb)),
)) ))
})) }))
} }
@ -185,8 +214,8 @@ impl<'a> Applicative<'a> for StacklessInstance {
fn discard_second<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> Self::F<A> { fn discard_second<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> Self::F<A> {
Stackless(Box::new(|takesa| { Stackless(Box::new(|takesa| {
Some(EvalTree::Composite( Some(EvalTree::Composite(
Box::new(EvalTree::Atom(Box::new(|| fa.0(takesa)))), batom(|| fa.0(takesa)),
Box::new(EvalTree::Atom(Box::new(|| fb.call(drop)))), batom(|| fb.call(drop)),
)) ))
})) }))
} }
@ -211,13 +240,11 @@ impl<'a> Monad<'a> for StacklessInstance {
let cell_l = Rc::new(Cell::new(None)); let cell_l = Rc::new(Cell::new(None));
let cell_r = cell_l.clone(); let cell_r = cell_l.clone();
Some(EvalTree::Composite( Some(EvalTree::Composite(
Box::new(EvalTree::Atom(Box::new(move || { batom(move || ffa.call(move |a| set_cell(cell_l, a))),
ffa.call(move |a| set_cell(cell_l, a)) batom(move || {
}))),
Box::new(EvalTree::Atom(Box::new(move || {
let stackless = get_cell(cell_r); let stackless = get_cell(cell_r);
Some(EvalTree::Atom(Box::new(|| stackless.0(takesa)))) satom(|| stackless.0(takesa))
}))), }),
)) ))
})) }))
} }