use std::any::Any;
use generator::Generator;
use rt::{Error, Context, ContextStack};
use reg_context::Context as RegContext;
#[inline]
pub fn yield_now() {
let env = ContextStack::current();
let mut cur = env.top();
let ref sp = cur.stack;
if sp.size() > 0 {
env.pop();
let parent = env.top();
RegContext::swap(&mut cur.regs, &parent.regs);
}
}
#[inline]
fn raw_yield<T: Any>(context: &mut Context, v: T) {
if !context.is_generator() {
error!("yield run at none generator context");
panic!(Error::ContextErr);
}
context.set_ret(v);
context._ref -= 1;
yield_now();
if context._ref != 1 {
panic!(Error::Cancel);
}
}
#[inline]
pub fn yield_with<T: Any>(v: T) {
raw_yield(ContextStack::current().top(), v);
}
#[inline]
pub fn get_yield<A: Any>() -> Option<A> {
let context = ContextStack::current().top();
context.get_para()
}
pub fn yield_from<'a, A: Any, T: Any>(mut g: Box<Generator<A, Output = T> + 'a>) {
let context = ContextStack::current().top();
while !g.is_done() {
let p = context.get_para();
let r = g.raw_send(p).unwrap();
raw_yield(context, r);
}
}
#[macro_export]
macro_rules! _yield {
($val:expr) => ({
let p = generator::get_yield().unwrap();
generator::yield_with($val);
p
});
() => (_yield!(()));
}
#[macro_export]
macro_rules! _yield_ {
($val:expr) => (generator::yield_with($val));
() => (_yield_!(()));
}