/
fsm.v
95 lines (81 loc) · 2.32 KB
/
fsm.v
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
module fsm
pub type EventHandlerFn = fn (receiver voidptr, from string, to string)
pub type ConditionFn = fn (receiver voidptr, from string, to string) bool
fn dummy_event_handler_fn(receiver voidptr, from string, to string) {
}
fn dummy_condition_fn(receiver voidptr, from string, to string) bool {
return true
}
struct State {
mut:
entry_handler EventHandlerFn = dummy_event_handler_fn
run_handler EventHandlerFn = dummy_event_handler_fn
exit_handler EventHandlerFn = dummy_event_handler_fn
}
struct Transition {
mut:
to string
condition_handler ConditionFn = dummy_condition_fn
}
pub struct StateMachine {
mut:
states map[string]State
transitions map[string][]Transition
current_state string
}
pub fn new() StateMachine {
return StateMachine{}
}
pub fn (mut s StateMachine) set_state(name string) ! {
if name in s.states {
s.current_state = name
} else {
return error('unknown state: ${name}')
}
}
pub fn (mut s StateMachine) get_state() string {
return s.current_state
}
pub fn (mut s StateMachine) add_state(name string, entry EventHandlerFn, run EventHandlerFn, exit EventHandlerFn) {
s.states[name] = State{
entry_handler: entry
run_handler: run
exit_handler: exit
}
if s.states.len == 1 {
s.current_state = name
}
}
pub fn (mut s StateMachine) add_transition(from string, to string, condition_handler ConditionFn) {
t := Transition{
to: to
condition_handler: condition_handler
}
if from in s.transitions {
s.transitions[from] << t
return
}
s.transitions[from] = [t]
}
pub fn (mut s StateMachine) run(receiver voidptr) ! {
from_state := s.current_state
mut to_state := s.current_state
if transitions := s.transitions[s.current_state] {
for transition in transitions {
if transition.condition_handler(receiver, from_state, transition.to) {
s.change_state(receiver, transition.to)
to_state = transition.to
break
}
}
} else {
s.states[s.current_state].run_handler(receiver, from_state, to_state)
return error('no more transitions')
}
s.states[s.current_state].run_handler(receiver, from_state, to_state)
}
fn (mut s StateMachine) change_state(receiver voidptr, newstate string) {
s.states[s.current_state].exit_handler(receiver, s.current_state, newstate)
s.states[newstate].entry_handler(receiver, s.current_state, newstate)
s.current_state = newstate
}