From 1d6cf2c683145b12c70251aa54d76eeb7ab6e891 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 2 Dec 2015 20:59:07 +0100 Subject: [PATCH] add `CCOrd.option` --- Makefile | 4 +- _tags | 145 ++++++++++ myocamlbuild.ml | 671 +++++++++++++++++++++++++++++++++++++++++++++ src/core/CCOrd.ml | 10 + src/core/CCOrd.mli | 4 + 5 files changed, 832 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4f0e4731..b1d6c96b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # OASIS_START -# DO NOT EDIT (digest: 9a60866e2fa295c5e33a3fe33b8f3a32) +# DO NOT EDIT (digest: 46f8bd9984975bd4727bed22d0876cd2) SETUP = ./setup.exe @@ -38,7 +38,7 @@ configure: $(SETUP) $(SETUP) -configure $(CONFIGUREFLAGS) setup.exe: setup.ml - ocamlfind ocamlopt -o $@ -linkpkg -package oasis.dynrun $< || ocamlfind ocamlc -o $@ -linkpkg -package oasis.dynrun $< || true + ocamlfind ocamlopt -o $@ $< || ocamlfind ocamlc -o $@ $< || true $(RM) setup.cmi setup.cmo setup.cmx setup.o .PHONY: build doc test all install uninstall reinstall clean distclean configure diff --git a/_tags b/_tags index a536b979..bdf2faa4 100644 --- a/_tags +++ b/_tags @@ -1,4 +1,149 @@ # OASIS_START +# DO NOT EDIT (digest: 0e7b7eeffb179d552ac9c060b7ab3be9) +# Ignore VCS directories, you can use the same kind of rule outside +# OASIS_START/STOP if you want to exclude directories that contains +# useless stuff for the build process +true: annot, bin_annot +<**/.svn>: -traverse +<**/.svn>: not_hygienic +".bzr": -traverse +".bzr": not_hygienic +".hg": -traverse +".hg": not_hygienic +".git": -traverse +".git": not_hygienic +"_darcs": -traverse +"_darcs": not_hygienic +# Library containers +"src/core/containers.cmxs": use_containers +: package(bytes) +# Library containers_io +"src/io/containers_io.cmxs": use_containers_io +: package(bytes) +# Library containers_unix +"src/unix/containers_unix.cmxs": use_containers_unix +: package(bytes) +: package(unix) +# Library containers_sexp +"src/sexp/containers_sexp.cmxs": use_containers_sexp +: package(bytes) +# Library containers_data +"src/data/containers_data.cmxs": use_containers_data +: package(bytes) +# Library containers_iter +"src/iter/containers_iter.cmxs": use_containers_iter +# Library containers_string +"src/string/containers_string.cmxs": use_containers_string +: package(bytes) +# Library containers_advanced +"src/advanced/containers_advanced.cmxs": use_containers_advanced +: package(bytes) +: package(sequence) +: use_containers +# Library containers_bigarray +"src/bigarray/containers_bigarray.cmxs": use_containers_bigarray +: package(bigarray) +: package(bytes) +: use_containers +# Library containers_thread +"src/threads/containers_thread.cmxs": use_containers_thread +: package(bytes) +: package(threads) +: use_containers +# Library containers_top +"src/top/containers_top.cmxs": use_containers_top +: package(bigarray) +: package(bytes) +: package(compiler-libs.common) +: package(unix) +: use_containers +: use_containers_bigarray +: use_containers_data +: use_containers_iter +: use_containers_sexp +: use_containers_string +: use_containers_unix +# Executable run_benchs +: package(benchmark) +: package(bytes) +: package(gen) +: package(hamt) +: package(sequence) +: package(threads) +: use_containers +: use_containers_advanced +: use_containers_data +: use_containers_iter +: use_containers_string +: use_containers_thread +: package(benchmark) +: package(gen) +: package(threads) +: use_containers_advanced +: use_containers_iter +: use_containers_string +: use_containers_thread +# Executable run_bench_hash +: package(bytes) +: use_containers +# Executable run_qtest +: package(QTest2Lib) +: package(bigarray) +: package(bytes) +: package(gen) +: package(oUnit) +: package(sequence) +: package(threads) +: package(unix) +: use_containers +: use_containers_advanced +: use_containers_bigarray +: use_containers_data +: use_containers_io +: use_containers_iter +: use_containers_sexp +: use_containers_string +: use_containers_thread +: use_containers_unix +: package(QTest2Lib) +: package(bigarray) +: package(bytes) +: package(gen) +: package(oUnit) +: package(sequence) +: package(threads) +: package(unix) +: use_containers +: use_containers_advanced +: use_containers_bigarray +: use_containers_data +: use_containers_io +: use_containers_iter +: use_containers_sexp +: use_containers_string +: use_containers_thread +: use_containers_unix +# Executable id_sexp +: package(bytes) +: use_containers_sexp +# Executable mem_measure +"benchs/mem_measure.native": package(bytes) +"benchs/mem_measure.native": package(hamt) +"benchs/mem_measure.native": package(sequence) +"benchs/mem_measure.native": package(unix) +"benchs/mem_measure.native": use_containers +"benchs/mem_measure.native": use_containers_data +: package(bytes) +: package(hamt) +: package(sequence) +: package(unix) +: use_containers +: use_containers_data +# Executable id_sexp2 +: package(bytes) +: use_containers_sexp +: package(bytes) +: use_containers_sexp # OASIS_STOP : thread : thread diff --git a/myocamlbuild.ml b/myocamlbuild.ml index a6f9fc91..b80ef8d1 100644 --- a/myocamlbuild.ml +++ b/myocamlbuild.ml @@ -1,4 +1,675 @@ (* OASIS_START *) +(* DO NOT EDIT (digest: b119194f5742ac2f3cdceac9a223dda7) *) +module OASISGettext = struct +(* # 22 "src/oasis/OASISGettext.ml" *) + + + let ns_ str = + str + + + let s_ str = + str + + + let f_ (str: ('a, 'b, 'c, 'd) format4) = + str + + + let fn_ fmt1 fmt2 n = + if n = 1 then + fmt1^^"" + else + fmt2^^"" + + + let init = + [] + + +end + +module OASISExpr = struct +(* # 22 "src/oasis/OASISExpr.ml" *) + + + + + + open OASISGettext + + + type test = string + + + type flag = string + + + type t = + | EBool of bool + | ENot of t + | EAnd of t * t + | EOr of t * t + | EFlag of flag + | ETest of test * string + + + + type 'a choices = (t * 'a) list + + + let eval var_get t = + let rec eval' = + function + | EBool b -> + b + + | ENot e -> + not (eval' e) + + | EAnd (e1, e2) -> + (eval' e1) && (eval' e2) + + | EOr (e1, e2) -> + (eval' e1) || (eval' e2) + + | EFlag nm -> + let v = + var_get nm + in + assert(v = "true" || v = "false"); + (v = "true") + + | ETest (nm, vl) -> + let v = + var_get nm + in + (v = vl) + in + eval' t + + + let choose ?printer ?name var_get lst = + let rec choose_aux = + function + | (cond, vl) :: tl -> + if eval var_get cond then + vl + else + choose_aux tl + | [] -> + let str_lst = + if lst = [] then + s_ "" + else + String.concat + (s_ ", ") + (List.map + (fun (cond, vl) -> + match printer with + | Some p -> p vl + | None -> s_ "") + lst) + in + match name with + | Some nm -> + failwith + (Printf.sprintf + (f_ "No result for the choice list '%s': %s") + nm str_lst) + | None -> + failwith + (Printf.sprintf + (f_ "No result for a choice list: %s") + str_lst) + in + choose_aux (List.rev lst) + + +end + + +# 132 "myocamlbuild.ml" +module BaseEnvLight = struct +(* # 22 "src/base/BaseEnvLight.ml" *) + + + module MapString = Map.Make(String) + + + type t = string MapString.t + + + let default_filename = + Filename.concat + (Sys.getcwd ()) + "setup.data" + + + let load ?(allow_empty=false) ?(filename=default_filename) () = + if Sys.file_exists filename then + begin + let chn = + open_in_bin filename + in + let st = + Stream.of_channel chn + in + let line = + ref 1 + in + let st_line = + Stream.from + (fun _ -> + try + match Stream.next st with + | '\n' -> incr line; Some '\n' + | c -> Some c + with Stream.Failure -> None) + in + let lexer = + Genlex.make_lexer ["="] st_line + in + let rec read_file mp = + match Stream.npeek 3 lexer with + | [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] -> + Stream.junk lexer; + Stream.junk lexer; + Stream.junk lexer; + read_file (MapString.add nm value mp) + | [] -> + mp + | _ -> + failwith + (Printf.sprintf + "Malformed data file '%s' line %d" + filename !line) + in + let mp = + read_file MapString.empty + in + close_in chn; + mp + end + else if allow_empty then + begin + MapString.empty + end + else + begin + failwith + (Printf.sprintf + "Unable to load environment, the file '%s' doesn't exist." + filename) + end + + + let rec var_expand str env = + let buff = + Buffer.create ((String.length str) * 2) + in + Buffer.add_substitute + buff + (fun var -> + try + var_expand (MapString.find var env) env + with Not_found -> + failwith + (Printf.sprintf + "No variable %s defined when trying to expand %S." + var + str)) + str; + Buffer.contents buff + + + let var_get name env = + var_expand (MapString.find name env) env + + + let var_choose lst env = + OASISExpr.choose + (fun nm -> var_get nm env) + lst +end + + +# 237 "myocamlbuild.ml" +module MyOCamlbuildFindlib = struct +(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *) + + + (** OCamlbuild extension, copied from + * http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild + * by N. Pouillard and others + * + * Updated on 2009/02/28 + * + * Modified by Sylvain Le Gall + *) + open Ocamlbuild_plugin + + type conf = + { no_automatic_syntax: bool; + } + + (* these functions are not really officially exported *) + let run_and_read = + Ocamlbuild_pack.My_unix.run_and_read + + + let blank_sep_strings = + Ocamlbuild_pack.Lexers.blank_sep_strings + + + let exec_from_conf exec = + let exec = + let env_filename = Pathname.basename BaseEnvLight.default_filename in + let env = BaseEnvLight.load ~filename:env_filename ~allow_empty:true () in + try + BaseEnvLight.var_get exec env + with Not_found -> + Printf.eprintf "W: Cannot get variable %s\n" exec; + exec + in + let fix_win32 str = + if Sys.os_type = "Win32" then begin + let buff = Buffer.create (String.length str) in + (* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'. + *) + String.iter + (fun c -> Buffer.add_char buff (if c = '\\' then '/' else c)) + str; + Buffer.contents buff + end else begin + str + end + in + fix_win32 exec + + let split s ch = + let buf = Buffer.create 13 in + let x = ref [] in + let flush () = + x := (Buffer.contents buf) :: !x; + Buffer.clear buf + in + String.iter + (fun c -> + if c = ch then + flush () + else + Buffer.add_char buf c) + s; + flush (); + List.rev !x + + + let split_nl s = split s '\n' + + + let before_space s = + try + String.before s (String.index s ' ') + with Not_found -> s + + (* ocamlfind command *) + let ocamlfind x = S[Sh (exec_from_conf "ocamlfind"); x] + + (* This lists all supported packages. *) + let find_packages () = + List.map before_space (split_nl & run_and_read (exec_from_conf "ocamlfind" ^ " list")) + + + (* Mock to list available syntaxes. *) + let find_syntaxes () = ["camlp4o"; "camlp4r"] + + + let well_known_syntax = [ + "camlp4.quotations.o"; + "camlp4.quotations.r"; + "camlp4.exceptiontracer"; + "camlp4.extend"; + "camlp4.foldgenerator"; + "camlp4.listcomprehension"; + "camlp4.locationstripper"; + "camlp4.macro"; + "camlp4.mapgenerator"; + "camlp4.metagenerator"; + "camlp4.profiler"; + "camlp4.tracer" + ] + + + let dispatch conf = + function + | After_options -> + (* By using Before_options one let command line options have an higher + * priority on the contrary using After_options will guarantee to have + * the higher priority override default commands by ocamlfind ones *) + Options.ocamlc := ocamlfind & A"ocamlc"; + Options.ocamlopt := ocamlfind & A"ocamlopt"; + Options.ocamldep := ocamlfind & A"ocamldep"; + Options.ocamldoc := ocamlfind & A"ocamldoc"; + Options.ocamlmktop := ocamlfind & A"ocamlmktop"; + Options.ocamlmklib := ocamlfind & A"ocamlmklib" + + | After_rules -> + + (* When one link an OCaml library/binary/package, one should use + * -linkpkg *) + flag ["ocaml"; "link"; "program"] & A"-linkpkg"; + + if not (conf.no_automatic_syntax) then begin + (* For each ocamlfind package one inject the -package option when + * compiling, computing dependencies, generating documentation and + * linking. *) + List.iter + begin fun pkg -> + let base_args = [A"-package"; A pkg] in + (* TODO: consider how to really choose camlp4o or camlp4r. *) + let syn_args = [A"-syntax"; A "camlp4o"] in + let (args, pargs) = + (* Heuristic to identify syntax extensions: whether they end in + ".syntax"; some might not. + *) + if Filename.check_suffix pkg "syntax" || + List.mem pkg well_known_syntax then + (syn_args @ base_args, syn_args) + else + (base_args, []) + in + flag ["ocaml"; "compile"; "pkg_"^pkg] & S args; + flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args; + flag ["ocaml"; "doc"; "pkg_"^pkg] & S args; + flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args; + flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args; + + (* TODO: Check if this is allowed for OCaml < 3.12.1 *) + flag ["ocaml"; "compile"; "package("^pkg^")"] & S pargs; + flag ["ocaml"; "ocamldep"; "package("^pkg^")"] & S pargs; + flag ["ocaml"; "doc"; "package("^pkg^")"] & S pargs; + flag ["ocaml"; "infer_interface"; "package("^pkg^")"] & S pargs; + end + (find_packages ()); + end; + + (* Like -package but for extensions syntax. Morover -syntax is useless + * when linking. *) + List.iter begin fun syntax -> + flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; + flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; + flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; + flag ["ocaml"; "infer_interface"; "syntax_"^syntax] & + S[A"-syntax"; A syntax]; + end (find_syntaxes ()); + + (* The default "thread" tag is not compatible with ocamlfind. + * Indeed, the default rules add the "threads.cma" or "threads.cmxa" + * options when using this tag. When using the "-linkpkg" option with + * ocamlfind, this module will then be added twice on the command line. + * + * To solve this, one approach is to add the "-thread" option when using + * the "threads" package using the previous plugin. + *) + flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]); + flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]); + flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]); + flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]); + flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]); + flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]); + flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]); + flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]); + + | _ -> + () +end + +module MyOCamlbuildBase = struct +(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *) + + + (** Base functions for writing myocamlbuild.ml + @author Sylvain Le Gall + *) + + + + + + open Ocamlbuild_plugin + module OC = Ocamlbuild_pack.Ocaml_compiler + + + type dir = string + type file = string + type name = string + type tag = string + + +(* # 62 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *) + + + type t = + { + lib_ocaml: (name * dir list * string list) list; + lib_c: (name * dir * file list) list; + flags: (tag list * (spec OASISExpr.choices)) list; + (* Replace the 'dir: include' from _tags by a precise interdepends in + * directory. + *) + includes: (dir * dir list) list; + } + + + let env_filename = + Pathname.basename + BaseEnvLight.default_filename + + + let dispatch_combine lst = + fun e -> + List.iter + (fun dispatch -> dispatch e) + lst + + + let tag_libstubs nm = + "use_lib"^nm^"_stubs" + + + let nm_libstubs nm = + nm^"_stubs" + + + let dispatch t e = + let env = + BaseEnvLight.load + ~filename:env_filename + ~allow_empty:true + () + in + match e with + | Before_options -> + let no_trailing_dot s = + if String.length s >= 1 && s.[0] = '.' then + String.sub s 1 ((String.length s) - 1) + else + s + in + List.iter + (fun (opt, var) -> + try + opt := no_trailing_dot (BaseEnvLight.var_get var env) + with Not_found -> + Printf.eprintf "W: Cannot get variable %s\n" var) + [ + Options.ext_obj, "ext_obj"; + Options.ext_lib, "ext_lib"; + Options.ext_dll, "ext_dll"; + ] + + | After_rules -> + (* Declare OCaml libraries *) + List.iter + (function + | nm, [], intf_modules -> + ocaml_lib nm; + let cmis = + List.map (fun m -> (String.uncapitalize m) ^ ".cmi") + intf_modules in + dep ["ocaml"; "link"; "library"; "file:"^nm^".cma"] cmis + | nm, dir :: tl, intf_modules -> + ocaml_lib ~dir:dir (dir^"/"^nm); + List.iter + (fun dir -> + List.iter + (fun str -> + flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir])) + ["compile"; "infer_interface"; "doc"]) + tl; + let cmis = + List.map (fun m -> dir^"/"^(String.uncapitalize m)^".cmi") + intf_modules in + dep ["ocaml"; "link"; "library"; "file:"^dir^"/"^nm^".cma"] + cmis) + t.lib_ocaml; + + (* Declare directories dependencies, replace "include" in _tags. *) + List.iter + (fun (dir, include_dirs) -> + Pathname.define_context dir include_dirs) + t.includes; + + (* Declare C libraries *) + List.iter + (fun (lib, dir, headers) -> + (* Handle C part of library *) + flag ["link"; "library"; "ocaml"; "byte"; tag_libstubs lib] + (S[A"-dllib"; A("-l"^(nm_libstubs lib)); A"-cclib"; + A("-l"^(nm_libstubs lib))]); + + flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib] + (S[A"-cclib"; A("-l"^(nm_libstubs lib))]); + + flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib] + (S[A"-dllib"; A("dll"^(nm_libstubs lib))]); + + (* When ocaml link something that use the C library, then one + need that file to be up to date. + This holds both for programs and for libraries. + *) + dep ["link"; "ocaml"; tag_libstubs lib] + [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)]; + + dep ["compile"; "ocaml"; tag_libstubs lib] + [dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)]; + + (* TODO: be more specific about what depends on headers *) + (* Depends on .h files *) + dep ["compile"; "c"] + headers; + + (* Setup search path for lib *) + flag ["link"; "ocaml"; "use_"^lib] + (S[A"-I"; P(dir)]); + ) + t.lib_c; + + (* Add flags *) + List.iter + (fun (tags, cond_specs) -> + let spec = BaseEnvLight.var_choose cond_specs env in + let rec eval_specs = + function + | S lst -> S (List.map eval_specs lst) + | A str -> A (BaseEnvLight.var_expand str env) + | spec -> spec + in + flag tags & (eval_specs spec)) + t.flags + | _ -> + () + + + let dispatch_default conf t = + dispatch_combine + [ + dispatch t; + MyOCamlbuildFindlib.dispatch conf; + ] + + +end + + +# 606 "myocamlbuild.ml" +open Ocamlbuild_plugin;; +let package_default = + { + MyOCamlbuildBase.lib_ocaml = + [ + ("containers", ["src/core"], []); + ("containers_io", ["src/io"], []); + ("containers_unix", ["src/unix"], []); + ("containers_sexp", ["src/sexp"], []); + ("containers_data", ["src/data"], []); + ("containers_iter", ["src/iter"], []); + ("containers_string", ["src/string"], []); + ("containers_advanced", ["src/advanced"], []); + ("containers_bigarray", ["src/bigarray"], []); + ("containers_thread", ["src/threads"], []); + ("containers_top", ["src/top"], []) + ]; + lib_c = []; + flags = []; + includes = + [ + ("src/top", + [ + "src/bigarray"; + "src/core"; + "src/data"; + "src/iter"; + "src/sexp"; + "src/string"; + "src/unix" + ]); + ("src/threads", ["src/core"]); + ("src/bigarray", ["src/core"]); + ("src/advanced", ["src/core"]); + ("qtest", + [ + "src/advanced"; + "src/bigarray"; + "src/core"; + "src/data"; + "src/io"; + "src/iter"; + "src/sexp"; + "src/string"; + "src/threads"; + "src/unix" + ]); + ("examples", ["src/sexp"]); + ("benchs", + [ + "src/advanced"; + "src/core"; + "src/data"; + "src/iter"; + "src/string"; + "src/threads" + ]) + ] + } + ;; + +let conf = {MyOCamlbuildFindlib.no_automatic_syntax = false} + +let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;; + +# 673 "myocamlbuild.ml" (* OASIS_STOP *) let doc_intro = "doc/intro.txt" diff --git a/src/core/CCOrd.ml b/src/core/CCOrd.ml index 4f2ace2a..f1c974b3 100644 --- a/src/core/CCOrd.ml +++ b/src/core/CCOrd.ml @@ -59,6 +59,16 @@ let () c (ord,x,y) = then ord x y else c +let option c o1 o2 = match o1, o2 with + | None, None -> 0 + | None, Some _ -> -1 + | Some _, None -> 1 + | Some x1, Some x2 -> c x1 x2 + +(*$Q + Q.(option int) (fun o -> option int_ None o <= 0) + *) + let pair o_x o_y (x1,y1) (x2,y2) = let c = o_x x1 x2 in if c = 0 diff --git a/src/core/CCOrd.mli b/src/core/CCOrd.mli index 52dae3b7..39949131 100644 --- a/src/core/CCOrd.mli +++ b/src/core/CCOrd.mli @@ -55,6 +55,10 @@ val () : int -> ('a t * 'a * 'a) -> int (CCBool.compare, true, false)]} *) +val option : 'a t -> 'a option t +(** Comparison of optional values. [None] is smaller than any [Some _]. + @since NEXT_RELEASE *) + val pair : 'a t -> 'b t -> ('a * 'b) t val triple : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t