2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
12 (** Callstack is simply a typed way to indicate that a string is a callstack *)
13 type callstack
= Callstack
of string
15 let () = Random.self_init
()
17 let profile = ref false
19 let log = ref (fun (_
: string) -> ())
36 module Map
= struct end
38 let spf = Printf.sprintf
39 let print_endlinef fmt
= Printf.ksprintf print_endline fmt
40 let prerr_endlinef fmt
= Printf.ksprintf prerr_endline fmt
42 let opt f env
= function
44 | Some x
-> let env, x
= f
env x
in env, Some x
46 let opt_fold f
env = function
50 let singleton_if cond x
= if cond
then [x
] else []
52 let smap_inter m1 m2
=
60 let imap_inter m1 m2
=
68 let smap_inter_list = function
71 List.fold_left rl ~f
:smap_inter ~init
:x
73 let imap_inter_list = function
76 List.fold_left rl ~f
:imap_inter ~init
:x
78 let rec wfold_left2 f
env l1 l2
=
80 | [], _
| _
, [] -> env
81 | x1
:: rl1
, x2
:: rl2
->
82 let env = f
env x1 x2
in
83 wfold_left2 f
env rl1 rl2
86 List.fold_right l ~f
:(^
) ~init
:""
88 let maybe f
env = function
92 (* Since OCaml usually runs w/o backtraces enabled, the note makes errors
94 let unsafe_opt_note note
= function
95 | None
-> raise
(Invalid_argument note
)
98 let unsafe_opt x
= unsafe_opt_note "unsafe_opt got None" x
100 let inter_list = function
103 List.fold_left rl ~f
:SSet.inter ~init
:x
105 let rec list_last f1 f2
=
109 | x
:: rl
-> f1 x
; list_last f1 f2 rl
111 let is_prefix_dir dir fn
=
112 let prefix = dir ^
Filename.dir_sep
in
113 String.length fn
> String.length
prefix &&
114 String.sub fn
0 (String.length
prefix) = prefix
116 let try_with_channel (oc
: out_channel
) (f1
: out_channel
-> 'a
) (f2
: exn
-> 'a
) : 'a
=
118 let result = f1 oc
in
125 let try_with_stack (f
: unit -> 'a
) : ('a
, exn
* callstack
) result =
129 let stack = Callstack
(Printexc.get_backtrace
()) in
133 let iter_n_acc n f acc
=
140 let map_of_list list
=
141 List.fold_left ~f
:(fun m
(k
, v
) -> SMap.add k v m
) ~init
:SMap.empty list
144 List.fold_right l ~f
:SSet.add ~init
:SSet.empty
146 (* \A\B\C -> A\B\C *)
148 if String.length s
== 0 || s
.[0] <> '
\\'
then s
149 else String.sub s
1 ((String.length s
) - 1)
151 (* A\B\C -> \A\B\C *)
153 if String.length s
= 0 || s
.[0] <> '
\\'
160 let base_name_start = String.rindex s '
\\'
+ 1 in
161 String.sub s
base_name_start ((String.length s
) - base_name_start)
164 (* "\\A\\B\\C" -> ("\\A\\B\\" * "C") *)
165 let split_ns_from_name (s
: string): (string * string) =
167 let base_name_start = (String.rindex s '
\\'
) + 1 in
168 let name_part = String.sub s
170 ((String.length s
) - base_name_start) in
171 let namespace_part = String.sub s
0 base_name_start in
172 (namespace_part, name_part)
173 with Not_found
-> ("\\", s
)
175 (*****************************************************************************)
176 (* Same as List.iter2, except that we only iterate as far as the shortest
179 (*****************************************************************************)
181 let rec iter2_shortest f l1 l2
=
183 | [], _
| _
, [] -> ()
184 | x1
:: rl1
, x2
:: rl2
-> f x1 x2
; iter2_shortest f rl1 rl2
186 let fold_fun_list acc fl
=
187 List.fold_left fl ~f
:(|>) ~init
:acc
189 let compose f g x
= f
(g x
)
191 module With_complete_flag
= struct
198 let try_finally ~f ~
(finally
: unit -> unit) =
199 let res = try f
() with e
-> finally
(); raise e
in
203 let with_context ~enter ~exit ~do_
=
205 let result = try do_
() with e
->
206 let stack = Printexc.get_raw_backtrace
() in
208 Printexc.raise_with_backtrace e
stack in
212 (* We run with exception backtraces turned off for performance reasons. But for
213 * some kinds of catastrophic exceptions, which we never recover from (so the
214 * performance doesn't matter) we do want the backtrace. "assert false" is one
215 * of such conditions.
217 let assert_false_log_backtrace msg
=
218 Printf.eprintf
"assert false with backtrace:\n";
219 Option.iter msg ~f
:(Printf.eprintf
"%s\n");
220 Printf.eprintf
"%s" (Printexc.raw_backtrace_to_string
221 (Printexc.get_callstack
100));
224 (* Returns the largest element in arr strictly less than `bound` *)
225 let infimum (arr
: 'a array
)
227 (compare
: 'a
-> 'b
-> int) : int option =
228 let rec binary_search low high
= begin
231 else if low
> high
then
234 let mid = (low
+ high
+ 1) / 2 in
235 let test = Array.get arr
mid in
236 if compare
test bound
< 0 then
237 binary_search mid high
239 binary_search low
(mid - 1)
242 binary_search 0 ((Array.length arr
) - 1)
244 let unwrap_snd (a
, b_opt
) =
247 | Some b
-> Some
(a
, b
)