use crate::process::{Pid, ProcessStatus};
use crate::sendable::{SendableValue, deserialize, serialize};
use crate::value::Value;
use crate::vm::VM;
pub enum ChildState {
Done(SendableValue),
Failed(String),
Running,
NotFound,
NotChild,
}
pub fn check_child_state(
child_status: Option<(&ProcessStatus, Option<Pid>)>,
parent_pid: Pid,
child_stack_top: Option<Value>,
child_heap: Option<&crate::heap::Heap>,
) -> ChildState {
match child_status {
None => ChildState::NotFound,
Some((_, parent)) if parent != Some(parent_pid) => ChildState::NotChild,
Some((ProcessStatus::Done, _)) => {
let val = child_stack_top.unwrap_or(Value::Unit);
let heap = child_heap.unwrap();
ChildState::Done(serialize(val, heap).unwrap_or(SendableValue::Unit))
}
Some((ProcessStatus::Failed(msg), _)) => ChildState::Failed(msg.clone()),
Some(_) => ChildState::Running,
}
}
pub fn deliver_result_to_parent(parent_vm: &mut VM, sendable: SendableValue) {
parent_vm.stack.pop(); let val = deserialize(sendable, &mut parent_vm.heap);
parent_vm.push_value(val);
}
pub fn deliver_message(vm: &mut VM, msg: SendableValue) {
vm.stack.pop(); let val = deserialize(msg, &mut vm.heap);
vm.push_value(val);
}
pub fn create_child_vm_from_parent(
parent_vm: &VM,
proto_idx: usize,
captures: Vec<SendableValue>,
) -> VM {
let mut child_vm = parent_vm.create_child();
let child_captures: Vec<Value> = captures
.into_iter()
.map(|v| deserialize(v, &mut child_vm.heap))
.collect();
child_vm.setup_closure_call(proto_idx, &child_captures);
child_vm
}
pub fn serialize_result(vm: &VM) -> SendableValue {
let val = vm.stack.last().copied().unwrap_or(Value::Unit);
serialize(val, &vm.heap).unwrap_or(SendableValue::Unit)
}
pub fn prepare_delivery(status: &ProcessStatus, vm: &VM) -> Result<SendableValue, String> {
match status {
ProcessStatus::Done => Ok(serialize_result(vm)),
ProcessStatus::Failed(msg) => Err(msg.clone()),
_ => Err("child not finished".into()),
}
}