extlib.mli 16.1 KB
Newer Older
1
2
3
4
(**************************************************************************)
(*                                                                        *)
(*  This file is part of Frama-C.                                         *)
(*                                                                        *)
Andre Maroneze's avatar
Andre Maroneze committed
5
(*  Copyright (C) 2007-2020                                               *)
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
(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
(*         alternatives)                                                  *)
(*                                                                        *)
(*  you can redistribute it and/or modify it under the terms of the GNU   *)
(*  Lesser General Public License as published by the Free Software       *)
(*  Foundation, version 2.1.                                              *)
(*                                                                        *)
(*  It is distributed in the hope that it will be useful,                 *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
(*  GNU Lesser General Public License for more details.                   *)
(*                                                                        *)
(*  See the GNU Lesser General Public License version 2.1                 *)
(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
(*                                                                        *)
(**************************************************************************)

(** Useful operations.
    This module does not depend of any of frama-c module. *)

val nop: 'a -> unit
  (** Do nothing. *)

external id: 'a -> 'a = "%identity"
  (** identity function.
      @since Oxygen-20120901
   *)


val adapt_filename: string -> string
  (** Ensure that the given filename has the extension "cmo" in bytecode
      and "cmxs" in native *)

val max_cpt: int -> int -> int
(** [max_cpt t1 t2] returns the maximum of [t1] and [t2] wrt the total ordering
    induced by tags creation. This ordering is defined as follows:
    forall tags t1 t2, t1 <= t2 iff t1 is before t2 in the finite sequence
    [0; 1; ..; max_int; min_int; min_int-1; -1] *)

val number_to_color: int -> int

(* ************************************************************************* *)
(** {2 Function builders} *)
(* ************************************************************************* *)

exception Unregistered_function of string
(** Never catch it yourself: let the kernel do the job.
    @since Oxygen-20120901 *)

val mk_labeled_fun: string -> 'a
(** To be used to initialized a reference over a labeled function.
    @since Oxygen-20120901
    @raise Unregistered_function when not properly initialized *)

val mk_fun: string -> ('a -> 'b) ref
  (** Build a reference to an uninitialized function
      @raise Unregistered_function when not properly initialized *)

(* ************************************************************************* *)
(** {2 Function combinators} *)
(* ************************************************************************* *)

val ($) : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c
  (** Composition. *)

val swap: ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
  (** Swap arguments. *)

val uncurry: ('a -> 'b -> 'c) -> ('a * 'b) -> 'c

val iter_uncurry2:
  (('a -> 'b -> unit) -> 'c -> unit) ->
  (('a * 'b -> unit) -> 'c -> unit)

(* ************************************************************************* *)
(** {2 Lists} *)
(* ************************************************************************* *)

val as_singleton: 'a list -> 'a
  (** returns the unique element of a singleton list.
      @raise Invalid_argument on a non singleton list. *)

val last: 'a list -> 'a
  (** returns the last element of a list.
      @raise Invalid_argument on an empty list
      @since Nitrogen-20111001 *)

val filter_out: ('a -> bool) -> 'a list -> 'a list
  (** Filter out elements that pass the test *)

val replace: ('a -> 'a -> bool) -> 'a -> 'a list -> 'a list
  (** [replace cmp x l] replaces the first element [y] of [l] such that
      [cmp x y] is true by [x]. If no such element exists, [x] is added
      at the tail of [l].
      @since Neon-20140301 
   *)

val filter_map: ('a -> bool) -> ('a -> 'b) -> 'a list -> 'b list
val filter_map': ('a -> 'b) -> ('b -> bool) -> 'a list -> 'b list
François Bobot's avatar
François Bobot committed
105
val filter_map_opt: ('a -> 'b option) -> 'a list -> 'b list
106
107
  (** Combines [filter] and [map]. *)

108
val fold_map: ('a -> 'b -> 'a * 'c) -> 'a -> 'b list -> 'a * 'c list
François Bobot's avatar
François Bobot committed
109
(** Combines [fold_left] and [map] *)
110
val fold_map_opt: ('a -> 'b -> 'a * 'c option) -> 'a -> 'b list -> 'a * 'c list
François Bobot's avatar
François Bobot committed
111
112
(** Combines [filter] [fold_left] and [map] *)

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
val product_fold: ('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a
(** [product f acc l1 l2] is similar to [fold_left f acc l12] with l12 the
    list of all pairs of an elt of [l1] and an elt of [l2]
*)

val product: ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list
  (** [product f l1 l2] applies [f] to all the pairs of an elt of [l1] and
      an element of [l2].
   *)

val find_index: ('a -> bool) -> 'a list -> int
  (** returns the index (starting at 0) of the first element verifying the
      condition
      @raise Not_found if no element in the list matches the condition
   *)

val list_compare : ('a -> 'a -> int) -> 'a list -> 'a list -> int
  (** Generic list comparison function, where the elements are compared
      with the specified function
      @since Boron-20100401 *)

val list_of_opt: 'a option -> 'a list
  (** converts an option into a list with 0 or 1 elt.
      @since Carbon-20111201-beta2 *)

val opt_of_list: 'a list -> 'a option
  (** converts a list with 0 or 1 element into an option.
      @raise Invalid_argument on lists with more than one argument
      @since Oxygen-20120901 *)

val find_opt : ('a -> 'b option) -> 'a list -> 'b
144
[@@deprecated "Use List.find_opt instead."]
145
146
147
148
149
  (** [find_option p l] returns the value [p e], [e] being the first
      element of [l] such that [p e] is not [None]. Raise [Not_found] if there
      is no such value the list l.

      @since Nitrogen-20111001
150
      @deprecated 18.0-Argon use [List.find_opt] instead *)
151
152
153
154
155
156
157
158
159
160
161
162

val iteri: (int -> 'a -> unit) -> 'a list -> unit
  (** Same as iter, but the function to be applied take also as argument the
      index of the element (starting from 0). Tail-recursive
      @since Nitrogen-20111001 *)

val mapi: (int -> 'a -> 'b) -> 'a list -> 'b list
  (** Same as map, but the function to be applied take also as argument the
      index of the element (starting from 0). Tail-recursive
      @since Oxygen-20120901 *)

val sort_unique: ('a -> 'a -> int) -> 'a list -> 'a list
163
164
165
  (**  Same as List.sort , but also remove duplicates.
       @deprecated use List.sort_uniq instead
  *)
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

val subsets: int -> 'a list -> 'a list list
  (** [subsets k l] computes the combinations of [k] elements from list [l].
      E.g. subsets 2 [1;2;3;4] = [[1;2];[1;3];[1;4];[2;3];[2;4];[3;4]].
      This function preserves the order of the elements in [l] when
      computing the sublists. [l] should not contain duplicates.
      @since Aluminium-20160501 *)

val list_first_n : int -> 'a list -> 'a list
(** [list_first_n n l] returns the first [n] elements of the list. Tail
    recursive.
    It returns an empty list if [n] is nonpositive and the whole list if [n] is
    greater than [List.length l].
    It is equivalent to [list_slice ~last:n l]. *)

val list_slice: ?first:int -> ?last:int -> 'a list -> 'a list
(** [list_slice ?first ?last l] is equivalent to Python's slice operator
    (l[first:last]): returns the range of the list between [first] (inclusive)
    and [last] (exclusive), starting from 0.
    If omitted, [first] defaults to 0 and [last] to [List.length l].
    Negative indices are allowed, and count from the end of the list.
    [list_slice] never raises exceptions: out-of-bounds arguments are clipped,
    and inverted ranges result in empty lists.
    @since 18.0-Argon *)

(* ************************************************************************* *)
(** {2 Arrays} *)
(* ************************************************************************* *)

val array_exists: ('a -> bool) -> 'a array -> bool
val array_existsi: (int -> 'a -> bool) -> 'a array -> bool

(* ************************************************************************* *)
(** {2 Options} *)
(* ************************************************************************* *)

(** [true] iff its argument is [Some x] 
    @since Nitrogen-20111001 *)
val has_some: 'a option -> bool

val may: ('a -> unit) -> 'a option -> unit
  (** [may f v] applies [f] to [x] if [v = Some(x)] *)

val opt_conv: 'a -> 'a option -> 'a
  (** [opt_conv default v] returns [default] if [v] is [None] and [a] if
      [v] is [Some a] *)

val opt_if: bool -> 'a -> 'a option
(** [opt_if cond v] returns [Some v] if [cond] is [true] and
    [None] otherwise *)

val may_map: ('a -> 'b) -> ?dft:'b -> 'a option -> 'b
  (** [may_map f ?dft x] applies [f] to the value of [x] if exists. Otherwise
      returns the default value [dft].
      Assume that either [x] or [dft] is defined. *)

val opt_map: ('a -> 'b) -> 'a option -> 'b option

val opt_fold: ('a -> 'b -> 'b) -> 'a option -> 'b -> 'b
(** @since Oxygen-20120901 *)

(** [merge f k a b]  returns
    - [None] if both [a] and [b] are [None]
    - [Some a'] (resp. [b'] if [b] (resp [a]) is [None] 
      and [a] (resp. [b]) is [Some]
    - [f k a' b'] if both [a] and [b] are [Some]
    
    It is mainly intended to be used with Map.merge
    
    @since Oxygen-20120901
*)
val merge_opt:
  ('a -> 'b -> 'b -> 'b) -> 'a -> 'b option -> 'b option -> 'b option

(** [opt_bind f x] returns [None] if [x] is [None] and [f y] if is [Some y]
    (monadic bind)
    @since Nitrogen-20111001
*)
val opt_bind: ('a -> 'b option) -> 'a option -> 'b option

val opt_filter: ('a -> bool) -> 'a option -> 'a option

val the: ?exn:exn -> 'a option -> 'a
(** @raise Exn if the value is [None] and [exn] is specified.
    @raise Invalid_argument if the value is [None] and [exn] is not specified.
    @return v if the value is [Some v].
    @modify Magnesium-20151001 add optional argument [exn]
    @plugin development guide *)

val find_or_none: ('a -> 'b) -> 'a -> 'b option

val opt_equal : ('a -> 'a -> bool) -> 'a option -> 'a option -> bool

val opt_compare : ('a -> 'a -> int) -> 'a option -> 'a option -> int
  (** @since Boron-20100401 *)

val opt_hash: ('a -> int) -> 'a option -> int
  (** @since Sodium-20150201 *)

(* ************************************************************************* *)
(** {2 Booleans} *)
(* ************************************************************************* *)

val xor: bool -> bool -> bool
(** exclusive-or. @since Oxygen-20120901 *)

(* ************************************************************************* *)
(** {2 Strings} *)
(* ************************************************************************* *)

val string_prefix: ?strict:bool -> string -> string -> bool
  (** [string_prefix ~strict p s] returns [true] if and only if [p] is a
      prefix of the string [s]. If [strict] is true, the prefix must be strict
      (that is, [s] must moreover be strictly longer than [p]. [strict]
      is false by default.
      @since Boron-20100401 *)

val string_del_prefix: ?strict:bool -> string -> string -> string option
  (** [string_del_prefix ~strict p s] returns [None] if [p] is not a prefix of
      [s] and Some [s1] iff [s=p^s1].
      @since Oxygen-20120901 *)

val string_suffix: ?strict:bool -> string -> string -> bool
  (** [string_suffix ~strict suf s] returns [true] iff [suf] is a suffix of
      string [s]. [strict], which defaults to [false], indicates whether [s]
      should be strictly longer than [p].
      @since Aluminium-20160501
  *)

val string_del_suffix: ?strict:bool -> string -> string -> string option
  (** [string_del_suffix ~strict suf s] returns [Some s1] when [s = s1 ^ suf]
      and None of [suf] is not a suffix of [s].
      @since Aluminium-20160501
  *)

val string_split: string -> int -> string * string
(** [string_split s i] returns the beginning of [s] up to char [i-1] and the 
    end of [s] starting from char [i+1]
    @raise Invalid_argument if [i] is not in the range [[0,(length s -1)]]
    @since Oxygen-20120901 *)

val make_unique_name: 
  (string -> bool) -> ?sep:string -> ?start:int -> string -> int*string
  (** [make_unique_name mem s] returns [(0, s)] when [(mem s)=false]
      otherwise returns [(n,new_string)] such that [new_string] is 
      derived from [(s,sep,start)] and [(mem new_string)=false] and [n<>0] 
      @since Oxygen-20120901 *)

val strip_underscore: string -> string
(** remove underscores at the beginning and end of a string. If a string
    is composed solely of underscores, return the empty string

    @since 18.0-Argon
  *)

val html_escape: string -> string

323
324
325
(** [format_string_of_stag stag] returns the string corresponding to [stag],
    or raises an exception if the tag extension is unsupported.

326
    @since 22.0-Titanium
327
328
329
 *)
val format_string_of_stag: Format.stag -> string

330
331
332
333
(* ************************************************************************* *)
(** {2 Performance} *)
(* ************************************************************************* *)

334
external address_of_value: 'a -> int = "address_of_value" [@@noalloc]
335
336
337
338
339
340
341
342
343
344
345

(* ************************************************************************* *)
(** {2 Exception catcher} *)
(* ************************************************************************* *)

val try_finally: finally:(unit -> unit) -> ('a -> 'b) -> 'a -> 'b

(* ************************************************************************* *)
(** System commands *)
(* ************************************************************************* *)

346
347
348
349
350
351
352
353
val mkdir : ?parents:bool -> string -> Unix.file_perm -> unit
  (** [mkdir ?parents name perm] creates directory [name] with permission
      [perm]. If [parents] is true, recursively create parent directories
      if needed. [parents] defaults to false.
      Note that this function may create some of the parent directories
      and then fail to create the children, e.g. if [perm] does not allow
      user execution of the created directory. This will leave the filesystem
      in a modified state before raising an exception.
Loïc Correnson's avatar
Loïc Correnson committed
354
      @raise Unix.Unix_error if cannot create [name] or its parents.
355
      @since 19.0-Potassium  *)
356

357
val safe_at_exit : (unit -> unit) -> unit
358
  (** Register function to call with [Stdlib.at_exit], but only
359
      for non-child process (fork). The order of execution is preserved 
360
      {i wrt} ordinary calls to [Stdlib.at_exit]. *)
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

val cleanup_at_exit: string -> unit
  (** [cleanup_at_exit file] indicates that [file] must be removed when the
      program exits (except if exit is caused by a signal).
      If [file] does not exist, nothing happens. *)

exception Temp_file_error of string

val temp_file_cleanup_at_exit: ?debug:bool -> string -> string -> string
  (** Similar to [Filename.temp_file] except that the temporary file will be
      deleted at the end of the execution (see above), unless [debug] is set
      to true, in which case a message with the name of the kept file will be
      printed.
      @raise Temp_file_error if the temp file cannot be created.
      @modify Nitrogen-20111001 may now raise Temp_file_error
      @modify Oxygen-20120901 optional debug argument
*)

val temp_dir_cleanup_at_exit: ?debug:bool -> string -> string
(** @raise Temp_file_error if the temp dir cannot be created.
    @modify Nitrogen-20111001 may now raise Temp_file_error
    @modify Neon-20130301 add optional debug flag *)

val safe_remove: string -> unit
  (** Tries to delete a file and never fails. *)

val safe_remove_dir: string -> unit

(* ************************************************************************* *)
(** Comparison functions *)
(* ************************************************************************* *)

393
(** Use this function instead of [Stdlib.compare], as this makes
394
395
396
397
398
399
400
401
402
403
404
405
    it easier to find incorrect uses of the latter *)
external compare_basic: 'a -> 'a -> int = "%compare"

(** Case-insensitive string comparison. Only ISO-8859-1 accents are handled.
    @since Silicon-20161101 *)
val compare_ignore_case: string -> string -> int

(*
Local Variables:
compile-command: "make -C ../../.."
End:
*)