Source file signature.ml
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
type counter_info = {
counter_info_min: int option;
counter_info_max: int option;
counter_default_value: int;
}
type 'links site_sig = {
internal_state: unit NamedDecls.t;
links: 'links option;
counter_info: counter_info option;
}
type t = bool array array site_sig NamedDecls.t
let fold f = NamedDecls.fold (fun i n o _ -> f i n o)
let num_of_site ?agent_name site_name signature =
let kind =
match agent_name with
| None -> "site name"
| Some agent_name -> "site name for agent " ^ agent_name
in
NamedDecls.elt_id ~kind signature site_name
let site_of_num addr signature =
try NamedDecls.elt_name signature addr
with Invalid_argument _ -> raise Not_found
let num_of_internal_state site_id state signature =
try
let site_name, site_sig = signature.NamedDecls.decls.(site_id) in
NamedDecls.elt_id
~kind:("internal state for site " ^ site_name)
site_sig.internal_state state
with Invalid_argument _ -> raise Not_found
let internal_state_of_site_id site_id val_id signature =
try
let site_sig = NamedDecls.elt_val signature site_id in
NamedDecls.elt_name site_sig.internal_state val_id
with Invalid_argument _ -> raise Not_found
let counter_of_site_id site_id signature =
try (NamedDecls.elt_val signature site_id).counter_info
with Invalid_argument _ -> raise Not_found
let has_counter signature =
fold
(fun p_id _ ok ->
try
let site_sig = NamedDecls.elt_val signature p_id in
ok || not (site_sig.counter_info = None)
with Invalid_argument _ -> raise Not_found)
false signature
let one_to_json =
NamedDecls.to_json (fun signature ->
`Assoc
[
( "internal_state",
NamedDecls.to_json (fun () -> `Null) signature.internal_state );
( "links",
JsonUtil.of_option
(fun links ->
`List
(Array.fold_right
(fun a acc ->
`List (Array.fold_right (fun b c -> `Bool b :: c) a [])
:: acc)
links []))
signature.links );
( "counter_info",
JsonUtil.of_option
(fun c ->
`Assoc
[
( "min",
JsonUtil.of_option (fun x -> `Int x) c.counter_info_min );
( "max",
JsonUtil.of_option (fun x -> `Int x) c.counter_info_max );
"default", `Int c.counter_default_value;
])
signature.counter_info );
])
let one_of_json : Yojson.Basic.t -> bool array array site_sig NamedDecls.t =
NamedDecls.of_json (function
| `Assoc [ ("internal_state", a); ("links", b); ("counter_info", c) ] ->
{
internal_state =
NamedDecls.of_json
(function
| `Null -> ()
| x ->
raise
(Yojson.Basic.Util.Type_error
("Problematic agent signature", x)))
a;
links =
Yojson.Basic.Util.to_option
(function
| `List l ->
Tools.array_map_of_list
(function
| `List l' ->
Tools.array_map_of_list
(function
| `Bool b -> b
| x ->
raise
(Yojson.Basic.Util.Type_error
("Problematic agent signature", x)))
l'
| x ->
raise
(Yojson.Basic.Util.Type_error
("Problematic agent signature", x)))
l
| x ->
raise
(Yojson.Basic.Util.Type_error
("Problematic agent signature", x)))
b;
counter_info =
Yojson.Basic.Util.to_option
(function
| `Assoc
[ ("min", c1_opt); ("max", c2_opt); ("default", `Int c3) ] ->
{
counter_info_min =
Yojson.Basic.Util.to_option
(function
| `Int c -> c
| x ->
raise
(Yojson.Basic.Util.Type_error
("Problematic agent signature", x)))
c1_opt;
counter_info_max =
Yojson.Basic.Util.to_option
(function
| `Int c -> c
| x ->
raise
(Yojson.Basic.Util.Type_error
("Problematic agent signature", x)))
c2_opt;
counter_default_value = c3;
}
| x ->
raise
(Yojson.Basic.Util.Type_error
("Problematic agent signature", x)))
c;
}
| x ->
raise (Yojson.Basic.Util.Type_error ("Problematic agent signature", x)))
type counter_agent_info = { id: int; arity: int; ports: int * int }
type s = {
agent_sigs: t NamedDecls.t;
counter_agent_info: counter_agent_info option;
}
let size sigs = NamedDecls.size sigs.agent_sigs
let get sigs agent_id = NamedDecls.elt_val sigs.agent_sigs agent_id
let arity sigs agent_id = NamedDecls.size (get sigs agent_id)
let max_arity sigs =
NamedDecls.fold (fun _ _ x a -> max x (NamedDecls.size a)) 0 sigs.agent_sigs
let agent_of_num i sigs = NamedDecls.elt_name sigs.agent_sigs i
let num_of_agent name sigs =
NamedDecls.elt_id ~kind:"agent" sigs.agent_sigs name
let id_of_site ((agent_name, _) as agent_ty) site_name sigs =
let n = num_of_agent agent_ty sigs in
num_of_site ~agent_name site_name (get sigs n)
let site_of_id agent_id site_id sigs = site_of_num site_id (get sigs agent_id)
let id_of_internal_state ((agent_name, _) as agent_ty) site_name state sigs =
let n = num_of_agent agent_ty sigs in
let signature = get sigs n in
let site_id = num_of_site ~agent_name site_name signature in
num_of_internal_state site_id state signature
let internal_state_of_id agent_id id_site id_state sigs =
internal_state_of_site_id id_site id_state (get sigs agent_id)
let internal_states_number agent_id site_id sigs =
try
let site_sig = NamedDecls.elt_val (get sigs agent_id) site_id in
NamedDecls.size site_sig.internal_state
with Invalid_argument _ -> raise Not_found
let default_internal_state agent_id site_id sigs =
try
let site_sig = NamedDecls.elt_val (get sigs agent_id) site_id in
if NamedDecls.size site_sig.internal_state = 0 then
None
else
Some 0
with Invalid_argument _ ->
invalid_arg "Signature.default_num_value: invalid site identifier"
let rec allowed_link ag1 s1 ag2 s2 sigs =
if ag1 > ag2 then
allowed_link ag2 s2 ag1 s1 sigs
else (
try
match (NamedDecls.elt_val (get sigs ag1) s1).links with
| None -> true
| Some l -> l.(ag2 - ag1).(s2)
with Invalid_argument _ ->
invalid_arg "Signature.allowed_link: invalid site identifier"
)
let create ~counters_per_agent agent_sigs =
{
agent_sigs;
counter_agent_info =
(if counters_per_agent = [] then
None
else
Some { id = 0; arity = 2; ports = 0, 1 });
}
let is_counter_agent sigs agent_id =
match sigs.counter_agent_info with
| None -> false
| Some agent_info -> agent_id = agent_info.id
let ports_if_counter_agent sigs agent_id =
match sigs.counter_agent_info with
| None -> None
| Some agent_info ->
if agent_id = agent_info.id then
Some agent_info.ports
else
None
let site_is_counter sigs ag_ty id =
counter_of_site_id id (get sigs ag_ty) <> None
let get_counter_agent_info sigs =
match sigs.counter_agent_info with
| None -> failwith "No counter agent"
| Some counter_agent_info -> counter_agent_info
let inverted_counter_suffix : string = "__inverted"
let is_inverted_counter (counter_name : string) : bool =
String.ends_with ~suffix:inverted_counter_suffix counter_name
let print_agent sigs f ag_ty =
Format.pp_print_string f @@ agent_of_num ag_ty sigs
let print_site sigs ag_ty f id =
Format.pp_print_string f @@ site_of_id ag_ty id sigs
let print_internal_state sigs ag_ty site f id =
Format.pp_print_string f @@ internal_state_of_id ag_ty site id sigs
let print_site_internal_state sigs ag_ty site f = function
| None -> print_site sigs ag_ty f site
| Some id ->
Format.fprintf f "%s{%s}"
(site_of_id ag_ty site sigs)
(internal_state_of_id ag_ty site id sigs)
let print_counter_info f = function
| None -> ()
| Some c ->
(match c.counter_info_min, c.counter_info_max with
| Some i, Some j when i = c.counter_default_value ->
Format.fprintf f "{=%d/+=%d}" i j
| i_opt, j_opt ->
Format.fprintf f "{-=%s/=%d/+=%s}"
(match i_opt with
| None -> "-oo"
| Some i -> Format.sprintf "%d" i)
c.counter_default_value
(match j_opt with
| None -> "-oo"
| Some i -> Format.sprintf "%d" i))
let print_counter sigs ag_ty f id =
print_counter_info f (counter_of_site_id id (get sigs ag_ty))
let print_one ?(sigs : s option) (i : int) (f : Format.formatter)
(signature : t) =
let pp_int f x =
if NamedDecls.size x > 0 then
Format.fprintf f "{%a}"
(NamedDecls.print ~sep:Pp.space (fun _ na f () ->
Format.fprintf f "%s" na))
x
in
let pp_link =
match sigs with
| None -> fun _ _ _ -> ()
| Some sigs ->
fun i f -> (function
| None -> ()
| Some links ->
Format.fprintf f "[%a]"
(Pp.array Pp.space (fun ag ->
Pp.array Pp.space (fun si f b ->
if b then
Format.fprintf f "%a.%a"
(print_site sigs (i + ag))
si (print_agent sigs) (i + ag))))
links)
in
(NamedDecls.print
~sep:(fun f -> Format.fprintf f ",@,")
(fun _ name f site_sig ->
Format.fprintf f "%s%a%a%a" name pp_int site_sig.internal_state
(pp_link i) site_sig.links print_counter_info site_sig.counter_info))
f signature
let print f sigs =
Format.fprintf f "@[<v>%a@]"
(NamedDecls.print ~sep:Pp.space (fun i n f si ->
Format.fprintf f "@[<h>%%agent: %s(%a)@]" n (print_one ~sigs i) si))
sigs.agent_sigs
let to_json sigs = NamedDecls.to_json one_to_json sigs.agent_sigs
let of_json v =
let agent_sigs : 'a site_sig NamedDecls.t NamedDecls.t =
NamedDecls.of_json one_of_json v
in
match
Mods.StringMap.find_option "__counter_agent" agent_sigs.NamedDecls.finder
with
| Some id ->
let agent_signature = NamedDecls.elt_val agent_sigs id in
let ports =
( num_of_site ("a", Loc.dummy) agent_signature,
num_of_site ("b", Loc.dummy) agent_signature )
in
{ agent_sigs; counter_agent_info = Some { id; arity = 2; ports } }
| None -> { agent_sigs; counter_agent_info = None }