use crate::utils::{combine, init_vm, init_with_ctx, push_to_ctx};
use rf_core::context::Context;
use rf_core::export::Export;
use rf_core::lang::execution::round;
use rf_core::lang::{branch, foldhood, mid, nbr, rep};
use rf_core::path::Path;
use rf_core::sensor_id::sensor;
use rf_core::slot::Slot::{FoldHood, Nbr, Rep};
use rf_core::vm::round_vm::RoundVM;
use rf_core::{export, path};
use std::any::Any;
use std::collections::HashMap;
use std::rc::Rc;
#[test]
fn test_multiple_rounds() {
let mut vm = init_vm();
let program = |vm1: &mut RoundVM| {
rep(
vm1,
|_vm| 0,
|vm2, a| {
let res = nbr(vm2, |_vm| a);
res + 1
},
)
};
let res: i32 = round(&mut vm, program);
assert_eq!(1, res);
let ctx_ = push_to_ctx(vm.context().clone(), Path::from(vec![Rep(0)]), res);
let res_: i32 = round(&mut init_with_ctx(ctx_), program);
assert_eq!(2, res_);
}
#[test]
fn test_local_value() {
let context = Context::new(
0,
Default::default(),
Default::default(),
Default::default(),
);
let result = round(&mut init_with_ctx(context), |vm| 10);
assert_eq!(10, result);
}
#[test]
fn test_alignment() {
let context = Context::new(
0,
Default::default(),
Default::default(),
Default::default(),
);
let program = |vm1: &mut RoundVM| {
rep(
vm1,
|_vm| 0,
|vm2, _| foldhood(vm2, |_vm| 0, |a, b| a + b, |_vm3| 1),
)
};
let result = round(&mut init_with_ctx(context), program);
assert_eq!(1, result);
let export_dev_1 = export!((path!(Rep(0)), 1), (path!(FoldHood(0), Rep(0)), 1));
let mut exports: HashMap<i32, Export> = HashMap::new();
exports.insert(1, export_dev_1);
let context = Context::new(0, Default::default(), Default::default(), exports);
let mut vm = init_with_ctx(context);
let result = round(&mut vm, program);
assert_eq!(2, result);
}
#[test]
fn export_should_compose() {
fn ctx() -> Context {
Context::new(
0,
HashMap::from([(sensor("sensor"), Rc::new(Box::new(5) as Box<dyn Any>))]),
Default::default(),
Default::default(),
)
}
let expr_1 = |_vm: &mut RoundVM| 1;
let expr_2 = |vm: &mut RoundVM| rep(vm, |_vm1| 7, |_vm2, val| val + 1);
let expr_3 = |vm: &mut RoundVM| {
foldhood(
vm,
|_vm1| 0,
|a, b| (a + b),
|vm2| {
nbr(vm2, |vm3| {
*vm3.local_sense::<i32>(&sensor("sensor")).unwrap()
})
},
)
};
let mut vm = init_vm();
let _ = round(&mut vm, combine(expr_1, expr_1.clone(), |a, b| a + b));
assert_eq!(2, vm.export_data().root::<i32>().clone());
let mut vm1 = init_vm();
let _ = round(&mut vm1, combine(expr_2, expr_2.clone(), |a, b| a + b));
assert_eq!(16, vm1.export_data().root::<i32>().clone());
let mut vm2 = init_with_ctx(ctx());
let _ = round(
&mut vm2,
combine(expr_3, expr_3.clone(), |a, b| a + b),
);
assert_eq!(10, vm2.export_data().root::<i32>().clone());
let mut vm3 = init_vm();
let _ = round(&mut vm3, |vm: &mut RoundVM| {
rep(
vm,
|vm1| 0,
|vm2, _| rep(vm2, |_vm3| 0, |vm4, _| expr_1(vm4)),
)
});
assert_eq!(1, vm3.export_data().root::<i32>().clone());
let mut vm4 = init_vm();
let _ = round(&mut vm4, |vm| {
rep(
vm,
|vm1| 0,
|vm2, _| rep(vm2, |vm3| 0, |vm4, _| expr_2(vm4)),
)
});
assert_eq!(8, vm4.export_data().root::<i32>().clone());
let mut vm5 = init_with_ctx(ctx());
let _ = round(&mut vm5, |vm: &mut RoundVM| {
rep(
vm,
|_vm1| 0,
|vm2, _| rep(vm2, |_vm3| 0, |vm4, _| expr_3(vm4)),
)
});
assert_eq!(5, vm5.export_data().root::<i32>().clone());
}
#[test]
fn test_foldhood_basic() {
let export_dev_2 = export!((path!(), 1), (path!(FoldHood(0)), 1));
let export_dev_4 = export!((path!(), 3), (path!(FoldHood(0)), 3));
let mut exports: HashMap<i32, Export> = HashMap::new();
exports.insert(2, export_dev_2);
exports.insert(4, export_dev_4);
let context = Context::new(0, Default::default(), Default::default(), exports);
let program = |vm: &mut RoundVM| foldhood(vm, |_vm| 1, |a, b| a + b, |_vm1| 2);
let result = round(&mut init_with_ctx(context), program);
assert_eq!(7, result);
}
#[test]
fn test_foldhood_advanced() {
let export_dev_2 = export!(
(path!(), 1),
(path!(FoldHood(0)), 1),
(path!(Nbr(0), FoldHood(0)), 4)
);
let export_dev_4 = export!(
(path!(), 3),
(path!(FoldHood(0)), 3),
(path!(Nbr(0), FoldHood(0)), 19)
);
let mut exports: HashMap<i32, Export> = HashMap::new();
exports.insert(2, export_dev_2);
exports.insert(4, export_dev_4);
let context = Context::new(0, Default::default(), Default::default(), exports);
let program = |vm: &mut RoundVM| {
foldhood(
vm,
|_vm| -5,
|a, b| (a + b),
|vm1| nbr(vm1, |_vm2| 2),
)
};
let result = round(&mut init_with_ctx(context), program);
assert_eq!(20, result);
}
#[test]
fn test_nbr() {
fn create_exports_nbr_test() -> HashMap<i32, Export> {
let export_dev_1 = export!(
(path!(), "any"),
(path!(FoldHood(0)), 1),
(path!(Nbr(0), FoldHood(0)), 1)
);
let export_dev_2 = export!(
(path!(), "any"),
(path!(FoldHood(0)), 2),
(path!(Nbr(0), FoldHood(0)), 2)
);
let mut exports: HashMap<i32, Export> = HashMap::new();
exports.insert(1, export_dev_1);
exports.insert(2, export_dev_2);
exports
}
let context = Context::new(
0,
Default::default(),
Default::default(),
Default::default(),
);
let result = round(&mut init_with_ctx(context), |vm| nbr(vm, |vm1| 7));
assert_eq!(7, result);
let context = Context::new(
0,
Default::default(),
Default::default(),
create_exports_nbr_test(),
);
let program = |vm: &mut RoundVM| {
foldhood(
vm,
|_vm| 0,
|a, b| a + b,
|vm1| {
let res = nbr(vm1, mid);
if res == vm1.self_id().clone() {
0
} else {
1
}
},
)
};
let result = round(&mut init_with_ctx(context), program);
assert_eq!(2, result);
}
#[test]
fn test_rep() {
let context = Context::new(
0,
Default::default(),
Default::default(),
Default::default(),
);
let program = |vm: &mut RoundVM| rep(vm, |vm| 9, |vm1, a| a * 2);
let result = round(&mut init_with_ctx(context), program);
assert_eq!(18, result);
let export_dev_0 = export!((path!(Rep(0)), 7));
let mut exports: HashMap<i32, Export> = HashMap::new();
exports.insert(0, export_dev_0);
let context = Context::new(0, Default::default(), Default::default(), exports);
let result = round(&mut init_with_ctx(context), program);
assert_eq!(14, result);
}
#[test]
fn test_branch() {
let program = |vm: &mut RoundVM| {
rep(
vm,
|_vm| 0,
|vm1, x| {
branch(
vm1,
|| x % 2 == 0,
|_vm3| 7,
|vm4| rep(vm4, |_vm| 4, |_vm5, _| 4),
);
x + 1
},
)
};
let context = Context::new(
0,
Default::default(),
Default::default(),
Default::default(),
);
let result = round(&mut init_with_ctx(context), program);
assert_eq!(1, result);
let export_dev_0 = export!((path!(Rep(0)), 1));
let mut exports: HashMap<i32, Export> = HashMap::new();
exports.insert(0, export_dev_0);
let context = Context::new(0, Default::default(), Default::default(), exports);
let result = round(&mut init_with_ctx(context), program);
assert_eq!(2, result);
}
#[test]
fn test_sense() {
fn ctx() -> Context {
Context::new(
0,
HashMap::from([
(sensor("a"), Rc::new(Box::new(7) as Box<dyn Any>)),
(sensor("b"), Rc::new(Box::new("right") as Box<dyn Any>)),
]),
Default::default(),
Default::default(),
)
}
let res = round(&mut init_with_ctx(ctx()), |vm| {
vm.local_sense::<i32>(&sensor("a")).unwrap().clone()
});
assert_eq!(7, res);
let res = round(&mut init_with_ctx(ctx()), |vm| {
vm.local_sense::<&str>(&sensor("b")).cloned().unwrap().to_string()
});
assert_eq!("right", res);
}