-
Thomas Wood authored
ml2js wasn't including . in the include paths by default. Add flag for explicitly indicating stdlib location.
Thomas Wood authoredml2js wasn't including . in the include paths by default. Add flag for explicitly indicating stdlib location.
mytools.ml 5.76 KiB
(** This file contains some helper functions *)
(**************************************************************)
(** Option manipulation functions *)
let option_map f = function
| None -> None
| Some x -> Some (f x)
let option_iter f = function
| None -> ()
| Some x -> f x
let unsome = function
| None -> assert false
| Some v -> v
let option_to_list = function (* todo: rename as [list_of_option] *)
| None -> []
| Some v -> [v]
let option_app d f = function
| None -> d
| Some x -> f x
let unsome_safe d = function
| None -> d
| Some s -> s
let bool_of_option xo =
match xo with
| None -> false
| Some x -> x
(**************************************************************)
(** List manipulation functions *)
let rec list_make n v =
if n = 0 then [] else v::(list_make (n-1) v)
let list_mapi f l =
let rec aux i = function
| [] -> []
| h::t -> (f i h)::(aux (i+1) t)
in
aux 0 l
let range i j =
let rec aux j acc =
if i <= j then aux (j - 1) (j :: acc) else acc in
aux j []
let list_nat n = (* for n >= 0 *)
range 0 n
let rec list_separ sep = function
| [] -> []
| a :: [] -> a :: []
| a :: l -> a :: sep :: list_separ sep l
let rec filter_somes = function
| [] -> []
| None :: l -> filter_somes l
| (Some x) :: l -> x :: filter_somes l
let list_unique l =
let rec aux acc = function
| [] -> acc
| a :: q ->
if List.mem a acc then aux acc q else aux (a :: acc) q
in
aux [] l
let list_intersect l1 l2 =
List.filter (fun x -> List.mem x l1) l2
let list_minus l1 l2 =
List.filter (fun t -> not (List.mem t l2)) l1
let list_concat_map f l =
List.concat (List.map f l)
let list_assoc_option x l =
try Some (List.assoc x l)
with Not_found -> None
let rec assoc_list_map f = function
| [] -> []
| (k,v)::l -> (k, f v)::(assoc_list_map f l)
let rec list_remove i l = (* i >= 0 *)
match l with
| [] -> failwith "list_remove invalid index" (* todo: illegal argument *)
| x::t -> if i = 0 then t else x::(list_remove (i-1) t)
let rec list_replace i v l = (* i >= 0 *)
match l with
| [] -> failwith "list_replace invalid index" (* todo: illegal argument *)
| x::t -> if i = 0 then v::t else x::(list_replace (i-1) v t)
let list_replace_nth i vs xs =
list_replace i (List.nth vs i) xs
let list_ksort cmp l =
List.sort (fun (k1,_) (k2,_) -> cmp k1 k2) l
let list_index k l =
let rec aux n = function
| [] -> raise Not_found
| x::l -> if x = k then n else aux (n+1) l
in
aux 0 l
let list_split3 l =
let l1 = List.map (fun (x,_,_) -> x) l in
let l2 = List.map (fun (_,x,_) -> x) l in
let l3 = List.map (fun (_,_,x) -> x) l in
(l1,l2,l3)
let add_to_list li s =
li := s :: !li
(**************************************************************)
(** String manipulation functions *)
let str_cmp (s1 : string) (s2 : string) =
if s1 < s2 then -1 else if s1 = s2 then 0 else 1
let str_starts_with p s =
let n = String.length p in
String.length s >= n
&& String.sub s 0 n = p
let str_replace char1 char2 s =
let s2 = String.copy s in
for i = 0 to pred (String.length s) do
if s2.[i] = char1 then s2.[i] <- char2;
done;
s2
let cutlines width s =
let len = String.length s in
let b = Buffer.create len in
let i_last = ref 0 in
let i = ref 0 in
while !i < len do
i := min (!i + width) len;
while !i < len && (s.[!i]) <> ' ' do
incr i
done;
let line = String.sub s !i_last (!i - !i_last) in
Buffer.add_string b line;
Buffer.add_char b '\n';
incr i;
i_last := !i;
done;
Buffer.contents b
let make_upper s =
if String.length s <= 0 then s else
let s' = String.copy s in
s'.[0] <- Char.uppercase s.[0];
s'
let make_upper_2 s =
if String.length s < 2 then s else
let s' = String.copy s in
s'.[1] <- Char.uppercase s.[1];
s'
(**************************************************************)
(** File manipulation functions *)
let file_put_contents filename text =
try
let handle = open_out filename in
output_string handle text;
close_out handle
with Sys_error s ->
failwith ("Could not write in file: " ^ filename ^ "\n" ^ s)
let output_endline outchannel str =
output_string outchannel str; output_char outchannel '\n'
(**************************************************************)
(** Try-with manipulation functions *)
(** Tests whether a function throws [Not_found] *)
let gives_not_found f =
try ignore (f()); false
with Not_found -> true
(**************************************************************)
(** Pretty-printing functions *)
let lin0 = ""
let lin1 = "\n"
let lin2 = "\n\n"
let show_list s sep l =
String.concat sep (List.map s l)
let show_listp s sep l =
if l = [] then "" else
sep ^ (String.concat sep (List.map s l))
let show_listq s sep l =
if l = [] then "" else
(String.concat sep (List.map s l)) ^ sep
let show_option f ox =
match ox with
| None -> ""
| Some x -> f x
let show_str s =
s
let show_par required s =
if required then "(" ^ s ^ ")" else s
(**************************************************************)
(** Error messages *)
let output s =
Printf.printf "%s\n" s
let warning s =
Printf.printf "### WARNING: %s\n" s
open Format
let unsupported ?loc s =
option_iter (Location.print_error err_formatter) loc;
failwith ("Unsupported language construction: " ^ s ^ ".")
let out_of_scope loc s =
Location.print_error err_formatter loc;
failwith (s ^ " are and will not be supported.")
let error ?loc s =
option_iter (Location.print_error err_formatter) loc;
failwith ("Error: " ^ s ^ ".")
let warning ?loc s =
option_iter (Location.print_loc err_formatter) loc;
Printf.printf "%s\n" ("Warning: " ^ s ^ ".")