Skip to content

Commit

Permalink
account for Generators being renamed to Coroutines
Browse files Browse the repository at this point in the history
  • Loading branch information
rosefromthedead committed Nov 5, 2023
1 parent 9023ddc commit 94e663f
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 94 deletions.
8 changes: 4 additions & 4 deletions effing-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use syn::{
fn quote_do(e: &Expr) -> Expr {
parse_quote! {
{
use ::core::ops::{Generator, GeneratorState};
use ::core::ops::{Coroutine, CoroutineState};
use ::effing_mad::frunk::Coproduct;
let mut gen = #e;
let mut injection = Coproduct::inject(::effing_mad::injection::Begin);
Expand All @@ -26,9 +26,9 @@ fn quote_do(e: &Expr) -> Expr {
pinned.resume(injection)
};
match res {
GeneratorState::Yielded(effs) =>
CoroutineState::Yielded(effs) =>
injection = (yield effs.embed()).subset().ok().unwrap(),
GeneratorState::Complete(v) => break v,
CoroutineState::Complete(v) => break v,
}
}
}
Expand Down Expand Up @@ -146,7 +146,7 @@ pub fn effectful(args: TokenStream, item: TokenStream) -> TokenStream {
#(#attrs)*
#vis #constness #unsafety
fn #ident #generics(#inputs)
-> impl ::core::ops::Generator<
-> impl ::core::ops::Coroutine<
<#yield_type as ::effing_mad::injection::EffectList>::Injections,
Yield = #yield_type,
Return = #return_type
Expand Down
4 changes: 2 additions & 2 deletions examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
//! Note that the effect definitions are written out manually in this example. For usage of the
//! effects! macro, which allows more ergonomic effect definitions, see effects_macro.rs

#![feature(generators)]
#![feature(generator_trait)]
#![feature(coroutines)]
#![feature(coroutine_trait)]

use effing_mad::{effectful, handle, handler, Effect};

Expand Down
4 changes: 2 additions & 2 deletions examples/effects-macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
//! Here we use State as a classic (and generic!) example of an effect. The same program could just
//! be written using a mutable variable, but that's no fun.

#![feature(generators)]
#![feature(generator_trait)]
#![feature(coroutines)]
#![feature(coroutine_trait)]

use effing_mad::{effectful, handle_group, handler, run};

Expand Down
4 changes: 2 additions & 2 deletions examples/higher-order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
//! as `Option::map`) that take effectful functions instead of "pure" ones. This allows some pretty
//! freaky control flow, like what we see here where the mapper function fails.

#![feature(generators)]
#![feature(generator_trait)]
#![feature(coroutines)]
#![feature(coroutine_trait)]

use effing_mad::{effectful, handle, handler, higher_order::OptionExt, run, Effect, Never};

Expand Down
6 changes: 3 additions & 3 deletions examples/nondet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
//!
//! solve for s, e, n, d, m, o, r, y

#![feature(generators)]
#![feature(generator_trait)]
#![feature(generator_clone)]
#![feature(coroutines)]
#![feature(coroutine_trait)]
#![feature(coroutine_clone)]

use effing_mad::effectful;
use effing_mad::effects::{run_nondet, Nondet};
Expand Down
4 changes: 2 additions & 2 deletions examples/sync-and-async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
//! completes in roughly the same time even though it's doing two of The Thing, because it is I/O
//! bound.

#![feature(generators)]
#![feature(generator_trait)]
#![feature(coroutines)]
#![feature(coroutine_trait)]

use effing_mad::{effectful, handle_group, handle_group_async, handler, run};

Expand Down
4 changes: 2 additions & 2 deletions examples/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
//! known in effing_mad as "transforming" the effects. Print is then handled on its own and since it
//! is the only remaining effect the computation can then be run.

#![feature(generators)]
#![feature(generator_trait)]
#![feature(coroutines)]
#![feature(coroutine_trait)]

use core::ops::ControlFlow;

Expand Down
26 changes: 13 additions & 13 deletions src/effects/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use core::{
future::Future,
ops::{Generator, GeneratorState},
ops::{Coroutine, CoroutineState},
pin::Pin,
task::{Context, Poll, Waker},
};
Expand Down Expand Up @@ -51,9 +51,9 @@ pub struct Futurise<G> {

impl<G> Future for Futurise<G>
where
G: Generator<FInjs, Yield = FEffs>,
G: Coroutine<FInjs, Yield = FEffs>,
{
type Output = <G as Generator<FInjs>>::Return;
type Output = <G as Coroutine<FInjs>>::Return;

fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// see the todo on has_begun
Expand All @@ -66,22 +66,22 @@ where
let g = unsafe { Pin::new_unchecked(&mut self.as_mut().get_unchecked_mut().g) };
let res = g.resume(inj);
match res {
GeneratorState::Yielded(eff) => match eff.uninject() {
CoroutineState::Yielded(eff) => match eff.uninject() {
Ok(GetContext) => inj = Coproduct::inject(Tagged::new(cx.waker() as *const Waker)),
Err(Coproduct::Inl(Await)) => panic!("can't await without context"),
Err(Coproduct::Inr(never)) => match never {},
},
GeneratorState::Complete(ret) => return Poll::Ready(ret),
CoroutineState::Complete(ret) => return Poll::Ready(ret),
}
let g = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().g) };
let res = g.resume(inj);
match res {
GeneratorState::Yielded(eff) => match eff.uninject() {
CoroutineState::Yielded(eff) => match eff.uninject() {
Ok(Await) => Poll::Pending,
Err(Coproduct::Inl(GetContext)) => panic!("no need to GetContext twice"),
Err(Coproduct::Inr(never)) => match never {},
},
GeneratorState::Complete(ret) => Poll::Ready(ret),
CoroutineState::Complete(ret) => Poll::Ready(ret),
}
}
}
Expand All @@ -94,23 +94,23 @@ pub struct Effectfulise<F> {
f: F,
}

impl<F> Generator<FInjs> for Effectfulise<F>
impl<F> Coroutine<FInjs> for Effectfulise<F>
where
F: Future,
{
type Yield = FEffs;
type Return = F::Output;

fn resume(self: Pin<&mut Self>, injs: FInjs) -> GeneratorState<Self::Yield, Self::Return> {
fn resume(self: Pin<&mut Self>, injs: FInjs) -> CoroutineState<Self::Yield, Self::Return> {
// safety: project
let f = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().f) };
match injs.uninject::<Tagged<*const Waker, _>, _>() {
// safety: it's a pointer to something that the caller has a reference to.
Ok(waker) => match f.poll(&mut Context::from_waker(unsafe { &*waker.untag() })) {
Poll::Ready(ret) => GeneratorState::Complete(ret),
Poll::Pending => GeneratorState::Yielded(Coproduct::inject(GetContext)),
Poll::Ready(ret) => CoroutineState::Complete(ret),
Poll::Pending => CoroutineState::Yielded(Coproduct::inject(GetContext)),
},
Err(_) => GeneratorState::Yielded(Coproduct::inject(GetContext)),
Err(_) => CoroutineState::Yielded(Coproduct::inject(GetContext)),
}
}
}
Expand All @@ -133,7 +133,7 @@ impl<F: Future> FutureExt for F {
}
impl<G> EffExt for G
where
G: Generator<FInjs, Yield = FEffs>,
G: Coroutine<FInjs, Yield = FEffs>,
{
fn futurise(self) -> Futurise<Self> {
Futurise {
Expand Down
58 changes: 31 additions & 27 deletions src/higher_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use core::{
marker::PhantomData,
ops::{Generator, GeneratorState},
ops::{Coroutine, CoroutineState},
pin::Pin,
};

Expand All @@ -15,25 +15,25 @@ pub struct OptionMapEff<G, Effs, U> {
_u: PhantomData<fn() -> U>,
}

impl<G, Effs, U> Generator<Effs::Injections> for OptionMapEff<G, Effs, U>
impl<G, Effs, U> Coroutine<Effs::Injections> for OptionMapEff<G, Effs, U>
where
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs, Return = U>,
G: Coroutine<Effs::Injections, Yield = Effs, Return = U>,
{
type Yield = Effs;
type Return = Option<U>;

fn resume(
self: Pin<&mut Self>,
injs: Effs::Injections,
) -> GeneratorState<Self::Yield, Self::Return> {
) -> CoroutineState<Self::Yield, Self::Return> {
unsafe {
match &mut self.get_unchecked_mut().g {
Some(g) => match Pin::new_unchecked(g).resume(injs) {
GeneratorState::Yielded(effs) => GeneratorState::Yielded(effs),
GeneratorState::Complete(ret) => GeneratorState::Complete(Some(ret)),
CoroutineState::Yielded(effs) => CoroutineState::Yielded(effs),
CoroutineState::Complete(ret) => CoroutineState::Complete(Some(ret)),
},
None => GeneratorState::Complete(None),
None => CoroutineState::Complete(None),
}
}
}
Expand All @@ -50,14 +50,14 @@ pub trait OptionExt<T>: Sized {
fn map_eff<Effs, G>(self, g: impl FnOnce(T) -> G) -> OptionMapEff<G, Effs, G::Return>
where
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs>;
G: Coroutine<Effs::Injections, Yield = Effs>;
}

impl<T> OptionExt<T> for Option<T> {
fn map_eff<Effs, G>(self, g: impl FnOnce(T) -> G) -> OptionMapEff<G, Effs, G::Return>
where
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs>,
G: Coroutine<Effs::Injections, Yield = Effs>,
{
OptionMapEff {
g: self.map(g),
Expand All @@ -74,29 +74,31 @@ pub struct ResultMapEff<G, E, Effs, U> {
_u: PhantomData<fn() -> U>,
}

impl<G, E, Effs, U> Generator<Effs::Injections> for ResultMapEff<G, E, Effs, U>
impl<G, E, Effs, U> Coroutine<Effs::Injections> for ResultMapEff<G, E, Effs, U>
where
E: Unpin,
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs, Return = U>,
G: Coroutine<Effs::Injections, Yield = Effs, Return = U>,
{
type Yield = Effs;
type Return = Result<U, E>;

fn resume(
self: Pin<&mut Self>,
injs: Effs::Injections,
) -> GeneratorState<Self::Yield, Self::Return> {
) -> CoroutineState<Self::Yield, Self::Return> {
unsafe {
let g = &mut self.get_unchecked_mut().g;
match g {
Some(Ok(g)) => match Pin::new_unchecked(g).resume(injs) {
GeneratorState::Yielded(effs) => GeneratorState::Yielded(effs),
GeneratorState::Complete(ret) => GeneratorState::Complete(Ok(ret)),
CoroutineState::Yielded(effs) => CoroutineState::Yielded(effs),
CoroutineState::Complete(ret) => CoroutineState::Complete(Ok(ret)),
},
Some(Err(_)) => {
let Some(Err(e)) = core::mem::take(g) else { unreachable!() };
GeneratorState::Complete(Err(e))
let Some(Err(e)) = core::mem::take(g) else {
unreachable!()
};
CoroutineState::Complete(Err(e))
},
None => panic!("resumed after completed"),
}
Expand All @@ -111,29 +113,31 @@ pub struct ResultMapErrEff<G, T, Effs, U> {
_u: PhantomData<fn() -> U>,
}

impl<G, T, Effs, U> Generator<Effs::Injections> for ResultMapErrEff<G, T, Effs, U>
impl<G, T, Effs, U> Coroutine<Effs::Injections> for ResultMapErrEff<G, T, Effs, U>
where
T: Unpin,
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs, Return = U>,
G: Coroutine<Effs::Injections, Yield = Effs, Return = U>,
{
type Yield = Effs;
type Return = Result<T, U>;

fn resume(
self: Pin<&mut Self>,
injs: Effs::Injections,
) -> GeneratorState<Self::Yield, Self::Return> {
) -> CoroutineState<Self::Yield, Self::Return> {
unsafe {
let g = &mut self.get_unchecked_mut().g;
match g {
Some(Err(g)) => match Pin::new_unchecked(g).resume(injs) {
GeneratorState::Yielded(effs) => GeneratorState::Yielded(effs),
GeneratorState::Complete(ret) => GeneratorState::Complete(Err(ret)),
CoroutineState::Yielded(effs) => CoroutineState::Yielded(effs),
CoroutineState::Complete(ret) => CoroutineState::Complete(Err(ret)),
},
Some(Ok(_)) => {
let Some(Ok(e)) = core::mem::take(g) else { unreachable!() };
GeneratorState::Complete(Ok(e))
let Some(Ok(e)) = core::mem::take(g) else {
unreachable!()
};
CoroutineState::Complete(Ok(e))
},
None => panic!("resumed after completed"),
}
Expand All @@ -149,22 +153,22 @@ pub trait ResultExt<T, E>: Sized {
fn map_eff<Effs, G>(self, g: impl FnOnce(T) -> G) -> ResultMapEff<G, E, Effs, G::Return>
where
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs>;
G: Coroutine<Effs::Injections, Yield = Effs>;

/// Transforms the value inside a [`Result::Err`] with some effects.
///
/// For more details, see [`OptionExt::map_eff`].
fn map_err_eff<Effs, G>(self, g: impl FnOnce(E) -> G) -> ResultMapErrEff<G, T, Effs, G::Return>
where
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs>;
G: Coroutine<Effs::Injections, Yield = Effs>;
}

impl<T, E> ResultExt<T, E> for Result<T, E> {
fn map_eff<Effs, G>(self, g: impl FnOnce(T) -> G) -> ResultMapEff<G, E, Effs, G::Return>
where
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs>,
G: Coroutine<Effs::Injections, Yield = Effs>,
{
ResultMapEff {
g: Some(self.map(g)),
Expand All @@ -176,7 +180,7 @@ impl<T, E> ResultExt<T, E> for Result<T, E> {
fn map_err_eff<Effs, G>(self, g: impl FnOnce(E) -> G) -> ResultMapErrEff<G, T, Effs, G::Return>
where
Effs: EffectList,
G: Generator<Effs::Injections, Yield = Effs>,
G: Coroutine<Effs::Injections, Yield = Effs>,
{
ResultMapErrEff {
g: Some(self.map_err(g)),
Expand Down
Loading

0 comments on commit 94e663f

Please sign in to comment.