summaryrefslogtreecommitdiff
path: root/libs/util.ml
blob: 01b0c5c7276b1e254282827099bf9bc3699bac4c (plain) (blame)
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
(* Either type *)

type ('a, 'b) either =
  | Left of 'a
  | Right of 'b


(* Locations *)

type position = Lexing.position
let position_unknown = Lexing.dummy_pos

type extent = position * position
let extent_unknown = (position_unknown, position_unknown)


(* Exceptions *)

exception NoLocError of string
let error x = raise (NoLocError x)

exception LocError of extent list * string
let loc_error l f x =
  try f x with
  | NoLocError e -> raise (LocError([l], e))
  | LocError(q, e) -> raise (LocError(l::q, e))

let not_implemented e = error ("Not implemented: " ^ e)

(* Varmaps *)

module VarMap = Mapext.Make(String)
let disjoint_union k a b = match a, b with
  | Some x, None -> Some x
  | None, Some y -> Some y 
  | _ -> error ("Duplicate name in disjoint union: " ^ k)

module SSet = Set.Make(String)

(* Fixpoint *)

let rec fix equal f s =
  let fs = f s in
  if equal fs s
    then fs
    else fix equal f fs

let (@@) f x = f x

let print_list x l =
  Format.printf "%s: " x;
  let rec aux = function
    | [] -> ()
    | [a] -> Format.printf "%s" a
    | p::q -> Format.printf "%s, " p; aux q
  in
  Format.printf "["; aux l; Format.printf "]@."

let uid =
  let c = ref 0 in
  fun () -> c := !c + 1; string_of_int !c

(* On lists *)

(* list_fold_op : ('a -> 'a -> 'a) -> 'a list -> 'a *)
let rec list_fold_op op = function
  | [] -> invalid_arg "list_fold_opt on empty list"
  | [a] -> a
  | x::q -> op x (list_fold_op op q)