use crate::slot::Slot::{Branch, FoldHood, Nbr, Rep};
use crate::vm::round_vm::RoundVM;
use std::str::FromStr;
pub mod builtins;
pub mod execution;
pub mod macros;
pub fn nbr<A: Clone + 'static + FromStr, F>(vm: &mut RoundVM, expr: F) -> A
where
F: Fn(&mut RoundVM) -> A,
{
vm.nest(
Nbr(vm.index()),
vm.unless_folding_on_others(),
true,
|vm| match vm.neighbor() {
Some(nbr) if nbr != vm.self_id() => match vm.neighbor_val::<A>() {
Ok(val) => val,
_ => expr(vm),
},
_ => expr(vm),
},
)
}
pub fn rep<A: Clone + 'static + FromStr, F, G>(vm: &mut RoundVM, init: F, fun: G) -> A
where
F: Fn(&mut RoundVM) -> A,
G: Fn(&mut RoundVM, A) -> A,
{
vm.nest(Rep(vm.index()), vm.unless_folding_on_others(), true, |vm| {
if vm.previous_round_val::<A>().is_ok() {
let prev = vm.previous_round_val::<A>().unwrap().clone();
fun(vm, prev)
} else {
let init_args = init(vm);
fun(vm, init_args)
}
})
}
pub fn foldhood<A: Clone + 'static + FromStr, F, G, H>(
vm: &mut RoundVM,
init: F,
aggr: G,
expr: H,
) -> A
where
F: Fn(&mut RoundVM) -> A + Copy,
G: Fn(A, A) -> A,
H: Fn(&mut RoundVM) -> A + Copy,
{
vm.nest(FoldHood(vm.index()), true, true, |vm| {
let local_init = vm.locally(init);
let mut nbr_field: Vec<A> = Vec::new();
vm.aligned_neighbours::<A>().iter().for_each(|id| {
let opt = vm.folded_eval(expr, *id);
nbr_field.push(opt.unwrap_or(local_init.clone()));
});
vm.isolate(|_vm| {
let res = nbr_field
.iter()
.fold(local_init.clone(), |x, y| aggr(x, y.clone()));
res
})
})
}
pub fn branch<A: Clone + 'static + FromStr, B, TH, EL>(
vm: &mut RoundVM,
cond: B,
thn: TH,
els: EL,
) -> A
where
B: Fn() -> bool,
TH: Fn(&mut RoundVM) -> A + Copy,
EL: Fn(&mut RoundVM) -> A + Copy,
{
vm.nest(
Branch(vm.index()),
vm.unless_folding_on_others(),
true,
|mut vm| {
let tag = vm.locally(|_vm1| cond());
let val: A = match vm.neighbor() {
Some(nbr) if nbr != vm.self_id() => {
vm.neighbor_val::<A>().unwrap()
}
_ => {
if tag {
vm.locally(thn)
} else {
vm.locally(els)
}
}
};
val
},
)
}
pub fn mid(vm: &mut RoundVM) -> i32 {
*vm.self_id()
}