summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/initial_check.ml7
-rw-r--r--src/initial_check.mli14
-rw-r--r--src/pp.ml76
-rw-r--r--src/pp.mli54
-rw-r--r--src/process_file.ml5
-rw-r--r--src/process_file.mli1
-rw-r--r--src/type_internal.ml57
-rw-r--r--src/type_internal.mli52
-rw-r--r--src/util.ml259
-rw-r--r--src/util.mli193
10 files changed, 717 insertions, 1 deletions
diff --git a/src/initial_check.ml b/src/initial_check.ml
new file mode 100644
index 00000000..8f474f26
--- /dev/null
+++ b/src/initial_check.ml
@@ -0,0 +1,7 @@
+open Type_internal
+open Ast
+
+type 'a envs = 'a * Nameset.t * kind Kindmap.t * t Typmap.t
+
+let rec to_ast (bound_names : Nameset.t) (kind_env : kind Kindmap.t) (typ_env : t Typmap.t) partial_defs defs =
+ (Defs [])
diff --git a/src/initial_check.mli b/src/initial_check.mli
new file mode 100644
index 00000000..39b955b5
--- /dev/null
+++ b/src/initial_check.mli
@@ -0,0 +1,14 @@
+
+open Type_internal
+open Ast
+
+type 'a envs = 'a * Nameset.t * kind Kindmap.t * t Typmap.t
+
+val to_ast : Nameset.t -> kind Kindmap.t -> t Typmap.t -> tannot def list -> Parse_ast.defs -> tannot defs
+(*val to_ast_def : nameset -> kind kindmap -> t typmap -> tannot def list -> Parse_ast.defs -> (annot def) envs * annot def list
+val to_ast_fun : nameset -> kind kindmap -> t typmap -> Parse_ast.fundef -> (annot fundef) envs
+val to_ast_expr : nameset -> kind kindmap -> t typmap -> Parse_ast.exp -> (annot exp) envs
+val to_ast_targ : nameset -> kind kindmap -> t typmap -> Parse_ast.atyp -> (annot typ_arg) envs
+val to_ast_typ : nameset -> kind kindmap -> t typmap -> Parse_ast.atyp -> (annot typ) envs
+val to_ast_nexp : nameset -> kind kindmap -> t typmap -> Parse_ast.atyp -> (annot nexp) envs
+*)
diff --git a/src/pp.ml b/src/pp.ml
new file mode 100644
index 00000000..0fa8636a
--- /dev/null
+++ b/src/pp.ml
@@ -0,0 +1,76 @@
+(**************************************************************************)
+(* Lem *)
+(* *)
+(* Dominic Mulligan, University of Cambridge *)
+(* Francesco Zappa Nardelli, INRIA Paris-Rocquencourt *)
+(* Gabriel Kerneis, University of Cambridge *)
+(* Kathy Gray, University of Cambridge *)
+(* Peter Boehm, University of Cambridge (while working on Lem) *)
+(* Peter Sewell, University of Cambridge *)
+(* Scott Owens, University of Kent *)
+(* Thomas Tuerk, University of Cambridge *)
+(* *)
+(* The Lem sources are copyright 2010-2013 *)
+(* by the UK authors above and Institut National de Recherche en *)
+(* Informatique et en Automatique (INRIA). *)
+(* *)
+(* All files except ocaml-lib/pmap.{ml,mli} and ocaml-libpset.{ml,mli} *)
+(* are distributed under the license below. The former are distributed *)
+(* under the LGPLv2, as in the LICENSE file. *)
+(* *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in the *)
+(* documentation and/or other materials provided with the distribution. *)
+(* 3. The names of the authors may not be used to endorse or promote *)
+(* products derived from this software without specific prior written *)
+(* permission. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS *)
+(* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *)
+(* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *)
+(* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY *)
+(* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *)
+(* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE *)
+(* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *)
+(* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER *)
+(* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR *)
+(* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN *)
+(* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *)
+(**************************************************************************)
+
+(** pretty printing utilities *)
+
+open Format
+
+let pp_str ppf s =
+ fprintf ppf "%s" s
+
+let rec lst sep f ppf = function
+ | [] -> ()
+ | [x] ->
+ fprintf ppf "%a"
+ f x
+ | (h::t) ->
+ f ppf h;
+ fprintf ppf sep;
+ lst sep f ppf t
+
+let opt f ppf = function
+ | None ->
+ fprintf ppf "None"
+ | Some(x) ->
+ fprintf ppf "Some(%a)"
+ f x
+
+let pp_to_string pp =
+ let b = Buffer.create 16 in
+ let f = formatter_of_buffer b in
+ pp f;
+ pp_print_flush f ();
+ Buffer.contents b
diff --git a/src/pp.mli b/src/pp.mli
new file mode 100644
index 00000000..2c7d6777
--- /dev/null
+++ b/src/pp.mli
@@ -0,0 +1,54 @@
+(**************************************************************************)
+(* Lem *)
+(* *)
+(* Dominic Mulligan, University of Cambridge *)
+(* Francesco Zappa Nardelli, INRIA Paris-Rocquencourt *)
+(* Gabriel Kerneis, University of Cambridge *)
+(* Kathy Gray, University of Cambridge *)
+(* Peter Boehm, University of Cambridge (while working on Lem) *)
+(* Peter Sewell, University of Cambridge *)
+(* Scott Owens, University of Kent *)
+(* Thomas Tuerk, University of Cambridge *)
+(* *)
+(* The Lem sources are copyright 2010-2013 *)
+(* by the UK authors above and Institut National de Recherche en *)
+(* Informatique et en Automatique (INRIA). *)
+(* *)
+(* All files except ocaml-lib/pmap.{ml,mli} and ocaml-libpset.{ml,mli} *)
+(* are distributed under the license below. The former are distributed *)
+(* under the LGPLv2, as in the LICENSE file. *)
+(* *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in the *)
+(* documentation and/or other materials provided with the distribution. *)
+(* 3. The names of the authors may not be used to endorse or promote *)
+(* products derived from this software without specific prior written *)
+(* permission. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS *)
+(* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *)
+(* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *)
+(* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY *)
+(* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *)
+(* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE *)
+(* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *)
+(* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER *)
+(* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR *)
+(* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN *)
+(* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *)
+(**************************************************************************)
+
+open Format
+val pp_str : formatter -> string -> unit
+
+val lst : ('a, formatter, unit) format -> (formatter -> 'b -> unit) -> formatter -> 'b list -> unit
+
+val opt : (formatter -> 'a -> unit) -> formatter -> 'a option -> unit
+
+val pp_to_string : (formatter -> 'a) -> string
diff --git a/src/process_file.ml b/src/process_file.ml
index 4284a252..8c996c14 100644
--- a/src/process_file.ml
+++ b/src/process_file.ml
@@ -44,7 +44,7 @@
(* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *)
(**************************************************************************)
-(* XXX: for debugging the developing code: open Coq_ast *)
+open Type_internal
(* let r = Ulib.Text.of_latin1 *)
@@ -69,6 +69,9 @@ let parse_file (f : string) : Parse_ast.defs =
| Lexer.LexError(s,p) ->
raise (Reporting_basic.Fatal_error (Reporting_basic.Err_lex (p, s)))
+let convert_ast (defs : Parse_ast.defs) : Type_internal.tannot Ast.defs =
+ Initial_check.to_ast Nameset.empty Kindmap.empty Typmap.empty [] defs
+
(* type instances = Types.instance list Types.Pfmap.t
let check_ast (ts : Typed_ast.Targetset.t) (mod_path : Name.t list)
diff --git a/src/process_file.mli b/src/process_file.mli
index 1622d902..f01aa251 100644
--- a/src/process_file.mli
+++ b/src/process_file.mli
@@ -47,6 +47,7 @@
(* open Typed_ast *)
val parse_file : string -> Parse_ast.defs
+val convert_ast : Parse_ast.defs -> Type_internal.tannot Ast.defs
(* type instances = Types.instance list Types.Pfmap.t
diff --git a/src/type_internal.ml b/src/type_internal.ml
new file mode 100644
index 00000000..8b68934e
--- /dev/null
+++ b/src/type_internal.ml
@@ -0,0 +1,57 @@
+module Kindmap = Finite_map.Fmap_map(String)
+module Nameset' = Set.Make(String)
+module Nameset = struct
+ include Nameset'
+ let pp ppf nameset =
+ Format.fprintf ppf "{@[%a@]}"
+ (Pp.lst ",@ " Pp.pp_str)
+ (Nameset'.elements nameset)
+end
+
+module Typmap = Finite_map.Fmap_map(String)
+
+type t = { mutable t : t_aux }
+and t_aux =
+ | Tvar of string
+ | Tfn of t * t * effect
+ | Ttup of t list
+ | Tapp of string * t_arg list
+ | Tuvar of t_uvar
+and t_uvar = { index : int; mutable subst : t option }
+and nexp = { mutable nexp : nexp_aux }
+and nexp_aux =
+ | Nvar of string
+ | Nconst of int
+ | Nadd of nexp * nexp
+ | Nmult of nexp * nexp
+ | N2n of nexp
+ | Nneg of nexp (* Unary minus for representing new vector sizes after vector slicing *)
+ | Nuvar of n_uvar
+and n_uvar = { nindex : int; mutable nsubst : t option }
+and effect = { mutable effect : effect_aux }
+and effect_aux =
+ | Evar of string
+ | Eset of Ast.efct_aux list
+ | Euvar of e_uvar
+and e_uvar = { eindex : int; mutable esubst : t option }
+and order = { mutable order : order_aux }
+and order_aux =
+ | Ovar of string
+ | Oinc
+ | Odec
+ | Ouvar of o_uvar
+and o_uvar = { oindex : int; mutable osubst : t option }
+and t_arg =
+ | TA_typ of t
+ | TA_nexp of nexp
+ | TA_eft of effect
+ | TA_ord of order
+
+(* Constraints for nexps, plus the location which added the constraint, each nexp is either <= 0 = 0 or >= 0 *)
+type nexp_range =
+ | LtEq of Parse_ast.l * nexp
+ | Eq of Parse_ast.l * nexp
+ | GtEq of Parse_ast.l * nexp
+ | In of Parse_ast.l * nexp * nexp list
+
+type tannot = (t * nexp_range list) option
diff --git a/src/type_internal.mli b/src/type_internal.mli
new file mode 100644
index 00000000..cfa12a75
--- /dev/null
+++ b/src/type_internal.mli
@@ -0,0 +1,52 @@
+module Kindmap : Finite_map.Fmap with type k = string
+module Typmap : Finite_map.Fmap with type k = string
+module Nameset : sig
+ include Set.S with type elt = string
+ val pp : Format.formatter -> t -> unit
+end
+
+type t_uvar
+type n_uvar
+type e_uvar
+type o_uvar
+type t = { mutable t : t_aux }
+and t_aux =
+ | Tvar of string
+ | Tfn of t * t * effect
+ | Ttup of t list
+ | Tapp of string * t_arg list
+ | Tuvar of t_uvar
+and nexp = { mutable nexp : nexp_aux }
+and nexp_aux =
+ | Nvar of string
+ | Nconst of int
+ | Nadd of nexp * nexp
+ | Nmult of nexp * nexp
+ | N2n of nexp
+ | Nneg of nexp (* Unary minus for representing new vector sizes after vector slicing *)
+ | Nuvar of n_uvar
+and effect = { mutable effect : effect_aux }
+and effect_aux =
+ | Evar of string
+ | Eset of Ast.efct_aux list
+ | Euvar of e_uvar
+and order = { mutable order : order_aux }
+and order_aux =
+ | Ovar of string
+ | Oinc
+ | Odec
+ | Ouvar of o_uvar
+and t_arg =
+ | TA_typ of t
+ | TA_nexp of nexp
+ | TA_eft of effect
+ | TA_ord of order
+
+(* Constraints for nexps, plus the location which added the constraint, each nexp is either <= 0 = 0 or >= 0 *)
+type nexp_range =
+ | LtEq of Parse_ast.l * nexp
+ | Eq of Parse_ast.l * nexp
+ | GtEq of Parse_ast.l * nexp
+ | In of Parse_ast.l * nexp * nexp list
+
+type tannot = (t * nexp_range list) option
diff --git a/src/util.ml b/src/util.ml
new file mode 100644
index 00000000..28b56f22
--- /dev/null
+++ b/src/util.ml
@@ -0,0 +1,259 @@
+(**************************************************************************)
+(* Lem *)
+(* *)
+(* Dominic Mulligan, University of Cambridge *)
+(* Francesco Zappa Nardelli, INRIA Paris-Rocquencourt *)
+(* Gabriel Kerneis, University of Cambridge *)
+(* Kathy Gray, University of Cambridge *)
+(* Peter Boehm, University of Cambridge (while working on Lem) *)
+(* Peter Sewell, University of Cambridge *)
+(* Scott Owens, University of Kent *)
+(* Thomas Tuerk, University of Cambridge *)
+(* *)
+(* The Lem sources are copyright 2010-2013 *)
+(* by the UK authors above and Institut National de Recherche en *)
+(* Informatique et en Automatique (INRIA). *)
+(* *)
+(* All files except ocaml-lib/pmap.{ml,mli} and ocaml-libpset.{ml,mli} *)
+(* are distributed under the license below. The former are distributed *)
+(* under the LGPLv2, as in the LICENSE file. *)
+(* *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in the *)
+(* documentation and/or other materials provided with the distribution. *)
+(* 3. The names of the authors may not be used to endorse or promote *)
+(* products derived from this software without specific prior written *)
+(* permission. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS *)
+(* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *)
+(* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *)
+(* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY *)
+(* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *)
+(* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE *)
+(* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *)
+(* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER *)
+(* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR *)
+(* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN *)
+(* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *)
+(**************************************************************************)
+
+module Duplicate(S : Set.S) = struct
+
+type dups =
+ | No_dups of S.t
+ | Has_dups of S.elt
+
+let duplicates (x : S.elt list) : dups =
+ let rec f x acc = match x with
+ | [] -> No_dups(acc)
+ | s::rest ->
+ if S.mem s acc then
+ Has_dups(s)
+ else
+ f rest (S.add s acc)
+ in
+ f x S.empty
+end
+
+let remove_duplicates l =
+ let l' = List.sort Pervasives.compare l in
+ let rec aux acc l = match (acc, l) with
+ (_, []) -> List.rev acc
+ | ([], x :: xs) -> aux [x] xs
+ | (y::ys, x :: xs) -> if (x = y) then aux (y::ys) xs else aux (x::y::ys) xs
+ in
+ aux [] l'
+
+let rec compare_list f l1 l2 =
+ match (l1,l2) with
+ | ([],[]) -> 0
+ | (_,[]) -> 1
+ | ([],_) -> -1
+ | (x::l1,y::l2) ->
+ let c = f x y in
+ if c = 0 then
+ compare_list f l1 l2
+ else
+ c
+
+let map_changed_default d f l =
+ let rec g = function
+ | [] -> ([],false)
+ | x::y ->
+ let (r,c) = g y in
+ match f x with
+ | None -> ((d x)::r,c)
+ | Some(x') -> (x'::r,true)
+ in
+ let (r,c) = g l in
+ if c then
+ Some(r)
+ else
+ None
+
+let map_changed f l = map_changed_default (fun x -> x) f l
+
+let rec map_filter (f : 'a -> 'b option) (l : 'a list) : 'b list =
+ match l with [] -> []
+ | x :: xs ->
+ let xs' = map_filter f xs in
+ match (f x) with None -> xs'
+ | Some x' -> x' :: xs'
+
+let list_index p l =
+ let rec aux i l =
+ match l with [] -> None
+ | (x :: xs) -> if p x then Some i else aux (i+1) xs
+ in
+ aux 0 l
+
+let option_get_exn e = function
+ | Some(o) -> o
+ | None -> raise e
+
+let option_default d = function
+ | None -> d
+ | Some(o) -> o
+
+let option_cases op f1 f2 = match op with
+ | Some(o) -> f1 o
+ | None -> f2 ()
+
+let option_map f = function
+ | None -> None
+ | Some(o) -> Some(f o)
+
+let option_bind f = function
+ | None -> None
+ | Some(o) -> f o
+
+let changed2 f g x h y =
+ match (g x, h y) with
+ | (None,None) -> None
+ | (Some(x'),None) -> Some(f x' y)
+ | (None,Some(y')) -> Some(f x y')
+ | (Some(x'),Some(y')) -> Some(f x' y')
+
+let rec map_all (f : 'a -> 'b option) (l : 'a list) : 'b list option =
+ match l with [] -> Some []
+ | x :: xs ->
+ match (f x) with None -> None
+ | Some x' -> option_map (fun xs' -> x' :: xs') (map_all f xs)
+
+let rec option_first f xL =
+ match xL with
+ [] -> None
+ | (x :: xs) -> match f x with None -> option_first f xs | Some s -> Some s
+
+let list_to_front n l =
+ if n <= 0 then l else
+ let rec aux acc n l =
+ match (n, l) with
+ (0, x::xs) -> (x :: (List.rev_append acc xs))
+ | (n, x::xs) -> aux (x :: acc) (n-1) xs
+ | (_, []) -> (* should not happen *) raise (Failure "list_to_front")
+ in aux [] n l
+
+let undo_list_to_front n l =
+ if n <= 0 then l else
+ let rec aux acc n y l =
+ match (n, l) with
+ (0, xs) -> List.rev_append acc (y::xs)
+ | (n, x::xs) -> aux (x :: acc) (n-1) y xs
+ | (_, []) -> List.rev_append acc [y]
+ in match l with [] -> l | y::xs -> aux [] n y xs
+
+let split_after n l =
+ if n < 0 then raise (Failure "negative argument to split_after") else
+ let rec aux acc n ll = match (n, ll) with
+ (0, _) -> (List.rev acc, ll)
+ | (n, x :: xs) -> aux (x :: acc) (n-1) xs
+ | _ -> raise (Failure "index too large")
+ in aux [] n l
+
+let list_mapi (f : int -> 'a -> 'b) (l : 'a list) : 'b list =
+ let rec aux f i l =
+ match l with
+ [] -> []
+ | (x :: xs) -> ((f i x) :: (aux f (i + 1) xs))
+ in
+ aux f 0 l
+
+let rec list_iter_sep (sf : unit -> unit) (f : 'a -> unit) l : unit =
+ match l with
+ | [] -> ()
+ | [x0] -> f x0
+ | (x0 :: x1 :: xs) -> (f x0; sf(); list_iter_sep sf f (x1 :: xs))
+
+let string_to_list s =
+ let rec aux i acc =
+ if i < 0 then acc
+ else aux (i-1) (s.[i] :: acc)
+ in aux (String.length s - 1) []
+
+module IntSet = Set.Make(
+ struct
+ let compare = Pervasives.compare
+ type t = int
+ end )
+
+module IntIntSet = Set.Make(
+ struct
+ let compare = Pervasives.compare
+ type t = int * int
+ end )
+
+
+module ExtraSet = functor (S : Set.S) ->
+ struct
+ let add_list s l = List.fold_left (fun s x -> S.add x s) s l
+ let from_list l = add_list S.empty l
+ let list_union l = List.fold_left S.union S.empty l
+ let list_inter = function s :: l -> List.fold_left S.inter s l
+ | [] -> raise (Failure "ExtraSet.list_inter")
+ end;;
+
+
+let copy_file src dst =
+ let len = 5096 in
+ let b = String.make len ' ' in
+ let read_len = ref 0 in
+ let i = open_in_bin src in
+ let o = open_out_bin dst in
+ while (read_len := input i b 0 len; !read_len <> 0) do
+ output o b 0 !read_len
+ done;
+ close_in i;
+ close_out o
+
+let move_file src dst =
+ if (Sys.file_exists dst) then Sys.remove dst;
+ try
+ (* try efficient version *)
+ Sys.rename src dst
+ with Sys_error _ ->
+ begin
+ (* OK, do it the the hard way *)
+ copy_file src dst;
+ Sys.remove src
+ end
+
+let same_content_files file1 file2 : bool =
+ (Sys.file_exists file1) && (Sys.file_exists file2) &&
+ begin
+ let s1 = Stream.of_channel (open_in_bin file1) in
+ let s2 = Stream.of_channel (open_in_bin file2) in
+ let stream_is_empty s = (try Stream.empty s; true with Stream.Failure -> false) in
+ try
+ while ((Stream.next s1) = (Stream.next s2)) do () done;
+ false
+ with Stream.Failure -> stream_is_empty s1 && stream_is_empty s2
+ end
+
diff --git a/src/util.mli b/src/util.mli
new file mode 100644
index 00000000..29c68a0d
--- /dev/null
+++ b/src/util.mli
@@ -0,0 +1,193 @@
+(**************************************************************************)
+(* Lem *)
+(* *)
+(* Dominic Mulligan, University of Cambridge *)
+(* Francesco Zappa Nardelli, INRIA Paris-Rocquencourt *)
+(* Gabriel Kerneis, University of Cambridge *)
+(* Kathy Gray, University of Cambridge *)
+(* Peter Boehm, University of Cambridge (while working on Lem) *)
+(* Peter Sewell, University of Cambridge *)
+(* Scott Owens, University of Kent *)
+(* Thomas Tuerk, University of Cambridge *)
+(* *)
+(* The Lem sources are copyright 2010-2013 *)
+(* by the UK authors above and Institut National de Recherche en *)
+(* Informatique et en Automatique (INRIA). *)
+(* *)
+(* All files except ocaml-lib/pmap.{ml,mli} and ocaml-libpset.{ml,mli} *)
+(* are distributed under the license below. The former are distributed *)
+(* under the LGPLv2, as in the LICENSE file. *)
+(* *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in the *)
+(* documentation and/or other materials provided with the distribution. *)
+(* 3. The names of the authors may not be used to endorse or promote *)
+(* products derived from this software without specific prior written *)
+(* permission. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS *)
+(* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *)
+(* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *)
+(* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY *)
+(* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *)
+(* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE *)
+(* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *)
+(* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER *)
+(* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR *)
+(* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN *)
+(* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *)
+(**************************************************************************)
+
+(** Mixed useful things *)
+module Duplicate(S : Set.S) : sig
+ type dups =
+ | No_dups of S.t
+ | Has_dups of S.elt
+ val duplicates : S.elt list -> dups
+end
+
+(** [remove_duplicates l] removes duplicate elements from
+ the list l. As a side-effect, the list might be reordered. *)
+val remove_duplicates : 'a list -> 'a list
+
+(** {2 Option Functions} *)
+
+(** [option_map f None] returns [None], whereas
+ [option_map f (Some x)] returns [Some (f x)]. *)
+val option_map : ('a -> 'b) -> 'a option -> 'b option
+
+(** [option_cases None f_s f_n] returns [f_n], whereas
+ [option_cases (Some x) f_s f_n] returns [f_s x]. *)
+val option_cases : 'a option -> ('a -> 'b) -> (unit -> 'b) -> 'b
+
+(** [option_bind f None] returns [None], whereas
+ [option_bind f (Some x)] returns [f x]. *)
+val option_bind : ('a -> 'b option) -> 'a option -> 'b option
+
+(** [option_default d None] returns the default value [d],
+ whereas [option_default d (Some x)] returns [x]. *)
+val option_default : 'a -> 'a option -> 'a
+
+(** [option_get_exn exn None] throws the exception [exn],
+ whereas [option_get_exn exn (Some x)] returns [x]. *)
+val option_get_exn : exn -> 'a option -> 'a
+
+(** [changed2 f g x h y] applies [g] to [x] and [h] to [y].
+ If both function applications return [None], then [None] is
+ returned. Otherwise [f] is applied to the results. For this
+ application of [f], [x] is used in case [g x] returns [None] and
+ similarly [y] in case [h y] returns [None]. *)
+val changed2 : ('a -> 'b -> 'c) -> ('a -> 'a option) -> 'a -> ('b -> 'b option) -> 'b -> 'c option
+
+
+(** {2 List Functions} *)
+
+(** [list_index p l] returns the first index [i] such that
+ the predicate [p (l!i)] holds. If no such [i] exists,
+ [None] is returned. *)
+val list_index: ('a -> bool) -> 'a list -> int option
+
+(** [option_first f l] searches for the first element [x] of [l] such
+ that the [f x] is not [None]. If such an element exists, [f x] is
+ returned, otherwise [None]. *)
+val option_first: ('a -> 'b option) -> 'a list -> 'b option
+
+(** [map_changed f l] maps [f] over [l].
+ If for all elements of [l] the
+ function [f] returns [None], then [map_changed f l] returns [None].
+ Otherwise, it uses [x] for all elements, where [f x] returns [None],
+ and returns the resulting list. *)
+val map_changed : ('a -> 'a option) -> 'a list -> 'a list option
+
+(** [map_changed_default d f l] maps [f] over [l].
+ If for all elements of [l] the
+ function [f] returns [None], then [map_changed f l] returns [None].
+ Otherwise, it uses [d x] for all elements [x], where [f x] returns [None],
+ and returns the resulting list. *)
+val map_changed_default : ('a -> 'b) -> ('a -> 'b option) -> 'a list -> 'b list option
+
+(** [list_mapi f l] maps [f] over [l]. In contrast to the standard
+ [map] function, [f] gets the current index of the list as an extra
+ argument. Counting starts at [0]. *)
+val list_mapi : (int -> 'a -> 'b) -> 'a list -> 'b list
+
+(** [list_iter sf f [a1; ...; an]] applies function [f] in turn to [a1; ...; an] and
+ calls [sf ()] in between. It is equivalent to [begin f a1; sf(); f a2; sf(); ...; f an; () end]. *)
+val list_iter_sep : (unit -> unit) -> ('a -> unit) -> 'a list -> unit
+
+(** [map_filter f l] maps [f] over [l] and removes all entries [x] of [l]
+ with [f x = None]. *)
+val map_filter : ('a -> 'b option) -> 'a list -> 'b list
+
+(** [map_all f l] maps [f] over [l]. If at least one entry is [None], [None] is returned. Otherwise,
+ the [Some] function is removed from the list. *)
+val map_all : ('a -> 'b option) -> 'a list -> 'b list option
+
+(** [list_to_front i l] resorts the list [l] by bringing the element at index [i]
+ to the front.
+ @throws Failure if [i] is not smaller than the length of [l]*)
+val list_to_front : int -> 'a list -> 'a list
+
+(** [undo_list_to_front i l] resorts the list [l] by moving the head element to index index [i]
+ It's the inverse of [list_to_front i l]. *)
+val undo_list_to_front : int -> 'a list -> 'a list
+
+(** [split_after n l] splits the first [n] elemenst from list [l], i.e. it returns two lists
+ [l1] and [l2], with [length l1 = n] and [l1 @ l2 = l]. Fails if n is too small or large. *)
+val split_after : int -> 'a list -> 'a list * 'a list
+
+val compare_list : ('a -> 'b -> int) -> 'a list -> 'b list -> int
+
+
+(** {2 Files} *)
+
+(** [copy_file src dst] copies file [src] to file [dst]. Only files are supported,
+ no directories. *)
+val copy_file : string -> string -> unit
+
+(** [move_file src dst] moves file [src] to file [dst]. In contrast to [Sys.rename] no error is
+ produced, if [dst] already exists. Moreover, in case [Sys.rename] fails for some reason (e.g. because
+ it does not work over filesystem boundaries), [copy_file] and [Sys.remove] are used as
+ fallback. *)
+val move_file : string -> string -> unit
+
+(** [same_content_files file1 file2] checks, whether the files [file1] and [file2] have the same content.
+If at least one of the files does not exist, [false] is returned. [same_content_files] throws an exception,
+if one of the files exists, but cannot be read. *)
+val same_content_files : string -> string -> bool
+
+(** {2 Strings} *)
+
+(** [string_to_list l] translates the string [l] to the list of its characters. *)
+val string_to_list : string -> char list
+
+(** {2 Useful Sets} *)
+
+(** Sets of Integers *)
+module IntSet : Set.S with type elt = int
+module IntIntSet : Set.S with type elt = int * int
+
+(** Some useful extra functions for sets *)
+module ExtraSet : functor (S : Set.S) ->
+ sig
+ (** Add a list of values to an existing set. *)
+ val add_list : S.t -> S.elt list -> S.t
+
+ (** Construct a set from a list. *)
+ val from_list : S.elt list -> S.t
+
+ (** Builds the union of a list of sets *)
+ val list_union : S.t list -> S.t
+
+ (** Builds the intersection of a list of sets.
+ If the list is empty, a match exception is thrown. *)
+ val list_inter : S.t list -> S.t
+ end
+
+