use crate::stack::{Stack, pop, push};
use crate::value::{Value, WeaveMessage};
use std::sync::Arc;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_resume(stack: Stack) -> Stack {
if stack.is_null() {
eprintln!("strand.resume: stack is null (fatal programming error)");
std::process::abort();
}
let (stack, value) = unsafe { pop(stack) };
let (stack, handle) = unsafe { pop(stack) };
let (yield_chan, resume_chan) = match &handle {
Value::WeaveCtx {
yield_chan,
resume_chan,
} => (Arc::clone(yield_chan), Arc::clone(resume_chan)),
_ => {
eprintln!("strand.resume: expected WeaveHandle, got {:?}", handle);
std::process::abort();
}
};
let msg_to_send = WeaveMessage::Value(value.clone());
if resume_chan.sender.send(msg_to_send).is_err() {
let stack = unsafe { push(stack, handle) };
let stack = unsafe { push(stack, Value::Int(0)) };
return unsafe { push(stack, Value::Bool(false)) };
}
match yield_chan.receiver.recv() {
Ok(msg) => match msg {
WeaveMessage::Done => {
let stack = unsafe { push(stack, handle) };
let stack = unsafe { push(stack, Value::Int(0)) };
unsafe { push(stack, Value::Bool(false)) }
}
WeaveMessage::Value(yielded) => {
let stack = unsafe { push(stack, handle) };
let stack = unsafe { push(stack, yielded) };
unsafe { push(stack, Value::Bool(true)) }
}
WeaveMessage::Cancel => {
let stack = unsafe { push(stack, handle) };
let stack = unsafe { push(stack, Value::Int(0)) };
unsafe { push(stack, Value::Bool(false)) }
}
},
Err(_) => {
let stack = unsafe { push(stack, handle) };
let stack = unsafe { push(stack, Value::Int(0)) };
unsafe { push(stack, Value::Bool(false)) }
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_weave_cancel(stack: Stack) -> Stack {
if stack.is_null() {
eprintln!("strand.weave-cancel: stack is null (fatal programming error)");
std::process::abort();
}
let (stack, handle) = unsafe { pop(stack) };
match handle {
Value::WeaveCtx { resume_chan, .. } => {
let _ = resume_chan.sender.send(WeaveMessage::Cancel);
}
_ => {
eprintln!(
"strand.weave-cancel: expected WeaveHandle, got {:?}",
handle
);
std::process::abort();
}
}
stack
}