use crate::thunk::Thunk;
pub struct Action<'a, T>(ActionKind<'a, T>);
enum ActionKind<'a, T> {
Done(T),
Call(Thunk<'a, Action<'a, T>>),
}
pub const fn done<'a, T>(value: T) -> Action<'a, T> {
Action(ActionKind::Done(value))
}
pub const fn call<'a, T, F>(fn_once: F) -> Action<'a, T>
where
F: FnOnce() -> Action<'a, T> + 'a,
{
Action(ActionKind::Call(Thunk::new(fn_once)))
}
pub fn run<T>(mut action: Action<'_, T>) -> T {
loop {
match action.0 {
ActionKind::Call(thunk) => action = thunk.call(),
ActionKind::Done(value) => return value,
}
}
}