-
Notifications
You must be signed in to change notification settings - Fork 2
/
ping-pong-protocol.sml
108 lines (80 loc) · 2.36 KB
/
ping-pong-protocol.sml
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
structure PingPongProtocol =
struct
structure PingPongMessage =
struct
datatype ping_pong_msg =
Ping of int * int |
Pong of int * int
type t = ping_pong_msg
fun sender (Ping (id, seq)) = id
| sender (Pong (id, seq)) = id
fun hash m = Word.fromInt 0
fun eq (Ping (u, v), Ping (x, y)) = (u = x) andalso (v = y)
| eq (Pong (u, v), Pong (x, y)) = (u = x) andalso (v = y)
| eq (_, _) = false
fun toString (Ping (id, seq)) =
"Ping " ^ Int.toString seq ^ " (from " ^ Int.toString id ^ ")"
| toString (Pong (id, seq)) =
"Pong " ^ Int.toString seq ^ " (from " ^ Int.toString id ^ ")"
exception ParseError
fun fromString _ = Ping (0, 0)
end (* PingPongMessage *)
structure Msg = PingPongMessage
structure State =
struct
datatype state = State of {id : int, counter : int, bound : int}
type t = state
fun toString (State {id, counter, bound}) =
"State "
^ "{ id: " ^ Int.toString id
^ ", counter: " ^ Int.toString counter
^ ", bound: " ^ Int.toString bound ^ " }"
end (* PingPongState *)
structure Param =
struct
datatype param = Param of {id : int, leader : bool, bound : int}
type t = param
fun id (Param {id, leader, bound}) = id
fun toString (Param {id, leader, bound}) =
"Param "
^ "{ id: " ^ Int.toString id
^ ", leader: " ^ Bool.toString leader
^ ", bound: " ^ Int.toString bound ^ " }"
end (* PingPongParam *)
type msg = PingPongMessage.t
type state = State.t
type param = Param.t
fun init param =
let
open PingPongMessage
open Param
open State
val Param {id, leader, bound} = param
val init_msgs = if leader then [Ping (id, 0)] else []
val init_state = State {id = id, counter = 0, bound = bound}
in
(init_msgs, init_state)
end
fun process (m, state) =
let
open PingPongMessage
fun sender (Ping (id, _)) = id
| sender (Pong (id, _)) = id
open State
val State {id, counter, bound} = state
in
if sender m = id then
([], state)
else
(case m of Ping (_, seq) => [Pong (id, seq)]
| Pong (_, seq) => [Ping (id, seq + 1)],
State {id = id, counter = counter + 1, bound = bound})
end
fun terminate state =
let
open State
val State {id, counter, bound} = state
in
counter >= bound
end
end (* PingPong *)