rf_core/lang.rs
1use crate::slot::Slot::{Branch, FoldHood, Nbr, Rep};
2use crate::vm::round_vm::RoundVM;
3use std::str::FromStr;
4
5pub mod builtins;
6pub mod execution;
7pub mod macros;
8
9/// Observes the value of an expression across neighbors, producing a “field of fields”.
10///
11/// # Arguments
12///
13/// * `vm` the current VM
14/// * `expr` the expression to evaluate
15///
16/// # Generic Parameters
17///
18/// * `A` The type of value returned by the expression.
19/// * `F` - The type of the closure, which must be a closure that takes a `RoundVM` as argument and returns a tuple `(RoundVM, A)`.
20///
21/// # Returns
22///
23/// the value of the expression
24pub fn nbr<A: Clone + 'static + FromStr, F>(vm: &mut RoundVM, expr: F) -> A
25where
26 F: Fn(&mut RoundVM) -> A,
27{
28 vm.nest(
29 Nbr(vm.index()),
30 vm.unless_folding_on_others(),
31 true,
32 |vm| match vm.neighbor() {
33 Some(nbr) if nbr != vm.self_id() => match vm.neighbor_val::<A>() {
34 Ok(val) => val,
35 _ => expr(vm),
36 },
37 _ => expr(vm),
38 },
39 )
40}
41
42/// Iteratively updates the value of the input expression at each device using the last computed value.
43///
44/// # Arguments
45///
46/// * `vm` the current VM
47/// * `init` the initial value
48/// * `fun` the function to apply to the value
49///
50/// # Generic Parameters
51///
52/// * `A` The type of value returned by the expression.
53/// * `F` - The type of the closure, which must be a closure that takes no arguments and returns a value of type `A`.
54/// * `G` - The type of the closure, which must be a closure that takes a tuple `(RoundVM, A)` and returns a tuple `(RoundVM, A)`.
55///
56/// # Returns
57///
58/// the updated value
59pub fn rep<A: Clone + 'static + FromStr, F, G>(vm: &mut RoundVM, init: F, fun: G) -> A
60where
61 F: Fn(&mut RoundVM) -> A,
62 G: Fn(&mut RoundVM, A) -> A,
63{
64 vm.nest(Rep(vm.index()), vm.unless_folding_on_others(), true, |vm| {
65 if vm.previous_round_val::<A>().is_ok() {
66 let prev = vm.previous_round_val::<A>().unwrap().clone();
67 fun(vm, prev)
68 } else {
69 let init_args = init(vm);
70 fun(vm, init_args)
71 }
72 })
73}
74
75/// Aggregates the results of the neighbor computation.
76///
77/// # Arguments
78///
79/// * `vm` the current VM
80/// * `init` the initial value
81/// * `aggr` the function to apply to the value
82/// * `expr` the expression to evaluate
83///
84/// # Generic Parameters
85///
86/// * `A` The type of value returned by the expression.
87/// * `F` - The type of inti, which must be a closure that takes no arguments and returns a value of type `A`.
88/// * `G` - The type of aggr, which must be a closure that takes a tuple `(A, A)` and returns a value of type `A`.
89/// * `H` - The type of expr, which must be a closure that takes a `RoundVM` as argument and returns a tuple `(RoundVM, A)`.
90///
91/// # Returns
92///
93/// the aggregated value
94pub fn foldhood<A: Clone + 'static + FromStr, F, G, H>(
95 vm: &mut RoundVM,
96 init: F,
97 aggr: G,
98 expr: H,
99) -> A
100where
101 F: Fn(&mut RoundVM) -> A + Copy,
102 G: Fn(A, A) -> A,
103 H: Fn(&mut RoundVM) -> A + Copy,
104{
105 vm.nest(FoldHood(vm.index()), true, true, |vm| {
106 let local_init = vm.locally(init);
107 let mut nbr_field: Vec<A> = Vec::new();
108
109 //fill the nbr_field with the values from neighbours
110 vm.aligned_neighbours::<A>().iter().for_each(|id| {
111 let opt = vm.folded_eval(expr, *id);
112 nbr_field.push(opt.unwrap_or(local_init.clone()));
113 });
114
115 //fold the nbr_field with the provided aggregation function
116 vm.isolate(|_vm| {
117 let res = nbr_field
118 .iter()
119 .fold(local_init.clone(), |x, y| aggr(x, y.clone()));
120 res
121 })
122 })
123}
124
125/// Partitions the domain into two subspaces that do not interact with each other.
126///
127/// # Arguments
128///
129/// * `vm` the current VM
130/// * `cond` the condition to evaluate
131/// * `thn` the expression to evaluate if the condition is true
132/// * `els` the expression to evaluate if the condition is false
133///
134/// # Generic Parameters
135///
136/// * `A` The type of value returned by the expression.
137/// * `B` - The type of cond, which must be a closure that takes no arguments and returns a value of type `bool`.
138/// * `F` - The type of thn and els, which must be a closure that takes a `RoundVM` as argument and returns a tuple `(RoundVM, A)`.
139///
140/// # Returns
141///
142/// the value of the expression
143pub fn branch<A: Clone + 'static + FromStr, B, TH, EL>(
144 vm: &mut RoundVM,
145 cond: B,
146 thn: TH,
147 els: EL,
148) -> A
149where
150 B: Fn() -> bool,
151 TH: Fn(&mut RoundVM) -> A + Copy,
152 EL: Fn(&mut RoundVM) -> A + Copy,
153{
154 vm.nest(
155 Branch(vm.index()),
156 vm.unless_folding_on_others(),
157 true,
158 |mut vm| {
159 let tag = vm.locally(|_vm1| cond());
160 let val: A = match vm.neighbor() {
161 Some(nbr) if nbr != vm.self_id() => {
162 vm.neighbor_val::<A>().unwrap()
163 }
164 _ => {
165 if tag {
166 vm.locally(thn)
167 } else {
168 vm.locally(els)
169 }
170 }
171 };
172 val
173 },
174 )
175}
176
177/// Returns the id of the current device.
178///
179/// # Arguments
180///
181/// * `vm` the current VM
182///
183/// # Returns
184///
185/// the id of the current device
186pub fn mid(vm: &mut RoundVM) -> i32 {
187 *vm.self_id()
188}