1
|
(* This file is part of the Kind 2 model checker.
|
2
|
|
3
|
Copyright (c) 2015 by the Board of Trustees of the University of Iowa
|
4
|
|
5
|
Licensed under the Apache License, Version 2.0 (the "License"); you
|
6
|
may not use this file except in compliance with the License. You
|
7
|
may obtain a copy of the License at
|
8
|
|
9
|
http://www.apache.org/licenses/LICENSE-2.0
|
10
|
|
11
|
Unless required by applicable law or agreed to in writing, software
|
12
|
distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
14
|
implied. See the License for the specific language governing
|
15
|
permissions and limitations under the License.
|
16
|
|
17
|
*)
|
18
|
|
19
|
(** General-purpose library functions
|
20
|
|
21
|
@author Christoph Sticksel
|
22
|
*)
|
23
|
|
24
|
(** {1 Helper functions} *)
|
25
|
|
26
|
(** Identity function. *)
|
27
|
val identity : 'a -> 'a
|
28
|
|
29
|
(** Prints the first argument and returns the second. *)
|
30
|
val print_pass : string -> 'a -> 'a
|
31
|
|
32
|
(** Returns true when given unit. *)
|
33
|
val true_of_unit : unit -> bool
|
34
|
|
35
|
(** Returns false when given unit. *)
|
36
|
val false_of_unit : unit -> bool
|
37
|
|
38
|
(** Returns None when given unit. *)
|
39
|
val none_of_unit : unit -> 'a option
|
40
|
|
41
|
(** Return true *)
|
42
|
val true_of_any : 'a -> bool
|
43
|
|
44
|
(** Return false *)
|
45
|
val false_of_any : 'a -> bool
|
46
|
|
47
|
(* Creates a directory if it does not already exist. *)
|
48
|
val mk_dir : string -> unit
|
49
|
|
50
|
|
51
|
|
52
|
(** {1 Option types} *)
|
53
|
|
54
|
(** Return the value of an option type, raise [Invalid_argument "get"]
|
55
|
if the option value is [None] *)
|
56
|
val get : 'a option -> 'a
|
57
|
|
58
|
|
59
|
(** {1 Integer functions} *)
|
60
|
|
61
|
(** [string_starts_with s1 s2] returns true if the first characters of
|
62
|
[s1] up to the length of [s2] are ientical to [s2]. Return false if
|
63
|
[s2] is longer than [s1]. *)
|
64
|
val string_starts_with : string -> string -> bool
|
65
|
|
66
|
(** {1 Integer functions} *)
|
67
|
|
68
|
(** [safe_hash_interleave h m i] compute [m * h + i] and makes sure
|
69
|
that the result does not overflow to a negtive number *)
|
70
|
val safe_hash_interleave : int -> int -> int -> int
|
71
|
|
72
|
(** {1 List functions} *)
|
73
|
|
74
|
(** Add element to the head of the list if the option value is not [None].
|
75
|
|
76
|
The function symbol is right-associative and infix:
|
77
|
|
78
|
{[ Some 1 @:: None @:: Some 2 @:: [3;4] ]}
|
79
|
|
80
|
returns
|
81
|
|
82
|
{[ \[1;2;3;4\] ]}
|
83
|
*)
|
84
|
val ( @:: ) : 'a option -> 'a list -> 'a list
|
85
|
|
86
|
(** Creates a size-n list equal to [f 0; f 1; ... ; f (n-1)] *)
|
87
|
val list_init : (int -> 'a) -> int -> 'a list
|
88
|
|
89
|
(** Returns the maximum element of a non-empty list *)
|
90
|
val list_max : 'a list -> 'a
|
91
|
|
92
|
(** Return the index of the first element that satisfies the predicate
|
93
|
[p], raise excpetion [Not_found] if no element satisfies the
|
94
|
predicate. *)
|
95
|
val list_index : ('a -> bool) -> 'a list -> int
|
96
|
|
97
|
(** [list_indexes l1 l2] returns the indexes in list [l2] of elements
|
98
|
in list [l1] *)
|
99
|
val list_indexes : 'a list -> 'a list -> int list
|
100
|
|
101
|
(** [list_filter_nth l [p1; p2; ...]] returns the elements [l] at
|
102
|
positions [p1], [p2] etc. *)
|
103
|
val list_filter_nth : 'a list -> int list -> 'a list
|
104
|
|
105
|
(** Remove and returns the nth element form a list *)
|
106
|
val list_extract_nth : 'a list -> int -> 'a * 'a list
|
107
|
|
108
|
(** [chain_list \[e1; e2; ...\]] is [\[\[e1; e2\]; \[e2; e3\]; ... \]] *)
|
109
|
val chain_list : 'a list -> 'a list list
|
110
|
|
111
|
(** Return a list containing all values in the first list that are not
|
112
|
in the second list *)
|
113
|
val list_subtract : 'a list -> 'a list -> 'a list
|
114
|
|
115
|
(** From a sorted list return a list with physical duplicates removed *)
|
116
|
val list_uniq : 'a list -> 'a list
|
117
|
|
118
|
(** Merge two sorted lists without physical duplicates to a sorted list without
|
119
|
physical duplicates *)
|
120
|
val list_merge_uniq : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
121
|
|
122
|
(** From two sorted lists without physical duplicates return a sorted
|
123
|
list without physical duplicates containing elements in both
|
124
|
lists *)
|
125
|
val list_inter_uniq : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
126
|
|
127
|
(** From two sorted lists without physical duplicates return a sorted
|
128
|
list without physical duplicates containing elements in the first
|
129
|
but not in the second list *)
|
130
|
val list_diff_uniq : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
131
|
|
132
|
(** For two sorted lists without physical duplicates return true if
|
133
|
the first list contains a physically equal element for each element
|
134
|
in the second list *)
|
135
|
val list_subset_uniq : ('a -> 'a -> int) -> 'a list -> 'a list -> bool
|
136
|
|
137
|
(** Given two ordered association lists with identical keys, push the
|
138
|
values of each element of the first association list to the list of
|
139
|
elements of the second association list.
|
140
|
|
141
|
The returned association list is in the order of the input lists,
|
142
|
the function [equal] is used to compare keys. Raise [Failure
|
143
|
"list_join"] if the lists are not of identical length and the keys
|
144
|
at each element are equal. *)
|
145
|
val list_join : ('a -> 'a -> bool) -> ('a * 'b) list -> ('a * 'b list) list -> ('a * 'b list) list
|
146
|
|
147
|
(** Lexicographic comparison of pairs *)
|
148
|
val compare_pairs : ('a -> 'a -> int) -> ('b -> 'b -> int) -> 'a * 'b -> 'a * 'b -> int
|
149
|
|
150
|
(** Lexicographic comparison of lists *)
|
151
|
val compare_lists : ('a -> 'a -> int) -> 'a list -> 'a list -> int
|
152
|
|
153
|
(** {1 Array functions} *)
|
154
|
|
155
|
(** Returns the maximum element of a non-empty array *)
|
156
|
val array_max : 'a array -> 'a
|
157
|
|
158
|
(** {1 Set functions} *)
|
159
|
|
160
|
(** Sets of integers *)
|
161
|
module IntegerSet : Set.S with type elt = int
|
162
|
|
163
|
(** Hashtable of integers *)
|
164
|
module IntegerHashtbl : Hashtbl.S with type key = int
|
165
|
|
166
|
(** {1 Pretty-printing helpers} *)
|
167
|
|
168
|
(** Pretty-print an array with given separator
|
169
|
|
170
|
[pp_print_array elem_printer separator formatter array] calls,
|
171
|
for each index [i] of the array whose corresponding element is [element],
|
172
|
[elem_printer formatter i element]. Between each of these calls
|
173
|
it prints the string [separator].
|
174
|
|
175
|
In order to get line breaks between the elements, do not use a
|
176
|
line feed character [\n] as separator, this might mess up
|
177
|
indentation. Instead wrap the list into a vertical box with the
|
178
|
format string [@\[<v>%a@\]] and the empty string as separator.
|
179
|
|
180
|
*)
|
181
|
val pp_print_arrayi : (Format.formatter -> int -> 'a -> unit) -> (unit, Format.formatter, unit) format -> Format.formatter -> 'a array -> unit
|
182
|
|
183
|
(** Pretty-print a list with given separator
|
184
|
|
185
|
[pp_print_list p s f l] pretty-prints the elements in the list [l]
|
186
|
by calling the pretty-printer [p] on each, separating the elements
|
187
|
by printing the string [s].
|
188
|
|
189
|
In order to get line breaks between the elements, do not use a
|
190
|
line feed character [\n] as separator, this might mess up
|
191
|
indentation. Instead wrap the list into a vertical box with the
|
192
|
format string [@\[<v>%a@\]] and the empty string as separator.
|
193
|
*)
|
194
|
val pp_print_list : (Format.formatter -> 'a -> unit) -> ('b, Format.formatter, unit) format -> Format.formatter -> 'a list -> unit
|
195
|
|
196
|
(** Pretty-print a list with given separator and maintain a counter of elements
|
197
|
|
198
|
See {!pp_print_list}, except that the pretty-printer is passes an
|
199
|
zero-based counter for the list's elements as the argument
|
200
|
preceding the list element.
|
201
|
*)
|
202
|
val pp_print_listi : (Format.formatter -> int -> 'a -> unit) -> ('b, Format.formatter, unit) format -> Format.formatter -> 'a list -> unit
|
203
|
|
204
|
(** Pretty-print two lists of the same length with given separator and maintain
|
205
|
a counter of their elements.*)
|
206
|
val pp_print_list2i :
|
207
|
(Format.formatter -> int -> 'a -> 'b -> unit) ->
|
208
|
('c, Format.formatter, unit) format ->
|
209
|
Format.formatter -> 'a list -> 'b list -> unit
|
210
|
|
211
|
(** Pretty-print an option type *)
|
212
|
val pp_print_option : (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a option -> unit
|
213
|
|
214
|
(** Pretty-print if list is not empty *)
|
215
|
val pp_print_if_not_empty : (unit, Format.formatter, unit) format -> Format.formatter -> 'a list -> unit
|
216
|
|
217
|
(** Pretty-print into a string *)
|
218
|
val string_of_t : (Format.formatter -> 'a -> unit) -> 'a -> string
|
219
|
|
220
|
(** Return the width of the string, meaning the wisth of it's longest line *)
|
221
|
val width_of_string : string -> int
|
222
|
|
223
|
(** Return the strings as a parenthesized and space separated list *)
|
224
|
val paren_string_of_string_list : string list -> string
|
225
|
|
226
|
(** {1 Logging} *)
|
227
|
|
228
|
(** Levels of log messages
|
229
|
|
230
|
- [L_fatal] A severe error that will lead to an immediate abort
|
231
|
|
232
|
- [L_error] An error event that might still allow to continue
|
233
|
|
234
|
- [L_warn] A potentially harmful situation
|
235
|
|
236
|
- [L_note] An important note (soft warning)
|
237
|
|
238
|
- [L_info] An informational message that highlight progress at a
|
239
|
coarse-grained level
|
240
|
|
241
|
- [L_debug] A fine-grained informational event that is useful for
|
242
|
debugging but not for an end user
|
243
|
|
244
|
- [L_trace] A finer-grained informational event than [L_debug]
|
245
|
|
246
|
*)
|
247
|
type log_level =
|
248
|
| L_off
|
249
|
| L_fatal
|
250
|
| L_error
|
251
|
| L_warn
|
252
|
| L_note
|
253
|
| L_info
|
254
|
| L_debug
|
255
|
| L_trace
|
256
|
|
257
|
(** Default log level. *)
|
258
|
val default_log_level : log_level
|
259
|
|
260
|
(** Associate an integer with each level to induce a total ordering *)
|
261
|
val int_of_log_level : log_level -> int
|
262
|
|
263
|
val log_level_of_int : int -> log_level
|
264
|
|
265
|
val string_of_log_level : log_level -> string
|
266
|
|
267
|
(** Current formatter for output *)
|
268
|
val log_ppf : Format.formatter ref
|
269
|
|
270
|
(** Ouputs all log messages to the given file *)
|
271
|
val log_to_file : string -> unit
|
272
|
|
273
|
(** Write all log messages to the standard output *)
|
274
|
val log_to_stdout : unit -> unit
|
275
|
|
276
|
(** Set log level
|
277
|
|
278
|
Only output messages of levels with equal or higher priority *)
|
279
|
val set_log_level : log_level -> unit
|
280
|
|
281
|
(** Gets the log level. *)
|
282
|
val get_log_level : unit -> log_level
|
283
|
|
284
|
(** Return true if given log level is of higher or equal priority than
|
285
|
current log level? *)
|
286
|
val output_on_level : log_level -> bool
|
287
|
|
288
|
(** Return Format.fprintf if level is is of higher or equal priority
|
289
|
than current log level, otherwise return Format.ifprintf *)
|
290
|
val ignore_or_fprintf : log_level -> Format.formatter -> ('a, Format.formatter, unit) format -> 'a
|
291
|
|
292
|
|
293
|
(** {1 System functions} *)
|
294
|
|
295
|
(* (\** Output the banner on the formatter *\) *)
|
296
|
(* val pp_print_banner : Format.formatter -> unit -> unit *)
|
297
|
|
298
|
(* (\** Output the version number on the formatter *\) *)
|
299
|
(* val pp_print_version : Format.formatter -> unit *)
|
300
|
|
301
|
|
302
|
(** Kind modules *)
|
303
|
type kind_module =
|
304
|
[ `IC3
|
305
|
| `BMC
|
306
|
| `IND
|
307
|
| `IND2
|
308
|
| `INVGEN
|
309
|
| `INVGENOS
|
310
|
| `INVGENINT
|
311
|
| `INVGENINTOS
|
312
|
| `INVGENREAL
|
313
|
| `INVGENREALOS
|
314
|
| `C2I
|
315
|
| `Interpreter
|
316
|
| `Supervisor
|
317
|
| `Parser
|
318
|
| `Certif ]
|
319
|
|
320
|
(** Wallclock timeout *)
|
321
|
exception TimeoutWall
|
322
|
|
323
|
(** CPU timeout *)
|
324
|
exception TimeoutVirtual
|
325
|
|
326
|
(** System signal caught *)
|
327
|
exception Signal of int
|
328
|
|
329
|
(** String representation of signal *)
|
330
|
val string_of_signal : int -> string
|
331
|
|
332
|
(** Pretty-print the termination status of a process *)
|
333
|
val pp_print_process_status : Format.formatter -> Unix.process_status -> unit
|
334
|
|
335
|
(** Raise exception on signal *)
|
336
|
val exception_on_signal : int -> 'a
|
337
|
|
338
|
(** Pretty-print the name of a kind module *)
|
339
|
val pp_print_kind_module : Format.formatter -> kind_module -> unit
|
340
|
|
341
|
(** String representation of a process type *)
|
342
|
val string_of_kind_module : kind_module -> string
|
343
|
|
344
|
(** String representation of a process type *)
|
345
|
val int_of_kind_module : kind_module -> int
|
346
|
|
347
|
(** Return a short representation of kind module *)
|
348
|
val short_name_of_kind_module : kind_module -> string
|
349
|
|
350
|
(** Kind module of a string *)
|
351
|
val kind_module_of_string : string -> kind_module
|
352
|
|
353
|
(* (\** Sleep for seconds, resolution is in ms *\) *)
|
354
|
(* val minisleep : float -> unit *)
|
355
|
|
356
|
(** Return full path to executable, search PATH environment variable
|
357
|
and current working directory *)
|
358
|
val find_on_path : string -> string
|
359
|
|
360
|
(** {1 Positions in the input} *)
|
361
|
|
362
|
(** A position in the input *)
|
363
|
type position
|
364
|
|
365
|
(** Dummy position different from any valid position *)
|
366
|
val dummy_pos : position
|
367
|
|
368
|
(** Comparision on positions *)
|
369
|
val compare_pos : position -> position -> int
|
370
|
|
371
|
(** Return [true] if the position is not a valid position in the
|
372
|
input *)
|
373
|
val is_dummy_pos : position -> bool
|
374
|
|
375
|
(** Pretty-print a position *)
|
376
|
val pp_print_position : Format.formatter -> position -> unit
|
377
|
|
378
|
(** Pretty-print a position in a concise way *)
|
379
|
val pp_print_pos : Format.formatter -> position -> unit
|
380
|
|
381
|
(** Return the file, line and column of a position; fail with
|
382
|
[Invalid_argument "file_row_col_of_pos"] if the position is a dummy
|
383
|
position *)
|
384
|
val file_row_col_of_pos : position -> string * int * int
|
385
|
|
386
|
(** Inverse of {!file_row_col_of_pos} *)
|
387
|
val pos_of_file_row_col : string * int * int -> position
|
388
|
|
389
|
(** Convert a position of the lexer to a position *)
|
390
|
val position_of_lexing : Lexing.position -> position
|
391
|
|
392
|
|
393
|
(** Pretty print a backtrace *)
|
394
|
val print_backtrace : Format.formatter -> Printexc.raw_backtrace -> unit
|
395
|
|
396
|
|
397
|
(** Extract scope from a concatenated name *)
|
398
|
val extract_scope_name : string -> string * string list
|
399
|
|
400
|
(** Create a directory if it does not already exists. *)
|
401
|
val create_dir : string -> unit
|
402
|
|
403
|
(** Copying file: [file_copy from to] copies file [from] to file [to] *)
|
404
|
val file_copy : string -> string -> unit
|
405
|
|
406
|
val files_cat_open : ?add_prefix:(Format.formatter -> unit) ->
|
407
|
string list -> string -> Unix.file_descr
|
408
|
|
409
|
(** Get standard output of command *)
|
410
|
val syscall : string -> string
|
411
|
|
412
|
(** Changes garbage collector parameters limit its effect *)
|
413
|
val set_liberal_gc : unit -> unit
|
414
|
|
415
|
(** Reset the parameters of the GC to its default values. Call after
|
416
|
{!set_liberal_gc}. *)
|
417
|
val reset_gc_params : unit -> unit
|
418
|
|
419
|
(** Paths Kind 2 can write some files.
|
420
|
Factored to avoid clashes. *)
|
421
|
module Paths : sig
|
422
|
(** Test generation files path. *)
|
423
|
val testgen : string
|
424
|
(** Test generation oracle path. *)
|
425
|
val oracle : string
|
426
|
(** Rust generation path. *)
|
427
|
val implem : string
|
428
|
end
|
429
|
|
430
|
(** Reserved identifiers. *)
|
431
|
module ReservedIds : sig
|
432
|
|
433
|
(** New variables from abstraction. *)
|
434
|
val abs_ident_string: string
|
435
|
(** New oracle input. *)
|
436
|
val oracle_ident_string: string
|
437
|
(** Unique identifier for node instance. *)
|
438
|
val instance_ident_string: string
|
439
|
(** First instant flag. *)
|
440
|
val init_flag_ident_string: string
|
441
|
(** Observer for contract requirements. *)
|
442
|
val all_req_ident_string: string
|
443
|
(** Observer for contract ensures. *)
|
444
|
val all_ens_ident_string: string
|
445
|
(** New variables from node instance. *)
|
446
|
val inst_ident_string: string
|
447
|
(** Initial predicate. *)
|
448
|
val init_uf_string: string
|
449
|
(** Transition relation. *)
|
450
|
val trans_uf_string: string
|
451
|
(** New clock initialization flag. *)
|
452
|
val index_ident_string: string
|
453
|
|
454
|
(** Automaton state encoding. *)
|
455
|
val state_string: string
|
456
|
val restart_string: string
|
457
|
val state_selected_string: string
|
458
|
val restart_selected_string: string
|
459
|
val state_selected_next_string: string
|
460
|
val restart_selected_next_string: string
|
461
|
val handler_string: string
|
462
|
val unless_string: string
|
463
|
|
464
|
(** Init flag string. *)
|
465
|
val init_flag_string: string
|
466
|
(** Abstraction depth input string. *)
|
467
|
val depth_input_string: string
|
468
|
(** Abstraction depth input string. *)
|
469
|
val max_depth_input_string: string
|
470
|
(** Suffix used for the name of the function encoding functional systems. *)
|
471
|
val function_of_inputs: string
|
472
|
|
473
|
(** All reserved identifiers. *)
|
474
|
val reserved_strings: string list
|
475
|
|
476
|
end
|
477
|
|
478
|
(** Exit codes. *)
|
479
|
module ExitCodes: sig
|
480
|
(** Exit code for an unknown result. *)
|
481
|
val unknown: int
|
482
|
(** Exit code for an unsafe result. *)
|
483
|
val unsafe: int
|
484
|
(** Exit code for a safe result. *)
|
485
|
val safe: int
|
486
|
(** Exit code for an error. *)
|
487
|
val error: int
|
488
|
(** Exit status if kid caught a signal, the signal number is added to
|
489
|
the value *)
|
490
|
val kid_status: int
|
491
|
end
|
492
|
|
493
|
(** File names. *)
|
494
|
module Names: sig
|
495
|
(** Contract generation. *)
|
496
|
val contract_gen_file : string
|
497
|
(** Contract name for contract generation. *)
|
498
|
val contract_name : string list -> string
|
499
|
(** Invariant logging. *)
|
500
|
val inv_log_file : string
|
501
|
(** Contract name for invariant logging. *)
|
502
|
val inv_log_contract_name : string list -> string
|
503
|
end
|
504
|
|
505
|
(*
|
506
|
Local Variables:
|
507
|
compile-command: "make -C .. -k"
|
508
|
tuareg-interactive-program: "./kind2.top -I ./_build -I ./_build/SExpr"
|
509
|
indent-tabs-mode: nil
|
510
|
End:
|
511
|
*)
|