chandeliers_sem/
registers.rs

1//! Stateful expressions
2
3use crate::nillable::{AllNil, FirstIsNil};
4
5/// A device that returns true exactly once and then always false.
6pub struct Flip(bool);
7
8impl Default for Flip {
9    #[inline]
10    fn default() -> Self {
11        Self(true)
12    }
13}
14
15impl Flip {
16    /// Test and set: returns `true` once and `false` permanently afterwards.
17    #[inline]
18    pub fn tas(&mut self) -> bool {
19        let res = self.0;
20        self.0 = false;
21        res
22    }
23}
24
25/// A device that can store an arbitrary value in between executions.
26pub struct Register<T> {
27    /// Value saved for the next execution.
28    inner: T,
29    /// Not yet commited next value.
30    next: T,
31    /// Whether the clock is currently active.
32    on_clock: bool,
33}
34
35impl<T> Default for Register<T>
36where
37    T: AllNil,
38{
39    #[inline]
40    fn default() -> Self {
41        Self {
42            inner: T::auto_size(),
43            next: T::auto_size(),
44            on_clock: false,
45        }
46    }
47}
48
49impl<T> Register<T> {
50    /// Store a value that can then be obtained later exactly once.
51    #[inline]
52    pub fn schedule(&mut self, t: T)
53    where
54        T: FirstIsNil,
55    {
56        if !t.first_is_nil() {
57            self.next = t;
58        }
59    }
60
61    /// Activate or not this register for this round.
62    #[inline]
63    pub fn with_clock(&mut self, clk: crate::nillable::Nillable<bool>) {
64        self.on_clock = clk.is(crate::nillable::Nillable::Defined(true));
65    }
66
67    /// Store the very first value of the register.
68    #[inline]
69    pub fn try_initialize(&mut self, t: T)
70    where
71        T: FirstIsNil,
72    {
73        if self.inner.first_is_nil() {
74            self.inner = t;
75        }
76    }
77
78    /// Move `next` to become the current value.
79    #[inline]
80    pub fn commit(&mut self)
81    where
82        T: Clone,
83    {
84        self.inner = self.next.clone();
85    }
86
87    /// Extract the inner value.
88    #[inline]
89    pub fn get(&mut self) -> T
90    where
91        T: Clone + AllNil,
92    {
93        if self.on_clock {
94            self.inner.clone()
95        } else {
96            T::auto_size()
97        }
98    }
99}