(*
 * Copyright (C) 2012 Batteries Included Development Team
 *
 * This library is free software; 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; either
 * version 2.1 of the License, or (at your option) any later version,
 * with the special exception on linking described in file LICENSE.
 *
 * This library 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)

(* Inner functions for Pervasives, that can be accessed from other
   modules without pulling in all of batteries as deps. *)

let finally handler f x =
  let r = (
    try
      f x
    with
      e -> handler(); raise e
  ) in
  handler();
  r

let with_dispose ~dispose f x =
  finally (fun () -> dispose x) f x

(* unique int generation *)
let unique_value  = ref 0
let lock          = ref BatConcurrent.nolock
let unique ()     =
  BatConcurrent.sync !lock BatRef.post_incr unique_value

(*$Q unique
   Q.unit (fun () -> unique () <> unique ())
*)

type ('a, 'b) result =
##V>=4.8## ('a, 'b) Stdlib.result =
  | Ok  of 'a
  | Error of 'b

(* Ideas taken from Nicholas Pouillard's my_std.ml in ocamlbuild/ *)
let ignore_ok = function
    Ok _ -> ()
  | Error ex -> raise ex

let ok = function
    Ok v -> v
  | Error ex -> raise ex

let wrap f x = try Ok (f x) with ex -> Error ex

let forever f x = ignore (while true do ignore (f x) done)

let ignore_exceptions f x = try ignore (f x) with _ -> ()


  (** {1 Operators}*)

##V<4## let ( |> ) x f = f x
##V>=4## external (|>) : 'a -> ('a -> 'b) -> 'b = "%revapply"

##V<4## let ( @@ ) f x = f x
##V>=4## external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply"

let ( %> ) f g x = g (f x)

let ( % ) f g x = f (g x)

let flip f x y = f y x

let curry f x y = f (x,y)

let uncurry f (x,y) = f x y

let const x _ = x

let neg p x = not (p x)

let neg2 p x y = not (p x y)

external identity : 'a -> 'a = "%identity"

let tap f x = f x; x

let ( |? ) = BatOption.Infix.( |? )
