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}