use rf_core::context::Context; use rf_core::export::Export; use rf_core::lang::execution::round; use rf_core::path::Path; use rf_core::sensor_id::SensorId; use rf_core::vm::round_vm::RoundVM; use std::any::Any; use std::collections::HashMap; use std::fmt::Debug; use std::rc::Rc; use std::str::FromStr; pub fn init_vm() -> RoundVM { let context = Context::new( 1, Default::default(), Default::default(), Default::default(), ); init_with_ctx(context) } pub fn init_with_ctx(ctx: Context) -> RoundVM { let mut vm = RoundVM::new(ctx); vm.new_export_stack(); vm } pub fn push_to_ctx(mut ctx: Context, path: Path, val: A) -> Context { let mut export = Export::new(); export.put(path, val); ctx.put_export(ctx.self_id().clone(), export); ctx } pub fn vm( self_id: i32, local_sensor: HashMap>>, nbr_sensor: HashMap>>>, exports: HashMap, ) -> RoundVM { let context = Context::new(self_id, local_sensor, nbr_sensor, exports); init_with_ctx(context) } pub fn combine(expr1: F, expr2: G, comb: H) -> impl Fn(&mut RoundVM) -> A where F: Fn(&mut RoundVM) -> A, G: Fn(&mut RoundVM) -> A, H: Fn(A, A) -> A, { move |vm| { let res1 = expr1(vm); let res2 = expr2(vm); comb(res1, res2) } } pub fn assert_equivalence( exec_order: Vec, nbrs: HashMap>, program_1: F, program_2: G, ) -> bool where F: Fn(&mut RoundVM) -> A + Copy, G: Fn(&mut RoundVM) -> A + Copy, A: Eq + Clone + 'static + Debug + FromStr, { let states = nbrs .iter() .map(|(curr, neighbors)| { let ex_1: HashMap = neighbors .iter() .map(|nbr| (nbr.clone(), Export::new())) .collect(); let ex_2: HashMap = neighbors .iter() .map(|nbr| (nbr.clone(), Export::new())) .collect(); ( curr.clone(), ( vm(curr.clone(), Default::default(), Default::default(), ex_1), vm(curr.clone(), Default::default(), Default::default(), ex_2), ), ) }) .collect(); assert_equivalence_rec(exec_order, states, program_1, program_2) } fn assert_equivalence_rec( mut exec_order: Vec, states: HashMap, program_1: F, program_2: G, ) -> bool where F: Fn(&mut RoundVM) -> A + Copy, G: Fn(&mut RoundVM) -> A + Copy, A: Eq + Clone + 'static + Debug + FromStr, { if exec_order.is_empty() { return true; } let curr = exec_order.pop().unwrap(); let new_states = states .into_iter() .map(|(id, (mut vm_1, mut vm_2))| { if id == curr { let res_1 = round(&mut vm_1, program_1); let res_2 = round(&mut vm_2, program_2); if res_1 != res_2 { panic!("Programs are not equivalent: {:?} != {:?}", res_1, res_2); } (id, (vm_1, vm_2)) } else { (id, (vm_1, vm_2)) } }) .collect(); assert_equivalence_rec(exec_order, new_states, program_1, program_2) } pub fn fully_connected_topology_map(elems: Vec) -> HashMap> { let new_elems = elems.clone(); elems .into_iter() .map(|elem| (elem, new_elems.clone())) .collect() } #[derive(Debug, Clone)] pub struct DeviceState { pub self_id: i32, pub exports: HashMap, pub local_sensor: HashMap>>, pub nbr_sensor: HashMap>>>, } impl DeviceState { pub fn update_exports(&mut self, nbr: i32, export: Export) { self.exports.insert(nbr, export); } } #[derive(Debug, Clone)] pub struct Topology { pub devices: Vec, pub states: HashMap, } impl Topology { pub fn new(devices: Vec, states: HashMap) -> Self { Topology { devices, states } } }