1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#[macro_export]
macro_rules! state_machine {
{
$(#[$attr:meta])*
$vis:vis $name:ident $(($($iname:ident: $itype:ty),+ $(,)?))? $({
$(
$(#[$vattr:meta])*
$vname:ident: $vtype:ty = $vinit:expr
),+ $(,)?
})? = $init:ident($($arg:expr),*);
$(
$(#[$fattr:meta])*
$state:ident ($ctx:ident $(, $pname:ident: $ptype:ty)* $(,)?) $([$($vref:ident),*])? $(-> $fret:ty)? $body:block
)*
} => {
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
$vis enum State {
$(
#[allow(non_camel_case_types)]
#[allow(missing_docs)]
$state($($ptype),*),
)*
}
#[derive(Clone)]
struct Vars {
$(
$(
$(#[$vattr])*
$vname: $vtype,
)+
)?
}
impl Vars {
$(
fn $state(&mut self, $ctx: $crate::rtos::Context, $($pname: $ptype),*) $(-> $fret)? {
$(
$(
let $vref: &mut _ = &mut self.$vref;
)*
)?
$body
}
)*
}
struct Data {
state: State,
#[allow(dead_code)]
promise: $crate::rtos::Promise<Vars>,
ctxw: $crate::rtos::ContextWrapper,
}
$(#[$attr])*
$vis struct $name($crate::rtos::Mutex<Data>);
impl $name {
pub fn new($($($iname: $itype),+)?) -> Self {
let (promise, resolve) = $crate::rtos::Promise::new();
$(
$(
let $vname = $vinit;
)+
)?
resolve(Vars {
$(
$(
$vname,
)+
)?
});
let state = State::$init($($arg),*);
let r = Self($crate::rtos::Mutex::new(Data {
state: ::core::clone::Clone::clone(&state),
promise,
ctxw: $crate::rtos::ContextWrapper::new(),
}));
$crate::machine::StateMachine::transition(&r, state);
r
}
$(
$(#[$fattr])*
pub fn $state(&self, $($pname: $ptype),*) -> $crate::rtos::Promise $(<$fret>)? {
let mut lock = self.0.lock();
let ctx = lock.ctxw.replace();
lock.state = State::$state($(::core::clone::Clone::clone($pname)),*);
let promise = lock.promise.then(move |vars: &Vars| {
let mut vars = ::core::clone::Clone::clone(vars);
let r = vars.$state(ctx, $($pname),*);
(vars, r)
});
lock.promise = promise.then(|(vars, _)| ::core::clone::Clone::clone(vars));
promise.then(|(_, r)| ::core::clone::Clone::clone(r))
}
)*
}
impl $crate::machine::StateMachine for $name {
type State = State;
#[inline]
fn state(&self) -> State {
self.0.lock().state.clone()
}
#[inline]
fn transition(&self, state: State) {
match state {
$(
State::$state($($pname),*) => self.$state($($pname),*),
)*
};
}
}
};
}